5bd01d491f2e196ae484d7c1b884086f571abaae
[packetcable.git] / packetcable-driver / src / main / java / org / pcmm / rcd / impl / AbstractPCMMServer.java
1 /**
2  @header@
3  */
4 package org.pcmm.rcd.impl;
5
6 import org.pcmm.PCMMConstants;
7 import org.pcmm.PCMMProperties;
8 import org.pcmm.concurrent.IWorkerPool;
9 import org.pcmm.concurrent.impl.WorkerPool;
10 import org.pcmm.messages.impl.MessageFactory;
11 import org.pcmm.rcd.IPCMMServer;
12 import org.pcmm.state.IState;
13 import org.slf4j.Logger;
14 import org.slf4j.LoggerFactory;
15 import org.umu.cops.stack.COPSHeader.OPCode;
16 import org.umu.cops.stack.COPSMsg;
17
18 import java.io.IOException;
19 import java.net.ServerSocket;
20 import java.net.Socket;
21 import java.util.concurrent.Executors;
22
23 // import org.junit.Assert;
24
25 /*
26  * (non-Javadoc)
27  *
28  * @see pcmm.rcd.IPCMMServer
29  */
30 public abstract class AbstractPCMMServer implements IPCMMServer {
31         protected Logger logger;
32         /*
33          * A ServerSocket to accept messages ( OPN requests)
34          */
35         private ServerSocket serverSocket;
36
37         private Socket stopSocket;
38
39         private volatile boolean keepAlive;
40         /*
41      *
42      */
43         private int port;
44
45         IWorkerPool pool;
46
47         /**
48          * Constructor to use the port number contained within the PCMMProperties static object
49          */
50         protected AbstractPCMMServer() {
51                 this(PCMMProperties.get(PCMMConstants.PCMM_PORT, Integer.class));
52         }
53
54         /**
55          * Constructor for starting the server to a pre-defined port number. When 0 is used, the server socket will
56          * assign one for you. To determine which port is being used, call getPort() after startServer() is called.
57          * @param port - the port number on which to start the server
58          */
59         protected AbstractPCMMServer(int port) {
60                 // XXX - Assert.assertTrue(port >= 0 && port <= 65535);
61                 this.port = port;
62                 keepAlive = true;
63                 logger = LoggerFactory.getLogger(getClass().getName());
64                 int poolSize = PCMMProperties.get(PCMMConstants.PS_POOL_SIZE, Integer.class);
65                 pool = new WorkerPool(poolSize);
66         }
67
68         /*
69          * (non-Javadoc)
70          * 
71          * @see pcmm.rcd.IPCMMServer#startServer()
72          */
73         public void startServer() {
74                 if (serverSocket != null)
75                         return;
76                 try {
77                         serverSocket = new ServerSocket(port);
78                         port = serverSocket.getLocalPort();
79                         logger.info("Server started and listening on port :" + port);
80                 } catch (IOException e) {
81                         logger.error(e.getMessage());
82                 }
83                 // execute this in a single thread executor
84                 Executors.newSingleThreadExecutor().execute(new Runnable() {
85                         public void run() {
86                                 while (keepAlive) {
87                                         try {
88                                                 Socket socket = serverSocket.accept();
89                                                 logger.info("Accepted a new connection from :" + socket.getInetAddress().getHostAddress() + ":" + socket.getPort());
90                                                 if (keepAlive) {
91                                                         pool.schedule(getPCMMClientHandler(socket));
92                                                         logger.info("Handler attached tp : " + socket.getInetAddress().getHostAddress() + ":" + socket.getPort());
93                                                 } else {
94                                                         logger.info("connection to be closed : " + socket.getInetAddress().getHostAddress() + ":" + socket.getPort());
95                                                         socket.close();
96                                                 }
97                                         } catch (IOException e) {
98                                                 logger.error(e.getMessage());
99                                         }
100                                 }
101                                 try {
102                                         if (stopSocket != null && stopSocket.isConnected()) {
103                                                 logger.info("Cleaning up");
104                                                 stopSocket.close();
105                                         }
106                                         if (serverSocket != null && serverSocket.isBound()) {
107                                                 logger.info("Server about to stop");
108                                                 serverSocket.close();
109                                                 logger.info("Server stopped");
110                                         }
111                                 } catch (IOException e) {
112                                         logger.error(e.getMessage());
113                                 }
114                         }
115                 });
116         }
117
118         /**
119          * This client is used to handle requests from within the Application
120          * Manager
121          * 
122          * @param socket - the connection to the PCMM server
123          * @return client handler
124          */
125         protected abstract IPCMMClientHandler getPCMMClientHandler(Socket socket);
126
127         /*
128          * (non-Javadoc)
129          * 
130          * @see pcmm.rcd.IPCMMServer#stopServer()
131          */
132         public void stopServer() {
133                 // set to stop
134                 keepAlive = false;
135                 try {
136                         if (serverSocket != null) {
137                                 stopSocket = new Socket(serverSocket.getInetAddress(), serverSocket.getLocalPort());
138                                 logger.info("STOP socket created and attached");
139                         }
140                 } catch (Exception e) {
141                         logger.error(e.getMessage());
142                 }
143         }
144
145         /*
146          * (non-Javadoc)
147          * 
148          * @see pcmm.state.IStateful#recordState()
149          */
150         public void recordState() {
151
152         }
153
154         /*
155          * (non-Javadoc)
156          * 
157          * @see pcmm.state.IStateful#getRecoredState()
158          */
159         public IState getRecoredState() {
160                 return null;
161         }
162
163         /**
164          * @return the port
165          */
166         public int getPort() {
167                 return port;
168         }
169
170         /**
171          * @param port
172          *            the port to set
173          */
174         public void setPort(int port) {
175                 this.port = port;
176         }
177
178         /*
179          * (non-Javadoc)
180          * 
181          * @see pcmm.rcd.IPCMMServer.IPCMMClientHandler
182          */
183         public abstract class AbstractPCMMClientHandler extends AbstractPCMMClient
184                         implements IPCMMClientHandler {
185
186                 protected boolean sendCCMessage = false;
187
188                 public AbstractPCMMClientHandler(Socket socket) {
189                         super();
190                         setSocket(socket);
191                 }
192
193                 @Override
194                 public boolean disconnect() {
195                         // XXX send CC message
196                         sendCCMessage = true;
197                         /*
198                          * is this really needed ?
199                          */
200                         // if (getSocket() != null)
201                         // handlersPool.remove(getSocket());
202                         COPSMsg message = MessageFactory.getInstance().create(OPCode.CC);
203                         sendRequest(message);
204                         return super.disconnect();
205                 }
206
207         }
208
209 }