package edu.uw.zookeeper.net.intravm; import static com.google.common.base.Preconditions.checkArgument; import java.net.SocketAddress; import net.engio.mbassy.common.IConcurrentSet; import net.engio.mbassy.common.WeakConcurrentSet; import com.google.common.base.Function; import com.google.common.util.concurrent.Futures; import com.google.common.util.concurrent.ListenableFuture; import edu.uw.zookeeper.common.Factory; import edu.uw.zookeeper.common.Pair; import edu.uw.zookeeper.common.ParameterizedFactory; import edu.uw.zookeeper.net.ClientConnectionFactory; import edu.uw.zookeeper.net.Connection; public class IntraVmClientConnectionFactory<I,O,U,V, T extends AbstractIntraVmEndpoint<I,O,U,V>, C extends Connection<?,?,?>> extends IntraVmConnectionFactory<I,O,U,V,T,C> implements ClientConnectionFactory<C> { public static <I,O,U,V, T extends AbstractIntraVmEndpoint<I,O,U,V>, C extends Connection<?,?,?>> IntraVmClientConnectionFactory<I,O,U,V,T,C> weakListeners( Function<SocketAddress, ? extends IntraVmServerConnectionFactory<?,?,? extends V,? super U,?,?>> connector, Factory<? extends T> endpointFactory, ParameterizedFactory<Pair<? extends T, ? extends AbstractIntraVmEndpoint<?,?,?,? super U>>, ? extends C> connectionFactory) { return new IntraVmClientConnectionFactory<I,O,U,V,T,C>(connector, endpointFactory, connectionFactory, new WeakConcurrentSet<ConnectionsListener<? super C>>()); } protected final Function<SocketAddress, ? extends IntraVmServerConnectionFactory<?,?,? extends V,? super U,?,?>> connector; public IntraVmClientConnectionFactory( Function<SocketAddress, ? extends IntraVmServerConnectionFactory<?,?,? extends V,? super U,?,?>> connector, Factory<? extends T> endpointFactory, ParameterizedFactory<Pair<? extends T, ? extends AbstractIntraVmEndpoint<?,?,?,? super U>>, ? extends C> connectionFactory, IConcurrentSet<ConnectionsListener<? super C>> listeners) { super(endpointFactory, connectionFactory, listeners); this.connector = connector; } @Override public ListenableFuture<C> connect(SocketAddress remoteAddress) { logger.debug("Connecting => {}", remoteAddress); IntraVmServerConnectionFactory<?,?,? extends V,? super U,?,?> server = connector.apply(remoteAddress); checkArgument(server != null, remoteAddress); T local = endpointFactory.get(); AbstractIntraVmEndpoint<?,?,?,? super U> remote = server.connect(local); C connection = connectionFactory.get(Pair.create(local, remote)); if (add(connection)) { return Futures.immediateFuture(connection); } else { return Futures.immediateFailedFuture(new IllegalStateException(String.valueOf(state()))); } } }