Package com.github.couchapptakeout

Source Code of com.github.couchapptakeout.DefaultCouchManager

/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/

package com.github.couchapptakeout;

import com.github.couchapptakeout.events.ExitApplicationMessage;
import com.github.couchapptakeout.events.utils.Unzipper;
import java.io.File;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.ServerSocket;
import java.net.URL;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.apache.commons.lang.SystemUtils;
import org.bushe.swing.event.EventBus;
import org.bushe.swing.event.EventSubscriber;
import org.ektorp.CouchDbConnector;
import org.ektorp.CouchDbInstance;
import org.ektorp.http.HttpClient;
import org.ektorp.http.StdHttpClient;
import org.ektorp.impl.StdCouchDbConnector;
import org.ektorp.impl.StdCouchDbInstance;
import org.ini4j.Wini;

/**
*
* @author ryan.ramage
*/
public class DefaultCouchManager implements LocalCouch{


    private static String COUCH_DIR = "couch";
    private int localCouchPort = 5984;
    private CouchDownloader couchDownloader;
    private Unzipper unzipper;
    private int cachedCouchPort = 5984;
    private String username = null;
    private String password = null;
    private boolean couchStarted = false;


    public void setCouchDownloader(CouchDownloader couchDownloader) {
        this.couchDownloader = couchDownloader;
    }

    public void setUnzipper(Unzipper unzipper) {
        this.unzipper = unzipper;
    }

    public void setLocalCouchPort(int localCouchPort) {
        this.localCouchPort = localCouchPort;
    }

    @Override
    public int getCouchPort() {
        return cachedCouchPort;
    }


    @Override
    public synchronized CouchDbInstance getCouchInstance() throws CouchDBNotFoundException {
        // check if we already have a embedded couch setup, if yes startEmbeded
        if (haveEmbeddedCouch()) {

            if (isLocalCouchRunning()) {
                setupShutdownHook();
                return getLocalCouchInstance();
            }

            if (!couchStarted) {
                String exe = getCouchExe();
                CouchRunner runner = new CouchRunner(exe);
                if (!SystemUtils.IS_OS_WINDOWS) {
                    runner.setWorkingDir(new File(getWorkingDir(), COUCH_DIR));
                }
                new Thread(runner).start();
                couchStarted = true;
                setupShutdownHookForLocal();
            }
            // wait for couch
            return waitForEmbeddedCouch();
        }
        // check for local couch on 5984, use that
        if (isLocalCouchRunning()) {
            setupShutdownHook();
            return getLocalCouchInstance();
        }
        // no luck
        throw new CouchDBNotFoundException();
               
    }

    protected void setupShutdownHookForLocal() {
       // create a annon listener
        EventBus.subscribeStrongly(ExitApplicationMessage.class, new EventSubscriber<ExitApplicationMessage>() {
            @Override
            public void onEvent(ExitApplicationMessage t) {
                System.out.println("Exiting Local DB");
                // wait for the local db to shutdown
                for (int i=0; i < 4; i++) {
                    try {
                        Thread.sleep(1000);
                        if (!isLocalCouchRunning()) {
                            System.out.println("Local couch shutdown successfully");
                            break;
                        } else {
                            System.out.println("Waiting for local couch to shutdown");
                        }
                    } catch (Exception e) {}

                }
                EventBus.publish(new ShutDownMessage());
            }
        });
    }

   
    protected void setupShutdownHook() {
        // create a annon listener
        EventBus.subscribeStrongly(ExitApplicationMessage.class, new EventSubscriber<ExitApplicationMessage>() {
            @Override
            public void onEvent(ExitApplicationMessage t) {
                System.out.println("Exiting Local DB");
                EventBus.publish(new ShutDownMessage());
            }
        });
    }


    @Override
    public void installCouchDbEmbedded() throws CouchDbInstallException {
        try {
            // download couchdb for os
            File couchZip = couchDownloader.downloadLatestCouch(getWorkingDir());

            File couchDir = new File(getWorkingDir(), COUCH_DIR);

            unzipper.doUnzip(couchZip, couchDir);

            // find a random port
            int port = findFreePort();
            // set random port in ini
            String iniFile = getCouchIniLocation();
            setEmbeddedCouchPort(iniFile, port);
        } catch (IOException ex) {
            Logger.getLogger(DefaultCouchManager.class.getName()).log(Level.SEVERE, null, ex);
            throw new CouchDbInstallException(ex.getMessage());
        }
    }

