001/**
002 * Logback: the reliable, generic, fast and flexible logging framework.
003 * Copyright (C) 1999-2015, QOS.ch. All rights reserved.
004 *
005 * This program and the accompanying materials are dual-licensed under
006 * either the terms of the Eclipse Public License v1.0 as published by
007 * the Eclipse Foundation
008 *
009 *   or (per the licensee's choosing)
010 *
011 * under the terms of the GNU Lesser General Public License version 2.1
012 * as published by the Free Software Foundation.
013 */
014package ch.qos.logback.core.net;
015
016import java.io.IOException;
017import java.net.InetAddress;
018import java.net.Socket;
019
020import javax.net.SocketFactory;
021
022import ch.qos.logback.core.util.DelayStrategy;
023import ch.qos.logback.core.util.FixedDelay;
024
025/**
026 * Default implementation of {@link SocketConnector}.
027 *
028 * @author Carl Harris
029 * @since 1.0.12
030 */
031public class DefaultSocketConnector implements SocketConnector {
032
033    private final InetAddress address;
034    private final int port;
035    private final DelayStrategy delayStrategy;
036
037    private ExceptionHandler exceptionHandler;
038    private SocketFactory socketFactory;
039
040    /**
041     * Constructs a new connector.
042     *
043     * @param address      address of remote listener
044     * @param port         port of remote listener
045     * @param initialDelay delay before initial connection attempt
046     * @param retryDelay   delay after failed connection attempt
047     */
048    public DefaultSocketConnector(InetAddress address, int port, long initialDelay, long retryDelay) {
049        this(address, port, new FixedDelay(initialDelay, retryDelay));
050    }
051
052    /**
053     * Constructs a new connector.
054     *
055     * @param address       address of remote listener
056     * @param port          port of remote listener
057     * @param delayStrategy strategy for choosing the delay to impose before each
058     *                      connection attempt
059     */
060    public DefaultSocketConnector(InetAddress address, int port, DelayStrategy delayStrategy) {
061        this.address = address;
062        this.port = port;
063        this.delayStrategy = delayStrategy;
064    }
065
066    /**
067     * Loops until the desired connection is established and returns the resulting
068     * connector.
069     */
070    public Socket call() throws InterruptedException {
071        useDefaultsForMissingFields();
072        Socket socket = createSocket();
073        while (socket == null && !Thread.currentThread().isInterrupted()) {
074            Thread.sleep(delayStrategy.nextDelay());
075            socket = createSocket();
076        }
077        return socket;
078    }
079
080    private Socket createSocket() {
081        Socket newSocket = null;
082        try {
083            newSocket = socketFactory.createSocket(address, port);
084        } catch (IOException ioex) {
085            exceptionHandler.connectionFailed(this, ioex);
086        }
087        return newSocket;
088    }
089
090    private void useDefaultsForMissingFields() {
091        if (exceptionHandler == null) {
092            exceptionHandler = new ConsoleExceptionHandler();
093        }
094        if (socketFactory == null) {
095            socketFactory = SocketFactory.getDefault();
096        }
097    }
098
099    /**
100     * {@inheritDoc}
101     */
102    public void setExceptionHandler(ExceptionHandler exceptionHandler) {
103        this.exceptionHandler = exceptionHandler;
104    }
105
106    /**
107     * {@inheritDoc}
108     */
109    public void setSocketFactory(SocketFactory socketFactory) {
110        this.socketFactory = socketFactory;
111    }
112
113    /**
114     * A default {@link ExceptionHandler} that writes to {@code System.out}
115     */
116    private static class ConsoleExceptionHandler implements ExceptionHandler {
117
118        public void connectionFailed(SocketConnector connector, Exception ex) {
119            System.out.println(ex);
120        }
121
122    }
123
124}