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.io.BufferedInputStream;
24 // import java.io.BufferedOutputStream;
25 import java.io.DataInputStream;
26 import java.io.DataOutputStream;
27 import java.io.StringReader;
28 import java.net.Socket;
29
30 import autohit.common.AutohitErrorCodes;
31 import autohit.common.AutohitException;
32 import autohit.common.AutohitLogInjectorWrapper;
33 import autohit.common.channels.ChannelException;
34 import autohit.common.channels.Injector;
35 import autohit.server.ServerException;
36 import autohit.server.command.CommandAtom;
37 import autohit.server.invoker.SimTextCommand;
38
39 /**
40 * Http Command Helper.<br>
41 * GET /command?param1¶m2¶mN<br>
42 * The ? and & are interchangable.
43 * <p>
44 * @author Erich P. Gatejen
45 * @version 1.0 <i>Version History </i>
46 * <code>EPG - Initial - 05Apr05</code>
47 */
48 public class HttpCommandHelper extends Thread {
49
50 final private static int BUFFER_SIZE = 512;
51
52 /**
53 * Socket connection
54 */
55 public Socket connection;
56
57 private DataInputStream is;
58 private DataOutputStream os;
59 private Injector commandInjector;
60 private SimTextCommand commander;
61 private HttpCommandService callingService;
62
63 /**
64 * Logging mechinism
65 */
66 public AutohitLogInjectorWrapper myLog;
67
68 /**
69 * Default constructor
70 */
71 public HttpCommandHelper() {
72 super();
73 }
74
75 /**
76 * Complete construction. This will be called when the VM is initialized.
77 */
78 public void init(Socket ins, AutohitLogInjectorWrapper logger, Injector cin, SimTextCommand c, HttpCommandService caller) {
79 connection = ins;
80 myLog = logger;
81 callingService = caller;
82 try {
83 is = new DataInputStream(ins.getInputStream());
84 os = new DataOutputStream(ins.getOutputStream());
85 commandInjector = cin;
86 commander = c;
87
88 } catch (Exception eee) {
89 myLog.error(
90 "HttpCommandHelper init() failed. Something bad will happen. message="
91 + eee.getMessage(),
92 AutohitErrorCodes.CODE_SERVICE_GENERAL_FAULT);
93 }
94 }
95
96 /**
97 * Run the context
98 */
99 public void run() {
100
101 String input;
102 String path;
103 String result = "SOFTWARE BUG! You should never see this in HttpCommandHelper.run()";
104 try {
105
106 // pull request line
107 input = is.readLine();
108 input = input.trim();
109 int spot = input.indexOf(' ');
110
111 // Validate
112 if (spot < 0) {
113 throw new Exception("Invalid HTTP Request Line");
114 }
115
116 // Second
117 input = input.substring(spot).trim();
118 spot = input.indexOf(' ');
119
120 // Split
121 if (spot < 0) {
122 // No protocol. Must be old protocol
123 path = input;
124 } else {
125 path = input.substring(1, spot);
126 }
127
128 // Decode and build command
129 String command = decodePath(path);
130 CommandAtom a = commander.create(command);
131
132 // loop if no command
133 if (a == null) throw new Exception("Bad command. Caused a null.");
134
135 // dispatch it
136 commandInjector.post(a);
137
138 // Report OK
139 result = "PASS: Command accepted";
140 myLog.info(result,AutohitException.CODE_INFORMATIONAL_OK);
141
142 // } catch (InterruptedException ie) {
143
144 } catch (ServerException se) {
145 if (se.numeric==AutohitErrorCodes.CODE_SERVER_DONE) {
146 // Signal exiting
147 callingService.die();
148 } else {
149 result = "FAIL: HttpCommandService Server HALTED because of serious issue. message=" + se.getMessage();
150 myLog.info(result,AutohitException.CODE_SERVICE_PANIC);
151 }
152 // We got the exit command
153
154 } catch (ChannelException e) {
155 result = "FAIL: HttpCommandService Server HALTED because there is no command service running or command channel available. This may be intentional during a shutdown.";
156 myLog.info(result,AutohitException.CODE_SERVICE_PANIC);
157
158 } catch (Throwable e) {
159 result = "FAIL: Error processing HTTP Request: " + e;
160 myLog.info(result,AutohitException.CODE_SERVER_IO_ERROR);
161
162 } finally {
163 try {
164 respond(result);
165 os.close();
166 connection.close();
167 } catch (Throwable e) {
168 // Bad place here
169 }
170 }
171 }
172
173 public void respond(String content) throws Throwable {
174
175 println("HTTP 200 OK");
176 println("Server: HttpCommandService");
177 println("Content-Type: text/html");
178 println("Content-Length: " + content.length());
179 println("Accept-ranges: bytes");
180 println("");
181 print(content);
182 try {
183 Thread.sleep(100);
184 } catch (Exception e) {
185 // dont care
186 }
187 }
188
189 private void println(String text) throws Exception {
190 print(text);
191 os.write('\n');
192 }
193
194 private void print(String text) throws Exception {
195 byte bytes[] = text.getBytes();
196 os.write(bytes);
197 }
198
199 /*
200 * Return as Command->param1->paramN
201 */
202 private static String decodePath(String s) throws Throwable {
203
204 int value;
205 String candidate;
206
207 StringReader rin = new StringReader(s);
208 StringBuffer accumulator = new StringBuffer();
209
210 int current = rin.read();
211 while (current >= 0) {
212
213 // escape it
214 if (current=='%') {
215 current = rin.read();
216 if (current < 0) throw new Exception("Uncompleted escaped character in URL");
217 value = Character.digit((char)current,16);
218 value = value << 4;
219 current = rin.read();
220 if (current < 0) throw new Exception("Uncompleted escaped character in URL");
221 current = value + Character.digit((char)current,16);
222 }
223
224 // process it
225 if ((current=='?')||(current=='&')) {
226 accumulator.append(' ');
227 } else {
228 accumulator.append((char)current);
229 }
230
231 //DO NOT EDIT BELOW
232 current = rin.read();
233 }
234
235 return (accumulator.toString());
236 }
237
238 }
|