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(), getInetAddress()); 062 ServerListener<RemoteReceiverClient> listener = createServerListener(socket); 063 064 runner = createServerRunner(listener, getContext().getScheduledExecutorService()); 065 runner.setContext(getContext()); 066 getContext().getScheduledExecutorService().execute(runner); 067 super.start(); 068 } catch (Exception ex) { 069 addError("server startup error: " + ex, ex); 070 } 071 } 072 073 protected ServerListener<RemoteReceiverClient> createServerListener(ServerSocket socket) { 074 return new RemoteReceiverServerListener(socket); 075 } 076 077 protected ServerRunner<RemoteReceiverClient> createServerRunner(ServerListener<RemoteReceiverClient> listener, Executor executor) { 078 return new RemoteReceiverServerRunner(listener, executor, getClientQueueSize()); 079 } 080 081 @Override 082 public void stop() { 083 if (!isStarted()) 084 return; 085 try { 086 runner.stop(); 087 super.stop(); 088 } catch (IOException ex) { 089 addError("server shutdown error: " + ex, ex); 090 } 091 } 092 093 @Override 094 protected void append(E event) { 095 if (event == null) 096 return; 097 postProcessEvent(event); 098 final Serializable serEvent = getPST().transform(event); 099 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}