Java tutorial
/* * MailServer * * [C#] Papercut - Copyright 2008-2012 Ken Robertson * [Java] JPapercut - Copyright 2014 Stphane Meny * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ package eu.smeny.jpapercut.smtp; import java.io.IOException; import java.io.OutputStream; import java.io.PrintWriter; import java.net.InetAddress; import java.net.ServerSocket; import java.net.Socket; import java.net.UnknownHostException; import java.util.HashMap; import java.util.Map; import org.apache.commons.lang3.StringUtils; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; public class MailServer implements Runnable { /** * Maximum allowed connections before refusing new ones. */ private static final int MAX_ALLOWED_CONNECTIONS = 50; /** * The socket used to receive incoming connections. */ private ServerSocket socket; /** * Port used to receive messages. Defaults to SMTP port (25). */ private int port = 25; /** * Indicates if the server is currently running. */ private volatile boolean running; /** * Logger used in this class. */ private final Logger logger = LogManager.getLogger(getClass()); /** * Map of connections to this server currently opened. */ private Map<Integer, Connection> connections; public MailServer() { running = false; connections = new HashMap<Integer, Connection>(); } public MailServer(int port) { this(); this.port = port; } @Override public void run() { logger.info("Starting server ..."); openServerSocket(); // We check that the server socket is opened to continue if (!running) { logger.error("Impossible to start server, socket is closed"); stop(); } // Will handle connection only if server is running handleConnection(); } private void handleConnection() { while (running) { try { // Starts a new client connection Socket client = socket.accept(); if (connections.size() < MAX_ALLOWED_CONNECTIONS) { acceptConnection(client); } else { refuseConnection(client); } } catch (IOException ioe) { logger.error("IO Error while starting connection", ioe); } } } private void acceptConnection(Socket client) { final int id = connections.size() + 1; final Connection connection = new Connection(id, client); final Thread thread = new Thread(connection); connections.put(Integer.valueOf(id), connection); thread.start(); } private void refuseConnection(Socket client) { try { OutputStream output = client.getOutputStream(); PrintWriter writer = new PrintWriter(output); String hostname = retrieveHostname(); writer.write("421 " + hostname + " Service not available, too much connections"); writer.flush(); client.close(); } catch (IOException ioe) { logger.error("IO Error while refusing connection", ioe); } } private void openServerSocket() { try { socket = new ServerSocket(port); logger.info("Socket opened successfully on port " + port); running = true; } catch (IOException ioe) { logger.error("Error while opening socket on port " + port, ioe); } } public void stop() { running = false; logger.info("Stoping server ..."); } public static String retrieveHostname() { String hostname; try { hostname = InetAddress.getLocalHost().getHostName(); } catch (UnknownHostException uhe) { // Tries environment variables hostname = System.getenv("COMPUTERNAME"); if (StringUtils.isEmpty(hostname)) { hostname = System.getenv("HOSTNAME"); } if (StringUtils.isEmpty(hostname)) { hostname = "localhost"; } } return hostname; } }