001: //========================================================================
002: // Copyright 2006 Mort Bay Consulting Pty. Ltd.
003: // expecting other bits copyrighted sun
004: //------------------------------------------------------------------------
005: // Licensed under the Apache License, Version 2.0 (the "License");
006: // you may not use this file except in compliance with the License.
007: // You may obtain a copy of the License at
008: // http://www.apache.org/licenses/LICENSE-2.0
009: // Unless required by applicable law or agreed to in writing, software
010: // distributed under the License is distributed on an "AS IS" BASIS,
011: // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
012: // See the License for the specific language governing permissions and
013: // limitations under the License.
014: //========================================================================
015:
016: package org.mortbay.jetty;
017:
018: import java.io.File;
019: import java.io.FileInputStream;
020: import java.io.IOException;
021: import java.io.PrintWriter;
022: import java.nio.channels.ByteChannel;
023: import java.nio.channels.ClosedChannelException;
024: import java.util.Random;
025:
026: import javax.servlet.ServletException;
027: import javax.servlet.http.HttpServlet;
028: import javax.servlet.http.HttpServletRequest;
029: import javax.servlet.http.HttpServletResponse;
030:
031: import org.mortbay.io.Buffer;
032: import org.mortbay.io.EndPoint;
033: import org.mortbay.io.nio.ChannelEndPoint;
034: import org.mortbay.io.nio.NIOBuffer;
035: import org.mortbay.jetty.nio.AbstractNIOConnector;
036: import org.mortbay.jetty.servlet.Context;
037: import org.mortbay.jetty.servlet.ServletHolder;
038: import org.mortbay.log.Log;
039: import org.mortbay.util.ajax.Continuation;
040:
041: /* ------------------------------------------------------------------------------- */
042: /**
043: * @author gregw
044: *
045: */
046: public class RandomConnector extends AbstractNIOConnector {
047: static Random random = new Random(System.currentTimeMillis());
048: static int rate = 1;
049:
050: /* ------------------------------------------------------------------------------- */
051: /**
052: * Constructor.
053: *
054: */
055: public RandomConnector() {
056: }
057:
058: /* ------------------------------------------------------------ */
059: public Object getConnection() {
060: // TODO return private connection eg server socket
061: return null;
062: }
063:
064: /* ------------------------------------------------------------ */
065: /*
066: * @see org.mortbay.jetty.AbstractConnector#doStart()
067: */
068: protected void doStart() throws Exception {
069: super .doStart();
070: }
071:
072: /* ------------------------------------------------------------ */
073: /*
074: * @see org.mortbay.jetty.AbstractConnector#doStop()
075: */
076: protected void doStop() throws Exception {
077: super .doStop();
078: }
079:
080: /* ------------------------------------------------------------ */
081: public void open() throws IOException {
082: // TODO Open server socket
083: }
084:
085: /* ------------------------------------------------------------ */
086: public void close() throws IOException {
087: // TODO Close server socket
088: }
089:
090: /* ------------------------------------------------------------ */
091: public void accept(int acceptorID) throws IOException {
092: // TODO accept a connection for real or progress an existing one
093: // but for now.... let's just pretend.
094:
095: // This creates a connection and runs it to completion.
096: // in reality there will be lots of endpoints in play and any one
097: // of them may need to be dispatched.
098:
099: try {
100: File file = new File("fakeRequests.txt");
101: if (!file.exists())
102: file = new File(
103: "modules/jetty/src/test/resources/fakeRequests.txt");
104: if (!file.exists())
105: file = new File("src/test/resources/fakeRequests.txt");
106: if (!file.exists())
107: file = new File("/tmp/fakeRequests.txt");
108: if (!file.exists()) {
109: System.err.println("No such file " + file);
110: System.exit(1);
111: }
112:
113: Thread.sleep(random.nextInt(50 * rate));
114:
115: ByteChannel channel = new FileInputStream(file)
116: .getChannel();
117: RandomEndPoint gep = new RandomEndPoint(this , channel);
118:
119: try {
120: // TODO in reality this dispatches would be mixed with others from other connections.
121: while (gep.isOpen()) {
122: Thread.sleep(random.nextInt(10 * rate));
123: synchronized (gep) {
124: if (!gep.dispatched) {
125: gep.dispatched = true;
126: getThreadPool().dispatch(gep);
127: }
128: }
129: }
130: } finally {
131: connectionClosed(gep._connection);
132: }
133:
134: } catch (InterruptedException e) {
135: // TODO Auto-generated catch block
136: e.printStackTrace();
137: }
138:
139: }
140:
141: /* ------------------------------------------------------------------------------- */
142: public void customize(EndPoint endpoint, Request request)
143: throws IOException {
144: super .customize(endpoint, request);
145: }
146:
147: /* ------------------------------------------------------------------------------- */
148: public int getLocalPort() {
149: // TODO return the actual port we are listening on
150: return 0;
151: }
152:
153: /* ------------------------------------------------------------------------------- */
154: /* ------------------------------------------------------------------------------- */
155: /* ------------------------------------------------------------------------------- */
156: public static class RandomEndPoint extends ChannelEndPoint
157: implements EndPoint, Runnable {
158: HttpConnection _connection;
159: boolean dispatched = false;
160:
161: public RandomEndPoint(RandomConnector connector,
162: ByteChannel channel) {
163: super (channel);
164: _connection = new HttpConnection(connector, this , connector
165: .getServer());
166: connector.connectionOpened(_connection);
167: }
168:
169: public void run() {
170: System.err.print("|");
171: try {
172: _connection.handle();
173: } catch (ClosedChannelException e) {
174: Log.ignore(e);
175: } catch (EofException e) {
176: Log.debug("EOF", e);
177: try {
178: close();
179: } catch (IOException e2) {
180: Log.ignore(e2);
181: }
182: } catch (HttpException e) {
183: Log.debug("BAD", e);
184: try {
185: close();
186: } catch (IOException e2) {
187: Log.ignore(e2);
188: }
189: } catch (Throwable e) {
190: Log.warn("handle failed", e);
191: try {
192: close();
193: } catch (IOException e2) {
194: Log.ignore(e2);
195: }
196: } finally {
197: Continuation continuation = _connection.getRequest()
198: .getContinuation();
199: if (continuation != null && continuation.isPending()) {
200: // We have a continuation
201: // TODO something!
202: } else {
203: synchronized (RandomEndPoint.this ) {
204: dispatched = false;
205: }
206: // something else... normally re-enable this connection is the selectset with the latest interested ops
207: }
208: }
209: }
210:
211: public boolean blockReadable(long millisecs) {
212: try {
213: Thread.sleep(random.nextInt(10 * rate));
214: } catch (InterruptedException e) {
215: e.printStackTrace();
216: }
217: return true;
218: }
219:
220: public boolean blockWritable(long millisecs) {
221: try {
222: Thread.sleep(random.nextInt(10 * rate));
223: } catch (InterruptedException e) {
224: e.printStackTrace();
225: }
226: return true;
227: }
228:
229: public int fill(Buffer buffer) throws IOException {
230: // sometimes read nothing
231: if (random.nextInt() % 10 < 2) {
232: // System.err.println("fill: 0");
233: return 0;
234: }
235:
236: // Get a random amount of data
237: int len = random.nextInt(20 * rate);
238: if (len > buffer.space())
239: len = buffer.space();
240:
241: // Load a length limited slice via a temp buffer
242: NIOBuffer temp = new NIOBuffer(len, false);
243: int len2 = super .fill(temp);
244: if (len2 < 0) {
245: // System.err.println("fill: EOF");
246: return -1;
247: }
248:
249: if (len != len2)
250: throw new IllegalStateException();
251: temp.mark();
252: buffer.put(temp);
253: temp.reset();
254: System.err.print(temp);
255: buffer.skip(len);
256: return len;
257: }
258:
259: public int flush(Buffer header, Buffer buffer, Buffer trailer)
260: throws IOException {
261: int len = 0;
262:
263: // TODO gather operation.
264: if (header != null && header.hasContent())
265: len += flush(header);
266:
267: if (header == null || !header.hasContent()) {
268: if (buffer != null && buffer.hasContent())
269: len += flush(buffer);
270: }
271:
272: if (buffer == null || !buffer.hasContent()) {
273: if (trailer != null && trailer.hasContent())
274: len += flush(trailer);
275: }
276:
277: return len;
278:
279: }
280:
281: public int flush(Buffer buffer) throws IOException {
282: // sometimes flush nothing
283: if (random.nextInt(10) < 2) {
284: // System.err.println("flush:"+0);
285: return 0;
286: }
287:
288: // flush a random amount of data
289: int len = random.nextInt(20 * rate);
290: if (len > buffer.length())
291: len = buffer.length();
292:
293: // Load a length limited slice via a temp buffer
294: Buffer temp = buffer.get(len);
295: System.err.print(temp);
296: return len;
297: }
298:
299: public boolean isBlocking() {
300: return false;
301: }
302:
303: }
304:
305: public static void main(String[] arg) throws Exception {
306: // Just a little test main....
307:
308: Server server = new Server();
309: server.addConnector(new RandomConnector());
310: Context context = new Context(server, "/", Context.SESSIONS);
311: context.addServlet(new ServletHolder(new HelloServlet()), "/*");
312:
313: server.start();
314: server.join();
315: }
316:
317: public static class HelloServlet extends HttpServlet {
318: protected void doGet(HttpServletRequest request,
319: HttpServletResponse response) throws ServletException,
320: IOException {
321: response.setContentType("text/html");
322: response.setStatus(HttpServletResponse.SC_OK);
323: PrintWriter out = response.getWriter();
324: out.println("<h1>Hello SimpleServlet: "
325: + request.getRequestURI() + "</h1><pre>");
326: int lines = random.nextInt(100);
327: for (int i = 0; i < lines; i++)
328: out
329: .println(i
330: + " Blah blah blah. Now is the time for all good FSMs to work. Hoooo nooo broooon cooooo");
331: out.println("</pre>");
332: }
333: }
334:
335: }
|