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.server; 015 016import java.io.IOException; 017import java.io.Serializable; 018import java.net.InetAddress; 019import java.net.ServerSocket; 020import java.net.UnknownHostException; 021import java.util.concurrent.Executor; 022 023import javax.net.ServerSocketFactory; 024 025import ch.qos.logback.core.AppenderBase; 026import ch.qos.logback.core.net.AbstractSocketAppender; 027import ch.qos.logback.core.spi.PreSerializationTransformer; 028 029/** 030 * 031 * This is the super class for module specific ServerSocketAppender 032 * implementations can derive from. 033 * 034 * @author Carl Harris 035 */ 036public abstract class AbstractServerSocketAppender<E> extends AppenderBase<E> { 037 038 /** 039 * Default {@link ServerSocket} backlog 040 */ 041 public static final int DEFAULT_BACKLOG = 50; 042 043 /** 044 * Default queue size used for each client 045 */ 046 public static final int DEFAULT_CLIENT_QUEUE_SIZE = 100; 047 048 private int port = AbstractSocketAppender.DEFAULT_PORT; 049 private int backlog = DEFAULT_BACKLOG; 050 private int clientQueueSize = DEFAULT_CLIENT_QUEUE_SIZE; 051 052 private String address; 053 054 private ServerRunner<RemoteReceiverClient> runner; 055 056 @Override 057 public void start() { 058 if (isStarted()) 059 return; 060 try { 061 ServerSocket socket = getServerSocketFactory().createServerSocket(getPort(), getBacklog(), 062 getInetAddress()); 063 ServerListener<RemoteReceiverClient> listener = createServerListener(socket); 064 065 runner = createServerRunner(listener, getContext().getExecutorService()); 066 runner.setContext(getContext()); 067 getContext().getExecutorService().execute(runner); 068 super.start(); 069 } catch (Exception ex) { 070 addError("server startup error: " + ex, ex); 071 } 072 } 073 074 protected ServerListener<RemoteReceiverClient> createServerListener(ServerSocket socket) { 075 return new RemoteReceiverServerListener(socket); 076 } 077 078 protected ServerRunner<RemoteReceiverClient> createServerRunner(ServerListener<RemoteReceiverClient> listener, 079 Executor executor) { 080 return new RemoteReceiverServerRunner(listener, executor, getClientQueueSize()); 081 } 082 083 @Override 084 public void stop() { 085 if (!isStarted()) 086 return; 087 088 try { 089 runner.stop(); 090 super.stop(); 091 } catch (IOException ex) { 092 addError("server shutdown error: " + ex, ex); 093 } 094 } 095 096 @Override 097 protected void append(E event) { 098 if (event == null) 099 return; 100 postProcessEvent(event); 101 final Serializable serEvent = getPST().transform(event); 102 runner.accept(new ClientVisitor<RemoteReceiverClient>() { 103 public void visit(RemoteReceiverClient client) { 104 client.offer(serEvent); 105 } 106 }); 107 } 108 109 /** 110 * Postprocess an event received via {@link #append append()}. 111 * 112 * @param event 113 */ 114 protected abstract void postProcessEvent(E event); 115 116 /** 117 * Gets a transformer that will be used to convert a received event to a 118 * {@link Serializable} form. 119 * 120 * @return 121 */ 122 protected abstract PreSerializationTransformer<E> getPST(); 123 124 /** 125 * Gets the factory used to create {@link ServerSocket} objects. 126 * <p> 127 * The default implementation delegates to 128 * {@link ServerSocketFactory#getDefault()}. Subclasses may override to private 129 * a different socket factory implementation. 130 * 131 * @return socket factory. 132 */ 133 protected ServerSocketFactory getServerSocketFactory() throws Exception { 134 return ServerSocketFactory.getDefault(); 135 } 136 137 /** 138 * Gets the local address for the listener. 139 * 140 * @return an {@link InetAddress} representation of the local address. 141 * @throws UnknownHostException 142 */ 143 protected InetAddress getInetAddress() throws UnknownHostException { 144 if (getAddress() == null) 145 return null; 146 return InetAddress.getByName(getAddress()); 147 } 148 149 /** 150 * Gets the local port for the listener. 151 * 152 * @return local port 153 */ 154 public int getPort() { 155 return port; 156 } 157 158 /** 159 * Sets the local port for the listener. 160 * 161 * @param port the local port to set 162 */ 163 public void setPort(int port) { 164 this.port = port; 165 } 166 167 /** 168 * Gets the listener queue depth. 169 * <p> 170 * This represents the number of connected clients whose connections have not 171 * yet been accepted. 172 * 173 * @return queue depth 174 * @see java.net.ServerSocket 175 */ 176 public int getBacklog() { 177 return backlog; 178 } 179 180 /** 181 * Sets the listener queue depth. 182 * <p> 183 * This represents the number of connected clients whose connections have not 184 * yet been accepted. 185 * 186 * @param backlog the queue depth to set 187 * @see java.net.ServerSocket 188 */ 189 public void setBacklog(int backlog) { 190 this.backlog = backlog; 191 } 192 193 /** 194 * Gets the local address for the listener. 195 * 196 * @return a string representation of the local address 197 */ 198 public String getAddress() { 199 return address; 200 } 201 202 /** 203 * Sets the local address for the listener. 204 * 205 * @param address a host name or a string representation of an IP address 206 */ 207 public void setAddress(String address) { 208 this.address = address; 209 } 210 211 /** 212 * Gets the event queue size used for each client connection. 213 * 214 * @return queue size 215 */ 216 public int getClientQueueSize() { 217 return clientQueueSize; 218 } 219 220 /** 221 * Sets the event queue size used for each client connection. 222 * 223 * @param clientQueueSize the queue size to set 224 */ 225 public void setClientQueueSize(int clientQueueSize) { 226 this.clientQueueSize = clientQueueSize; 227 } 228 229}