View Javadoc
1   /**
2    * Logback: the reliable, generic, fast and flexible logging framework.
3    * Copyright (C) 1999-2015, QOS.ch. All rights reserved.
4    *
5    * This program and the accompanying materials are dual-licensed under
6    * either the terms of the Eclipse Public License v1.0 as published by
7    * the Eclipse Foundation
8    *
9    *   or (per the licensee's choosing)
10   *
11   * under the terms of the GNU Lesser General Public License version 2.1
12   * as published by the Free Software Foundation.
13   */
14  package ch.qos.logback.core.net.server;
15  
16  import java.io.IOException;
17  import java.io.Serializable;
18  import java.net.InetAddress;
19  import java.net.ServerSocket;
20  import java.net.UnknownHostException;
21  import java.util.concurrent.Executor;
22  
23  import javax.net.ServerSocketFactory;
24  
25  import ch.qos.logback.core.AppenderBase;
26  import ch.qos.logback.core.net.AbstractSocketAppender;
27  import ch.qos.logback.core.spi.PreSerializationTransformer;
28  
29  /**
30   * 
31   * This is the super class for module specific ServerSocketAppender
32   * implementations can derive from.
33   * 
34   * @author Carl Harris
35   */
36  public abstract class AbstractServerSocketAppender<E> extends AppenderBase<E> {
37  
38      /**
39       * Default {@link ServerSocket} backlog
40       */
41      public static final int DEFAULT_BACKLOG = 50;
42  
43      /** 
44       * Default queue size used for each client
45       */
46      public static final int DEFAULT_CLIENT_QUEUE_SIZE = 100;
47  
48      private int port = AbstractSocketAppender.DEFAULT_PORT;
49      private int backlog = DEFAULT_BACKLOG;
50      private int clientQueueSize = DEFAULT_CLIENT_QUEUE_SIZE;
51  
52      private String address;
53  
54      private ServerRunner<RemoteReceiverClient> runner;
55  
56      @Override
57      public void start() {
58          if (isStarted())
59              return;
60          try {
61              ServerSocket socket = getServerSocketFactory().createServerSocket(getPort(), getBacklog(), getInetAddress());
62              ServerListener<RemoteReceiverClient> listener = createServerListener(socket);
63  
64              runner = createServerRunner(listener, getContext().getScheduledExecutorService());
65              runner.setContext(getContext());
66              getContext().getScheduledExecutorService().execute(runner);
67              super.start();
68          } catch (Exception ex) {
69              addError("server startup error: " + ex, ex);
70          }
71      }
72  
73      protected ServerListener<RemoteReceiverClient> createServerListener(ServerSocket socket) {
74          return new RemoteReceiverServerListener(socket);
75      }
76  
77      protected ServerRunner<RemoteReceiverClient> createServerRunner(ServerListener<RemoteReceiverClient> listener, Executor executor) {
78          return new RemoteReceiverServerRunner(listener, executor, getClientQueueSize());
79      }
80  
81      @Override
82      public void stop() {
83          if (!isStarted())
84              return;
85          try {
86              runner.stop();
87              super.stop();
88          } catch (IOException ex) {
89              addError("server shutdown error: " + ex, ex);
90          }
91      }
92  
93      @Override
94      protected void append(E event) {
95          if (event == null)
96              return;
97          postProcessEvent(event);
98          final Serializable serEvent = getPST().transform(event);
99          runner.accept(new ClientVisitor<RemoteReceiverClient>() {
100             public void visit(RemoteReceiverClient client) {
101                 client.offer(serEvent);
102             }
103         });
104     }
105 
106     /**
107      * Post process an event received via {@link #append append()}.
108      * @param event
109      */
110     protected abstract void postProcessEvent(E event);
111 
112     /**
113      * Gets a transformer that will be used to convert a received event
114      * to a {@link Serializable} form.
115      * @return
116      */
117     protected abstract PreSerializationTransformer<E> getPST();
118 
119     /**
120      * Gets the factory used to create {@link ServerSocket} objects.
121      * <p>
122      * The default implementation delegates to 
123      * {@link ServerSocketFactory#getDefault()}.  Subclasses may override to
124      * private a different socket factory implementation.
125      * 
126      * @return socket factory.
127      */
128     protected ServerSocketFactory getServerSocketFactory() throws Exception {
129         return ServerSocketFactory.getDefault();
130     }
131 
132     /**
133      * Gets the local address for the listener.
134      * @return an {@link InetAddress} representation of the local address.
135      * @throws UnknownHostException
136      */
137     protected InetAddress getInetAddress() throws UnknownHostException {
138         if (getAddress() == null)
139             return null;
140         return InetAddress.getByName(getAddress());
141     }
142 
143     /**
144      * Gets the local port for the listener.
145      * @return local port
146      */
147     public int getPort() {
148         return port;
149     }
150 
151     /**
152      * Sets the local port for the listener.
153      * @param port the local port to set
154      */
155     public void setPort(int port) {
156         this.port = port;
157     }
158 
159     /**
160      * Gets the listener queue depth.
161      * <p>
162      * This represents the number of connected clients whose connections 
163      * have not yet been accepted.
164      * @return queue depth
165      * @see java.net.ServerSocket
166      */
167     public int getBacklog() {
168         return backlog;
169     }
170 
171     /**
172      * Sets the listener queue depth.
173      * <p>
174      * This represents the number of connected clients whose connections 
175      * have not yet been accepted.
176      * @param backlog the queue depth to set
177      * @see java.net.ServerSocket
178      */
179     public void setBacklog(int backlog) {
180         this.backlog = backlog;
181     }
182 
183     /**
184      * Gets the local address for the listener.
185      * @return a string representation of the local address
186      */
187     public String getAddress() {
188         return address;
189     }
190 
191     /**
192      * Sets the local address for the listener.
193      * @param address a host name or a string representation of an IP address
194      */
195     public void setAddress(String address) {
196         this.address = address;
197     }
198 
199     /**
200      * Gets the event queue size used for each client connection. 
201      * @return queue size
202      */
203     public int getClientQueueSize() {
204         return clientQueueSize;
205     }
206 
207     /**
208      * Sets the event queue size used for each client connection.
209      * @param clientQueueSize the queue size to set
210      */
211     public void setClientQueueSize(int clientQueueSize) {
212         this.clientQueueSize = clientQueueSize;
213     }
214 
215 }