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.classic.net.server;
015
016import java.io.IOException;
017import java.net.InetAddress;
018import java.net.ServerSocket;
019import java.net.UnknownHostException;
020import java.util.concurrent.Executor;
021
022import javax.net.ServerSocketFactory;
023
024import ch.qos.logback.classic.net.ReceiverBase;
025import ch.qos.logback.core.net.AbstractSocketAppender;
026import ch.qos.logback.core.net.server.ServerListener;
027import ch.qos.logback.core.net.server.ServerRunner;
028import ch.qos.logback.core.util.CloseUtil;
029
030/**
031 * A logging socket server that is configurable using Joran.
032 *
033 * @author Carl Harris
034 */
035public class ServerSocketReceiver extends ReceiverBase {
036
037    /**
038     * Default {@link ServerSocket} backlog
039     */
040    public static final int DEFAULT_BACKLOG = 50;
041
042    private int port = AbstractSocketAppender.DEFAULT_PORT;
043    private int backlog = DEFAULT_BACKLOG;
044
045    private String address;
046
047    private ServerSocket serverSocket;
048    @SuppressWarnings("rawtypes")
049    private ServerRunner runner;
050
051    /**
052     * Starts the server.
053     */
054    protected boolean shouldStart() {
055        try {
056            ServerSocket serverSocket = getServerSocketFactory().createServerSocket(getPort(), getBacklog(),
057                    getInetAddress());
058
059            ServerListener<RemoteAppenderClient> listener = createServerListener(serverSocket);
060
061            runner = createServerRunner(listener, getContext().getExecutorService());
062            runner.setContext(getContext());
063            return true;
064        } catch (Exception ex) {
065            addError("server startup error: " + ex, ex);
066            CloseUtil.closeQuietly(serverSocket);
067            return false;
068        }
069    }
070
071    protected ServerListener<RemoteAppenderClient> createServerListener(ServerSocket socket) {
072        return new RemoteAppenderServerListener(socket);
073    }
074
075    @SuppressWarnings("rawtypes")
076    protected ServerRunner createServerRunner(ServerListener<RemoteAppenderClient> listener, Executor executor) {
077        return new RemoteAppenderServerRunner(listener, executor);
078    }
079
080    @Override
081    protected Runnable getRunnableTask() {
082        return runner;
083    }
084
085    /**
086     * {@inheritDoc}
087     */
088    protected void onStop() {
089        try {
090            if (runner == null)
091                return;
092            runner.stop();
093        } catch (IOException ex) {
094            addError("server shutdown error: " + ex, ex);
095        }
096    }
097
098    /**
099     * Gets the server socket factory.
100     * <p>
101     * Subclasses may override to provide a custom factory.
102     * 
103     * @return server socket factory
104     * @throws Exception
105     */
106    protected ServerSocketFactory getServerSocketFactory() throws Exception {
107        return ServerSocketFactory.getDefault();
108    }
109
110    /**
111     * Gets the local address for the listener.
112     * 
113     * @return an {@link InetAddress} representation of the local address.
114     * @throws UnknownHostException
115     */
116    protected InetAddress getInetAddress() throws UnknownHostException {
117        if (getAddress() == null)
118            return null;
119        return InetAddress.getByName(getAddress());
120    }
121
122    /**
123     * Gets the local port for the listener.
124     * 
125     * @return local port
126     */
127    public int getPort() {
128        return port;
129    }
130
131    /**
132     * Sets the local port for the listener.
133     * 
134     * @param port the local port to set
135     */
136    public void setPort(int port) {
137        this.port = port;
138    }
139
140    /**
141     * Gets the listener queue depth.
142     * <p>
143     * This represents the number of connected clients whose connections have not
144     * yet been accepted.
145     * 
146     * @return queue depth
147     * @see java.net.ServerSocket
148     */
149    public int getBacklog() {
150        return backlog;
151    }
152
153    /**
154     * Sets the listener queue depth.
155     * <p>
156     * This represents the number of connected clients whose connections have not
157     * yet been accepted.
158     * 
159     * @param backlog the queue depth to set
160     * @see java.net.ServerSocket
161     */
162    public void setBacklog(int backlog) {
163        this.backlog = backlog;
164    }
165
166    /**
167     * Gets the local address for the listener.
168     * 
169     * @return a string representation of the local address
170     */
171    public String getAddress() {
172        return address;
173    }
174
175    /**
176     * Sets the local address for the listener.
177     * 
178     * @param address a host name or a string representation of an IP address
179     */
180    public void setAddress(String address) {
181        this.address = address;
182    }
183
184}