1 /**
2 * AUTOHIT 2003
3 * Copyright Erich P Gatejen (c) 1989,1997,2003,2004
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or (at
8 * your option) any later version.
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
11 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 * You should have received a copy of the GNU General Public License along
15 * with this program; if not, write to the Free Software Foundation, Inc.,
16 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 *
18 * Additional license information can be found in the documentation.
19 * @author Erich P Gatejen
20 */
21 package autohit.server.service;
22
23 import java.net.ServerSocket;
24 import java.net.Socket;
25 import java.net.SocketTimeoutException;
26 import java.util.HashSet;
27 import java.util.Iterator;
28
29 import autohit.common.AutohitErrorCodes;
30 import autohit.common.AutohitProperties;
31 import autohit.common.Utils;
32 import autohit.common.channels.Channel;
33 import autohit.common.channels.Controller;
34 import autohit.common.channels.Injector;
35 import autohit.common.channels.SimpleInjector;
36 import autohit.server.invoker.SimTextCommand;
37
38 /**
39 * This is a socket relay service. It's a dumb relay for sockets. Don't ask why
40 * I did this. It will accept connections on port
41 * AutohitProperties.value_SOCKETRELAY_SERVER_PORT. It'll relay them to the
42 * current property settings for
43 * AutohitProperties.SERVICE_SOCKETRELAY_DESTINATION_ADDR and
44 * AutohitProperties.SERVICE_SOCKETRELAY_DESTINATION_PORT for address and port,
45 * respectively. If either is not set, a default will be used, though there is
46 * little utility in the default.
47 * <p>
48 * <p>
49 * The relay will stay active until either side drops the connection. There is
50 * absolutely no filtering or logging.
51 *
52 * @author Erich P. Gatejen
53 * @version 1.0 <i>Version History</i><code>EPG - Initial - 12SEP03</code>
54 */
55 public class HttpCommandService extends Service {
56
57 final private static int ACCEPT_TIMEOUT = 2000;
58 final private static int CLEANUP_THRESHOLD = 200;
59
60 public final static String INJECTOR_NAME = AutohitProperties.COMMAND_SERVER_INJECTOR + ".HttpCommandService";
61
62 /**
63 * accept port */
64 ServerSocket listen;
65
66 /**
67 * active ports */
68 HashSet active;
69
70 /**
71 * Channel stuff
72 * */
73 private Channel commandChannel;
74 private Injector commandInjector;
75 private SimTextCommand commander;
76
77
78 /**
79 * Default constructor */
80 public HttpCommandService() {
81 super();
82 }
83
84 /**
85 * Complete construction. This will be called when the VM is initialized. */
86 public void construct() throws ServiceException {
87
88 try {
89
90 // How are we confiugred
91 int port = AutohitProperties.default_HTTPCOMMAND_SERVER_PORT;
92 String portString =
93 (String) Utils.testGetProperty(
94 AutohitProperties.SERVICE_HTTPCOMMAND_SERVER_PORT,
95 sc.getPropertiesSet());
96 if (portString != null) {
97 port = Integer.parseInt(portString);
98 }
99 // Set up communication
100 listen = new ServerSocket(port);
101 active = new HashSet();
102
103 // command interface
104 commandInjector = new SimpleInjector();
105 commandChannel = Controller.tune(AutohitProperties.COMMAND_SERVER_STATION);
106 commandChannel.register(INJECTOR_NAME, commandInjector);
107
108 commander = new SimTextCommand();
109 commander.init(sc);
110
111 } catch (NumberFormatException nee) {
112 throw new ServiceException(
113 "Failed constructing HttpCommandService. Bad value for property " +
114 AutohitProperties.SERVICE_HTTPCOMMAND_SERVER_PORT + ". message=" + nee.getMessage(),
115 ServiceException.CODE_SERVICE_STARTUP_FAULT);
116
117 } catch (Exception ee) {
118 throw new ServiceException(
119 "Failed constructing HttpCommandService. message=" + ee.getMessage(),
120 ServiceException.CODE_SERVICE_STARTUP_FAULT);
121 }
122
123 }
124
125 /**
126 * Fast loop. We spend most of our time waiting for connections. Cycle back
127 * to VM only after an accept or a timeout.
128 *
129 * @see autohit.vm.VMException
130 */
131 public void execute() throws ServiceException {
132
133 Socket accepted;
134
135 // Try to accept
136 try {
137
138 // Do we need to clean the active set?
139 if (active.size() > CLEANUP_THRESHOLD) {
140 this.cleanActive();
141 }
142
143 // ACCEPT
144 listen.setSoTimeout(ACCEPT_TIMEOUT);
145 accepted = listen.accept();
146 myLog.debug("HttpCommandService:Accepted a connection.", AutohitErrorCodes.CODE_DEBUGGING_SERVICES);
147
148 // Build helper
149 HttpCommandHelper srh = new HttpCommandHelper();
150 srh.init(accepted, myLog, commandInjector, commander, this);
151 myLog.debug(
152 "HttpCommandService:Relay helper initialized.",
153 AutohitErrorCodes.CODE_DEBUGGING_SERVICES);
154
155 // dispatch
156 srh.start();
157 active.add(srh);
158 myLog.debug("HttpCommandService:Relay helper dispatched.", AutohitErrorCodes.CODE_DEBUGGING_SERVICES);
159
160 } catch (SocketTimeoutException ste) {
161 // This is ok. See if we are dead.
162 if (this.getState() < HttpCommandService.STATE_ACTIVE_THRESHOLD)
163 throw new ServiceException(
164 "HttpCommandService ordered to stop.",
165 ServiceException.CODE_SERVICE_INTENTIONAL_HALT);
166
167 } catch (Exception ee) {
168 throw new ServiceException(
169 "Fault in HttpCommandService. message=" + ee.getMessage(),
170 ServiceException.CODE_SERVICE_GENERAL_FAULT);
171 }
172 }
173
174 /**
175 * Helper */
176 private void cleanActive() throws Exception {
177
178 Iterator i = active.iterator();
179
180 while (i.hasNext()) {
181 HttpCommandHelper srh = (HttpCommandHelper) i.next();
182 if (!srh.isAlive())
183 active.remove(srh);
184 }
185 }
186
187 /**
188 * Complete destroy. This will be called when the VM is finalizing. */
189 public void destruct() throws ServiceException {
190
191 Iterator i = active.iterator();
192
193 while (i.hasNext()) {
194 HttpCommandHelper srh = (HttpCommandHelper) i.next();
195 active.remove(srh);
196 if (srh.isAlive()) {
197 try {
198 srh.interrupt();
199 } catch (Exception eee) { // dont care
200 }
201 }
202 } // end while
203
204 } // end destruct
205
206 }
|