    @Override
    public CouchDbConnector getCouchConnector(String name, CouchDbInstance instance) {
        return  new StdCouchDbConnector(name, instance);
    }

    public static File getWorkingDir() {
       String userHome = System.getProperty("user.home");
       File homeDir = new File(userHome, ".couchapptakeout");
       if (!homeDir.exists()) {
           homeDir.mkdirs();
       }
       return homeDir;
    }

   
    public boolean haveEmbeddedCouch() {
        File workDir = getWorkingDir();
        File couchdir = new File(workDir, COUCH_DIR);
        if (couchdir.exists()) return true;
        return false;
    }








    public static int findFreePort() throws IOException {
      ServerSocket server = new ServerSocket(0);
      int port = server.getLocalPort();
      server.close();
      return port;
    }

    public CouchDbInstance getLocalCouchInstance() {
        this.cachedCouchPort = localCouchPort;
         StdHttpClient.Builder builder =  new StdHttpClient.Builder()
                                    .host("localhost")
                                    .port(localCouchPort);
         if (username != null) {
             builder.username(username);
             builder.password(password);
         }
        

         HttpClient httpClient = builder.build();
        return new StdCouchDbInstance(httpClient);
    }

    private String getCouchExe() {
        File workDir = getWorkingDir();
        File couchdir = new File(workDir, COUCH_DIR);
        if (SystemUtils.IS_OS_WINDOWS) {
            File couchdbBinDir = new File(couchdir, OSUtils.getCouchBinLocation());
            return couchdbBinDir.getAbsolutePath();
        } else {
            return OSUtils.getCouchBinLocation();
        }
    }

    private String getCouchIniLocation() {
        File workDir = getWorkingDir();
        File couchdir = new File(workDir, COUCH_DIR);
        File localIni = new File(couchdir, OSUtils.getCouchIniLocation());
        return localIni.getAbsolutePath();
    }

    public CouchDbInstance getEmbeddedCouchInstance() throws IOException {
        String ini = getCouchIniLocation();
        int port = getEmbeddedCouchPort(ini);
        this.cachedCouchPort = port;
        StdHttpClient.Builder builder = new StdHttpClient.Builder()
                                    .host("localhost")
                                    .port(port);
        if (username != null) {
            builder.username(username);
            builder.password(password);
        }
        HttpClient httpClient  = builder.build();
        return new StdCouchDbInstance(httpClient);
    }


    protected int getEmbeddedCouchPort(String localIniFile) throws IOException {
        Wini ini = new Wini(new File(localIniFile));
        int port = ini.get("httpd", "port", int.class);
        return port;
    }

    protected void setEmbeddedCouchPort(String localIniFile, int port) throws IOException {
        Wini ini = new Wini(new File(localIniFile));
        ini.put("httpd", "port", port);
        // side effects!!! need to ensure bind address is 127.0.0.1, add lucene
        ini.put("httpd", "bind_address", "127.0.0.1");
        ini.put("httpd_global_handlers", "_fti", "{couch_httpd_proxy, handle_proxy_req, <<\"http://127.0.0.1:5985\">>}");



        ini.store();
    }


    private CouchDbInstance waitForEmbeddedCouch() {
        for (int i =0; i < 4; i++) {
            try {
                if (isEmbeddedCouchRunning()) {
                    return getEmbeddedCouchInstance();
                }
                Thread.sleep(2100);
            } catch (Exception ex) {
                Logger.getLogger(DefaultCouchManager.class.getName()).log(Level.SEVERE, null, ex);
            }
        }
        return null;
    }

    public boolean isLocalCouchRunning() {
        CouchDbInstance instance = getLocalCouchInstance();
        return isCouchInstanceUp(instance);

    }

    private boolean isEmbeddedCouchRunning() throws IOException {
        CouchDbInstance instance = getEmbeddedCouchInstance();
        return isCouchInstanceUp(instance);
    }

    private boolean isCouchInstanceUp(CouchDbInstance dbInstance) {
        try {
            List<String> names = dbInstance.getAllDatabases();
            if (names != null && names.size() > 0) {
                return true;
            }
        } catch (Exception e) {}
        return false;
    }

    @Override
    public void setCredentials(String username, String password) {
        this.username = username;
        this.password = password;
    }


}
TOP

Related Classes of com.github.couchapptakeout.DefaultCouchManager

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.