2 * Copyright (c) 2014, 2015 Cable Television Laboratories, Inc. and others. All rights reserved.
4 * This program and the accompanying materials are made available under the
5 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6 * and is available at http://www.eclipse.org/legal/epl-v10.html
9 package org.pcmm.rcd.impl;
11 import java.util.concurrent.atomic.AtomicBoolean;
12 import org.pcmm.PCMMConstants;
13 import org.pcmm.PCMMProperties;
14 import org.pcmm.concurrent.IWorkerPool;
15 import org.pcmm.concurrent.impl.WorkerPool;
16 import org.pcmm.rcd.IPCMMServer;
17 import org.pcmm.state.IState;
18 import org.slf4j.Logger;
19 import org.slf4j.LoggerFactory;
21 import java.io.IOException;
22 import java.net.ServerSocket;
23 import java.net.Socket;
24 import java.util.concurrent.ExecutorService;
25 import java.util.concurrent.Executors;
27 // import org.junit.Assert;
32 * @see pcmm.rcd.IPCMMServer
34 public abstract class AbstractPCMMServer implements IPCMMServer {
36 private static final Logger logger = LoggerFactory.getLogger(AbstractPCMMServer.class);
39 * A ServerSocket to accept messages ( OPN requests)
41 private transient ServerSocket serverSocket;
43 private volatile boolean keepAlive;
46 * This object is used to signal when the server is ready to accept connections.
47 * It is used in signaling and therefore must be final.
49 private final AtomicBoolean isReadyFlag = new AtomicBoolean(false);
52 * The port number on which to start the server.
54 private final int port;
59 * The thread pool executor
61 private final ExecutorService executorService;
64 * Constructor to use the port number contained within the PCMMProperties static object
66 protected AbstractPCMMServer() {
67 this(PCMMProperties.get(PCMMConstants.PCMM_PORT, Integer.class));
71 * Constructor for starting the server to a pre-defined port number. When 0 is used, the server socket will
72 * assign one for you. To determine which port is being used, call getPort() after startServer() is called.
73 * @param port - the port number on which to start the server
75 protected AbstractPCMMServer(int port) {
76 // XXX - Assert.assertTrue(port >= 0 && port <= 65535);
79 int poolSize = PCMMProperties.get(PCMMConstants.PS_POOL_SIZE, Integer.class);
80 pool = new WorkerPool(poolSize);
81 executorService = Executors.newSingleThreadExecutor();
87 * @see pcmm.rcd.IPCMMServer#startServer()
89 public void startServer() throws IOException {
90 if (serverSocket != null)
93 serverSocket = new ServerSocket(port);
94 logger.info("Server started and listening on port :" + port);
96 // execute this in a single thread executor
97 executorService.execute(new Runnable() {
100 synchronized (isReadyFlag) {
101 isReadyFlag.set(true);
102 isReadyFlag.notify();
107 Socket socket = serverSocket.accept();
108 logger.info("Accepted a new connection from :" + socket.getInetAddress().getHostAddress() + ":" + socket.getPort());
110 pool.schedule(getPCMMClientHandler(socket));
111 logger.info("Handler attached to : " + socket.getInetAddress().getHostAddress() + ":" + socket.getPort());
113 logger.info("connection to be closed : " + socket.getInetAddress().getHostAddress() + ":" + socket.getPort());
116 } catch (IOException e) {
117 logger.error(e.getMessage());
121 synchronized (isReadyFlag) {
122 isReadyFlag.set(false);
129 synchronized (isReadyFlag) {
130 // block until the server thread is ready to go
131 while (!isReadyFlag.get()) {
134 } catch (InterruptedException e) {
135 Thread.currentThread().interrupt();
141 public boolean isReady() {
142 return isReadyFlag.get();
146 * This client is used to handle requests from within the Application
149 * @param socket - the connection to the PCMM server
150 * @return client handler
152 protected abstract IPCMMClientHandler getPCMMClientHandler(Socket socket) throws IOException;
155 public void stopServer() {
158 executorService.shutdownNow();
160 if (serverSocket != null) {
161 serverSocket.close();
163 } catch (Exception e) {
164 logger.error(e.getMessage());
170 public void recordState() {
171 // TODO - implement me
175 public IState getRecoredState() {
182 public int getPort() {
183 if (serverSocket != null && serverSocket.isBound()) return serverSocket.getLocalPort();
184 else return this.port;