Package com.groupon.odo.proxylib

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

/*
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.EndpointOverride;
import com.groupon.odo.proxylib.models.Group;
import com.groupon.odo.proxylib.models.Method;
import com.groupon.odo.proxylib.models.Script;
import com.groupon.odo.proxylib.models.ServerGroup;
import com.groupon.odo.proxylib.models.ServerRedirect;
import com.groupon.odo.proxylib.models.backup.Backup;
import com.groupon.odo.proxylib.models.backup.Profile;

import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.conn.ssl.TrustStrategy;
import org.apache.http.conn.ssl.X509HostnameVerifier;
import org.codehaus.jackson.map.ObjectMapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.InputStream;
import java.net.InetAddress;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Set;

import javax.management.MBeanServer;
import javax.management.MBeanServerFactory;
import javax.management.ObjectName;
import javax.net.ssl.HostnameVerifier;

@SuppressWarnings("deprecation")
public class BackupService {
    private static final Logger logger = LoggerFactory.getLogger(BackupService.class);
    private static BackupService serviceInstance = null;

    public BackupService() {

    }

    public static BackupService getInstance() {
        if (serviceInstance == null) {
            serviceInstance = new BackupService();
        }
        return serviceInstance;
    }

    /**
     * Get all Groups
     *
     * @return
     * @throws Exception
     */
    private List<Group> getGroups() throws Exception {
        List<Group> groups = new ArrayList<Group>();
        List<Group> sourceGroups = PathOverrideService.getInstance().findAllGroups();

        // loop through the groups
        for (Group sourceGroup : sourceGroups) {
            Group group = new Group();

            // add all methods
            ArrayList<Method> methods = new ArrayList<Method>();
            for (Method sourceMethod : EditService.getInstance().getMethodsFromGroupId(sourceGroup.getId(), null)) {
                Method method = new Method();
                method.setClassName(sourceMethod.getClassName());
                method.setMethodName(sourceMethod.getMethodName());
                methods.add(method);
            }

            group.setMethods(methods);
            group.setName(sourceGroup.getName());
            groups.add(group);
        }

        return groups;
    }

    private List<Profile> getProfiles() throws Exception {
        ArrayList<Profile> profiles = new ArrayList<Profile>();

        for (com.groupon.odo.proxylib.models.Profile sourceProfile : ProfileService.getInstance().findAllProfiles()) {
            Profile profile = new Profile();
            profile.setName(sourceProfile.getName());

            // get paths
            profile.setPaths(PathOverrideService.getInstance().getPaths(sourceProfile.getId(), Constants.PROFILE_CLIENT_DEFAULT_ID, null));

            // get default servers
            profile.setServers(ServerRedirectService.getInstance().tableServers(sourceProfile.getId(), 0));

            //get server groups
            profile.setServerGroups(ServerRedirectService.getInstance().tableServerGroups(sourceProfile.getId()));

            // set active
            profile.setActive(ProfileService.getInstance().isActive(sourceProfile.getId()));
            profiles.add(profile);
        }
        return profiles;
    }

    /**
     * Return the structured backup data
     *
     * @return
     * @throws Exception
     */
    public Backup getBackupData() throws Exception {
        Backup backupData = new Backup();

        backupData.setGroups(getGroups());
        backupData.setProfiles(getProfiles());
        ArrayList<Script> scripts = new ArrayList<Script>();
        Collections.addAll(scripts, ScriptService.getInstance().getScripts());
        backupData.setScripts(scripts);

        return backupData;
    }

    /**
     * Restore configuration from backup data
     *
     * @param streamData
     * @return
     */
    public boolean restoreBackupData(InputStream streamData) {
        // convert stream to string
        java.util.Scanner s = new java.util.Scanner(streamData).useDelimiter("\\A");
        String data = s.hasNext() ? s.next() : "";

        // parse JSON
        ObjectMapper mapper = new ObjectMapper();
        Backup backupData = null;
        try {
            backupData = mapper.readValue(data, Backup.class);
        } catch (Exception e) {
            logger.error("Could not parse input data: {}, {}", e.getClass(), e.getMessage());
            return false;
        }

        // TODO: validate json against a schema for safety

        // GROUPS
        try {
            logger.info("Number of groups: {}", backupData.getGroups().size());

            for (Group group : backupData.getGroups()) {
                // determine if group already exists.. if not then add it
                Integer groupId = PathOverrideService.getInstance().getGroupIdFromName(group.getName());
                if (groupId == null)
                    groupId = PathOverrideService.getInstance().addGroup(group.getName());

                // get all methods from the group.. we are going to remove ones that don't exist in the new configuration
                List<Method> originalMethods = EditService.getInstance().getMethodsFromGroupId(groupId, null);

                for (Method originalMethod : originalMethods) {
                    Boolean matchInImportGroup = false;

                    int importCount = 0;
                    for (Method importMethod : group.getMethods()) {
                        if (originalMethod.getClassName().equals(importMethod.getClassName()) &&
                                originalMethod.getMethodName().equals(importMethod.getMethodName())) {
                            matchInImportGroup = true;
                            break;
                        }
                        importCount++;
                    }

                    if (!matchInImportGroup) {
                        // remove it from current database since it is a delta to the current import
                        PathOverrideService.getInstance().removeOverride(originalMethod.getId());
                    } else {
                        // remove from import list since it already exists
                        group.getMethods().remove(importCount);
                    }
                }

                // add methods to groups
                for (Method method : group.getMethods()) {
                    PathOverrideService.getInstance().createOverride(groupId, method.getMethodName(), method.getClassName());
                }
            }
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        // PROFILES
        try {
            logger.info("Number of profiles: {}", backupData.getProfiles().size());

            // remove all servers
            // don't care about deltas here.. we'll just recreate them all
            // removed default servers (belong to group id=0)
            ServerRedirectService.getInstance().deleteServerGroup(0);

            for (com.groupon.odo.proxylib.models.backup.Profile profile : backupData.getProfiles()) {
                // see if a profile with this name already exists
                Integer profileId = ProfileService.getInstance().getIdFromName(profile.getName());
                com.groupon.odo.proxylib.models.Profile newProfile;
                if (profileId == null) {
                    // create new profile
                    newProfile = ProfileService.getInstance().add(profile.getName());
                } else {
                    // get the existing profile
                    newProfile = ProfileService.getInstance().findProfile(profileId);
                }

                // add new servers
                if (profile.getServers() != null) {
                    for (ServerRedirect server : profile.getServers()) {
                        ServerRedirectService.getInstance().addServerRedirect(server.getRegion(), server.getSrcUrl(), server.getDestUrl(), server.getHostHeader(), newProfile.getId(), 0);
                    }
                }

                // remove all server groups
                for (ServerGroup group : ServerRedirectService.getInstance().tableServerGroups(newProfile.getId())) {
                    ServerRedirectService.getInstance().deleteServerGroup(group.getId());
                }

                // add new server groups
                if (profile.getServerGroups() != null) {
                    for (ServerGroup group : profile.getServerGroups()) {
                        int groupId = ServerRedirectService.getInstance().addServerGroup(group.getName(), newProfile.getId());
                        for (ServerRedirect server : group.getServers()) {
                            ServerRedirectService.getInstance().addServerRedirect(server.getRegion(), server.getSrcUrl(), server.getDestUrl(), server.getHostHeader(), newProfile.getId(), groupId);
                        }
                    }
                }

                // remove all paths
                // don't care about deltas here.. we'll just recreate them all
                for (EndpointOverride path : PathOverrideService.getInstance().getPaths(newProfile.getId(), Constants.PROFILE_CLIENT_DEFAULT_ID, null)) {
                    PathOverrideService.getInstance().removePath(path.getPathId());
                }

                // add new paths
                if (profile.getPaths() != null) {
                    for (EndpointOverride path : profile.getPaths()) {
                        int pathId = PathOverrideService.getInstance().addPathnameToProfile(newProfile.getId(), path.getPathName(), path.getPath());

                        PathOverrideService.getInstance().setContentType(pathId, path.getContentType());
                        PathOverrideService.getInstance().setRequestType(pathId, path.getRequestType());
                        PathOverrideService.getInstance().setGlobal(pathId, path.getGlobal());

                        // add groups to path
                        for (String groupName : path.getGroupNames()) {
                            int groupId = PathOverrideService.getInstance().getGroupIdFromName(groupName);
                            PathOverrideService.getInstance().AddGroupByNumber(newProfile.getId(), pathId, groupId);
                        }
                    }
                }

                // set active
                ClientService.getInstance().updateActive(newProfile.getId(), Constants.PROFILE_CLIENT_DEFAULT_ID, profile.getActive());
            }
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        // SCRIPTS
        try {
            // delete all scripts
            for (Script script : ScriptService.getInstance().getScripts()) {
                ScriptService.getInstance().removeScript(script.getId());
            }

            // add scripts
            for (Script script : backupData.getScripts()) {
                ScriptService.getInstance().addScript(script.getName(), script.getScript());
            }
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        // tell http/https proxies to reload plugins
        try {
            org.apache.http.conn.ssl.SSLSocketFactory sslsf = new org.apache.http.conn.ssl.SSLSocketFactory(new TrustStrategy() {
                @Override
                public boolean isTrusted(
                        final X509Certificate[] chain, String authType) throws CertificateException {
                    // ignore SSL cert issues
                    return true;
                }

            });
            HostnameVerifier hostnameVerifier = org.apache.http.conn.ssl.SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER;
            sslsf.setHostnameVerifier((X509HostnameVerifier) hostnameVerifier);
            for (String connectstring : getConnectorStrings("https_proxy")) {
                HttpGet request = new HttpGet(connectstring + "/proxy/reload");


                HttpClient httpClient = new org.apache.http.impl.client.DefaultHttpClient();
                String[] parts = connectstring.split(":");
                httpClient.getConnectionManager().getSchemeRegistry().register(new org.apache.http.conn.scheme.Scheme("https", Integer.parseInt(parts[parts.length - 1]), sslsf));
                HttpResponse response = httpClient.execute(request);
            }
        } catch (Exception e) {
            e.printStackTrace();
            logger.info("Exception caught during proxy reload.  Things may be in an inconsistent state.");
        }

        // restart plugin service for this process
        PluginManager.destroy();

        return true;
    }

    /**
     * Returns an MBeanServer with the specified name
     *
     * @param name
     * @return
     */
    private MBeanServer getServerForName(String name) {
        try {
            MBeanServer mbeanServer = null;
            final ObjectName objectNameQuery = new ObjectName(name + ":type=Service,*");

            for (final MBeanServer server : MBeanServerFactory.findMBeanServer(null)) {
                if (server.queryNames(objectNameQuery, null).size() > 0) {
                    mbeanServer = server;
                    // we found it, bail out
                    break;
                }
            }

            return mbeanServer;
        } catch (Exception e) {
        }

        return null;
    }

    /**
     * Get a list of strings(scheme + host + port) that the specified connector is running on
     *
     * @param name
     * @return
     */
    private ArrayList<String> getConnectorStrings(String name) {
        ArrayList<String> connectorStrings = new ArrayList<String>();

        try {
            MBeanServer mbeanServer = getServerForName(name);
            Set<ObjectName> objs = mbeanServer.queryNames(new ObjectName("*:type=Connector,*"), null);
            String hostname = InetAddress.getLocalHost().getHostName();
            InetAddress[] addresses = InetAddress.getAllByName(hostname);

            for (Iterator<ObjectName> i = objs.iterator(); i.hasNext(); ) {
                ObjectName obj = i.next();
                String scheme = mbeanServer.getAttribute(obj, "scheme").toString();
                String port = obj.getKeyProperty("port");
                connectorStrings.add(scheme + "://localhost:" + port);
                logger.info("Adding: {}", scheme + "://localhost:" + port);
            }
        } catch (Exception e) {
        }

        return connectorStrings;
    }
}
TOP

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

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.