// Path: elastic-config-core/src/main/java/com/github/config/exception/RegisterExceptionHandler.java
// @Slf4j
// @NoArgsConstructor(access = AccessLevel.PRIVATE)
// public final class RegisterExceptionHandler {
// 
//     /**
//      * 处理掉中断和连接失效异常并继续抛出RegisterException.
//      * 
//      * @param cause 待处理的异常.
//      */
//     public static void handleException(final Exception cause) {
//         if (isIgnoredException(cause) || isIgnoredException(cause.getCause())) {
//             log.debug("Elastic config: ignored exception for: {}", cause.getMessage());
//         }
//         else if (cause instanceof InterruptedException) {
//             Thread.currentThread().interrupt();
//         }
//         else {
//             throw new RegisterException(cause);
//         }
//     }
// 
//     private static boolean isIgnoredException(final Throwable cause) {
//         return null != cause
//             && (cause instanceof ConnectionLossException || cause instanceof NoNodeException || cause instanceof NodeExistsException);
//     }
// }


import java.io.File;
import java.io.IOException;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;
import org.apache.curator.test.TestingServer;
import com.github.config.exception.RegisterExceptionHandler;
package com.github.config.register.zookeeper;





/**
 * 内嵌的Zookeeper服务器.
 * <p>
 * 可以根据不同的端口号启动多个Zookeeper服务. 但每个相同的端口号共用一个服务实例.
 * </p>
 * 
 * @author ZhangWei
 */
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public final class NestedZookeeperServers {

    private static NestedZookeeperServers instance = new NestedZookeeperServers();

    private static ConcurrentMap<Integer, TestingServer> nestedServers = new ConcurrentHashMap<>();

    /**
     * 获取单例实例.
     * 
     * @return 单例实例
     */
    public static NestedZookeeperServers getInstance() {
        return instance;
    }

    /**
     * 启动内嵌的Zookeeper服务.
     * 
     * @param port 端口号
     *            <p>
     *            如果该端口号的Zookeeper服务未启动, 则启动服务. 如果该端口号的Zookeeper服务已启动, 则不做任何操作.
     *            </p>
     */
    public synchronized void startServerIfNotStarted(final int port, final String dataDir) {
        if (!nestedServers.containsKey(port)) {
            TestingServer testingServer = null;
            try {
                testingServer = new TestingServer(port, new File(dataDir));
            }
            catch (final Exception ex) {
// Path: elastic-config-core/src/main/java/com/github/config/exception/RegisterExceptionHandler.java
// @Slf4j
// @NoArgsConstructor(access = AccessLevel.PRIVATE)
// public final class RegisterExceptionHandler {
// 
//     /**
//      * 处理掉中断和连接失效异常并继续抛出RegisterException.
//      * 
//      * @param cause 待处理的异常.
//      */
//     public static void handleException(final Exception cause) {
//         if (isIgnoredException(cause) || isIgnoredException(cause.getCause())) {
//             log.debug("Elastic config: ignored exception for: {}", cause.getMessage());
//         }
//         else if (cause instanceof InterruptedException) {
//             Thread.currentThread().interrupt();
//         }
//         else {
//             throw new RegisterException(cause);
//         }
//     }
// 
//     private static boolean isIgnoredException(final Throwable cause) {
//         return null != cause
//             && (cause instanceof ConnectionLossException || cause instanceof NoNodeException || cause instanceof NodeExistsException);
//     }
// }


// Path: elastic-config-core/src/main/java/com/github/config/register/zookeeper/NestedZookeeperServers.java
import java.io.File;
import java.io.IOException;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;
import org.apache.curator.test.TestingServer;
import com.github.config.exception.RegisterExceptionHandler;

package com.github.config.register.zookeeper;





/**
 * 内嵌的Zookeeper服务器.
 * <p>
 * 可以根据不同的端口号启动多个Zookeeper服务. 但每个相同的端口号共用一个服务实例.
 * </p>
 * 
 * @author ZhangWei
 */
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public final class NestedZookeeperServers {

    private static NestedZookeeperServers instance = new NestedZookeeperServers();

    private static ConcurrentMap<Integer, TestingServer> nestedServers = new ConcurrentHashMap<>();

    /**
     * 获取单例实例.
     * 
     * @return 单例实例
     */
    public static NestedZookeeperServers getInstance() {
        return instance;
    }

    /**
     * 启动内嵌的Zookeeper服务.
     * 
     * @param port 端口号
     *            <p>
     *            如果该端口号的Zookeeper服务未启动, 则启动服务. 如果该端口号的Zookeeper服务已启动, 则不做任何操作.
     *            </p>
     */
    public synchronized void startServerIfNotStarted(final int port, final String dataDir) {
        if (!nestedServers.containsKey(port)) {
            TestingServer testingServer = null;
            try {
                testingServer = new TestingServer(port, new File(dataDir));
            }
            catch (final Exception ex) {
                RegisterExceptionHandler.handleException(ex);