curator-master/curator-x-discovery/src/main/java/org/apache/curator/x/discovery/ServiceInstanceBuilder.java
/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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 org.apache.curator.x.discovery;

import com.google.common.collect.Lists;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.SocketException;
import java.util.Collection;
import java.util.Enumeration;
import java.util.List;
import java.util.concurrent.atomic.AtomicReference;

/**
 * Builder for service instances
 */
public class ServiceInstanceBuilder<T> {
    private T payload;
    private String name;
    private String address;
    private Integer port;
    private Integer sslPort;
    private String id;
    private long registrationTimeUTC;
    private ServiceType serviceType = ServiceType.DYNAMIC;
    private UriSpec uriSpec;
    private boolean enabled = true;

    private static final AtomicReference<LocalIpFilter> localIpFilter =
            new AtomicReference<LocalIpFilter>(new LocalIpFilter() {
                @Override
                public boolean use(NetworkInterface nif, InetAddress adr) throws SocketException {
                    return (adr != null)
                            && !adr.isLoopbackAddress()
                            && (nif.isPointToPoint() || !adr.isLinkLocalAddress());
                }
            });

    /**
     * Replace the default local ip filter used by {@link #getAllLocalIPs()}
     *
     * @param newLocalIpFilter the new local ip filter
     */
    public static void setLocalIpFilter(LocalIpFilter newLocalIpFilter) {
        localIpFilter.set(newLocalIpFilter);
    }

    /**
     * Return the current local ip filter used by {@link #getAllLocalIPs()}
     *
     * @return ip filter
     */
    public static LocalIpFilter getLocalIpFilter() {
        return localIpFilter.get();
    }

    ServiceInstanceBuilder() {}

    /**
     * Return a new instance with the currently set values
     *
     * @return instance
     */
    public ServiceInstance<T> build() {
        return new ServiceInstance<T>(
                name, id, address, port, sslPort, payload, registrationTimeUTC, serviceType, uriSpec, enabled);
    }

    public ServiceInstanceBuilder<T> name(String name) {
        this.name = name;
        return this;
    }

    public ServiceInstanceBuilder<T> address(String address) {
        this.address = address;
        return this;
    }

    public ServiceInstanceBuilder<T> id(String id) {
        this.id = id;
        return this;
    }

    public ServiceInstanceBuilder<T> port(int port) {
        this.port = port;
        return this;
    }

    public ServiceInstanceBuilder<T> sslPort(int port) {
        this.sslPort = port;
        return this;
    }

    public ServiceInstanceBuilder<T> payload(T payload) {
        this.payload = payload;
        return this;
    }

    public ServiceInstanceBuilder<T> serviceType(ServiceType serviceType) {
        this.serviceType = serviceType;
        return this;
    }

    public ServiceInstanceBuilder<T> registrationTimeUTC(long registrationTimeUTC) {
        this.registrationTimeUTC = registrationTimeUTC;
        return this;
    }

    public ServiceInstanceBuilder<T> uriSpec(UriSpec uriSpec) {
        this.uriSpec = uriSpec;
        return this;
    }

    public ServiceInstanceBuilder<T> enabled(boolean enabled) {
        this.enabled = enabled;
        return this;
    }

    /**
     * based on http://pastebin.com/5X073pUc
     * <p>
     *
     * Returns all available IP addresses.
     * <p>
     * In error case or if no network connection is established, we return
     * an empty list here.
     * <p>
     * Loopback addresses are excluded - so 127.0.0.1 will not be never
     * returned.
     * <p>
     * The "primary" IP might not be the first one in the returned list.
     *
     * @return  Returns all IP addresses (can be an empty list in error case
     *          or if network connection is missing).
     * @since   0.1.0
     * @throws SocketException errors
     */
    public static Collection<InetAddress> getAllLocalIPs() throws SocketException {
        List<InetAddress> listAdr = Lists.newArrayList();
        Enumeration<NetworkInterface> nifs = NetworkInterface.getNetworkInterfaces();
        if (nifs == null) return listAdr;

        while (nifs.hasMoreElements()) {
            NetworkInterface nif = nifs.nextElement();
            // We ignore subinterfaces - as not yet needed.

            Enumeration<InetAddress> adrs = nif.getInetAddresses();
            while (adrs.hasMoreElements()) {
                InetAddress adr = adrs.nextElement();
                if (localIpFilter.get().use(nif, adr)) {
                    listAdr.add(adr);
                }
            }
        }
        return listAdr;
    }
}
