Source Code Cross Referenced for PseudoServer.java in  » Testing » HttpUnit » com » meterware » pseudoserver » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Testing » HttpUnit » com.meterware.pseudoserver 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        package com.meterware.pseudoserver;
002:
003:        /********************************************************************************************************************
004:         * $Id: PseudoServer.java,v 1.16 2004/04/20 16:35:21 russgold Exp $
005:         *
006:         * Copyright (c) 2000-2003, Russell Gold
007:         *
008:         * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
009:         * documentation files (the "Software"), to deal in the Software without restriction, including without limitation
010:         * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and
011:         * to permit persons to whom the Software is furnished to do so, subject to the following conditions:
012:         *
013:         * The above copyright notice and this permission notice shall be included in all copies or substantial portions
014:         * of the Software.
015:         *
016:         * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO
017:         * THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
018:         * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
019:         * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
020:         * DEALINGS IN THE SOFTWARE.
021:         *
022:         *******************************************************************************************************************/
023:        import java.io.*;
024:
025:        import java.net.HttpURLConnection;
026:        import java.net.ServerSocket;
027:        import java.net.Socket;
028:
029:        import java.util.*;
030:
031:        /**
032:         * A basic simulated web-server for testing user agents without a web server.
033:         **/
034:        public class PseudoServer {
035:
036:            private static final int DEFAULT_SOCKET_TIMEOUT = 1000;
037:
038:            private static final int INPUT_POLL_INTERVAL = 10;
039:
040:            /** Time in msec to wait for an outstanding server socket to be released before creating a new one. **/
041:            private static int _socketReleaseWaitTime = 50;
042:
043:            /** Number of outstanding server sockets that must be present before trying to wait for one to be released. **/
044:            private static int _waitThreshhold = 10;
045:
046:            private static int _numServers = 0;
047:
048:            private int _serverNum = 0;
049:
050:            private int _connectionNum = 0;
051:
052:            private ArrayList _classpathDirs = new ArrayList();
053:
054:            private String _maxProtocolLevel = "1.1";
055:
056:            private final int _socketTimeout;
057:
058:            /**
059:             * Returns the amount of time the pseudo server will wait for a server socket to be released (in msec)
060:             * before allocating a new one. See also {@link #getWaitThreshhold getWaitThreshhold}.
061:             */
062:            public static int getSocketReleaseWaitTime() {
063:                return _socketReleaseWaitTime;
064:            }
065:
066:            /**
067:             * Returns the amount of time the pseudo server will wait for a server socket to be released (in msec)
068:             * before allocating a new one. See also {@link #getWaitThreshhold getWaitThreshhold}.
069:             */
070:            public static void setSocketReleaseWaitTime(
071:                    int socketReleaseWaitTime) {
072:                _socketReleaseWaitTime = socketReleaseWaitTime;
073:            }
074:
075:            /**
076:             * Returns the number of server sockets that must have been allocated and not returned before waiting for one
077:             * to be returned.
078:             */
079:            public static int getWaitThreshhold() {
080:                return _waitThreshhold;
081:            }
082:
083:            /**
084:             * Specifies the number of server sockets that must have been allocated and not returned before waiting for one
085:             * to be returned.
086:             */
087:            public static void setWaitThreshhold(int waitThreshhold) {
088:                _waitThreshhold = waitThreshhold;
089:            }
090:
091:            public PseudoServer() {
092:                this (DEFAULT_SOCKET_TIMEOUT);
093:            }
094:
095:            public PseudoServer(int socketTimeout) {
096:                _socketTimeout = socketTimeout;
097:                _serverNum = ++_numServers;
098:                Thread t = new Thread("PseudoServer " + _serverNum) {
099:                    public void run() {
100:                        while (_active) {
101:                            try {
102:                                handleNewConnection(getServerSocket().accept());
103:                                Thread.sleep(20);
104:                            } catch (InterruptedIOException e) {
105:                            } catch (IOException e) {
106:                                System.out.println("Error in pseudo server: "
107:                                        + e);
108:                                e.printStackTrace();
109:                            } catch (InterruptedException e) {
110:                                System.out
111:                                        .println("Interrupted. Shutting down");
112:                                _active = false;
113:                            }
114:                        }
115:                        try {
116:                            if (_serverSocket != null)
117:                                ServerSocketFactory.release(_serverSocket);
118:                            _serverSocket = null;
119:                        } catch (IOException e) {
120:                        }
121:                    }
122:                };
123:                t.start();
124:            }
125:
126:            public void shutDown() {
127:                if (_debug)
128:                    System.out
129:                            .println("** Requested shutdown of pseudoserver: "
130:                                    + hashCode());
131:                _active = false;
132:            }
133:
134:            public void setMaxProtocolLevel(int majorLevel, int minorLevel) {
135:                _maxProtocolLevel = majorLevel + "." + minorLevel;
136:            }
137:
138:            /**
139:             * Returns the port on which this server is listening.
140:             **/
141:            public int getConnectedPort() throws IOException {
142:                return getServerSocket().getLocalPort();
143:            }
144:
145:            /**
146:             * Defines the contents of an expected resource.
147:             **/
148:            public void setResource(String name, String value) {
149:                setResource(name, value, "text/html");
150:            }
151:
152:            /**
153:             * Defines the contents of an expected resource.
154:             **/
155:            public void setResource(String name, PseudoServlet servlet) {
156:                _resources.put(asResourceName(name), servlet);
157:            }
158:
159:            /**
160:             * Defines the contents of an expected resource.
161:             **/
162:            public void setResource(String name, String value,
163:                    String contentType) {
164:                _resources.put(asResourceName(name), new WebResource(value,
165:                        contentType));
166:            }
167:
168:            /**
169:             * Defines the contents of an expected resource.
170:             **/
171:            public void setResource(String name, byte[] value,
172:                    String contentType) {
173:                _resources.put(asResourceName(name), new WebResource(value,
174:                        contentType));
175:            }
176:
177:            /**
178:             * Defines a resource which will result in an error message.
179:             **/
180:            public void setErrorResource(String name, int errorCode,
181:                    String errorMessage) {
182:                _resources.put(asResourceName(name), new WebResource(
183:                        errorMessage, errorCode));
184:            }
185:
186:            /**
187:             * Enables the sending of the character set in the content-type header.
188:             **/
189:            public void setSendCharacterSet(String name, boolean enabled) {
190:                WebResource resource = (WebResource) _resources
191:                        .get(asResourceName(name));
192:                if (resource == null)
193:                    throw new IllegalArgumentException("No defined resource "
194:                            + name);
195:                resource.setSendCharacterSet(enabled);
196:            }
197:
198:            /**
199:             * Specifies the character set encoding for a resource.
200:             **/
201:            public void setCharacterSet(String name, String characterSet) {
202:                WebResource resource = (WebResource) _resources
203:                        .get(asResourceName(name));
204:                if (resource == null) {
205:                    resource = new WebResource("");
206:                    _resources.put(asResourceName(name), resource);
207:                }
208:                resource.setCharacterSet(characterSet);
209:            }
210:
211:            /**
212:             * Adds a header to a defined resource.
213:             **/
214:            public void addResourceHeader(String name, String header) {
215:                WebResource resource = (WebResource) _resources
216:                        .get(asResourceName(name));
217:                if (resource == null) {
218:                    resource = new WebResource("");
219:                    _resources.put(asResourceName(name), resource);
220:                }
221:                resource.addHeader(header);
222:            }
223:
224:            public void mapToClasspath(String directory) {
225:                _classpathDirs.add(directory);
226:            }
227:
228:            public void setDebug(boolean debug) {
229:                _debug = debug;
230:            }
231:
232:            //------------------------------------- private members ---------------------------------------
233:
234:            private Hashtable _resources = new Hashtable();
235:
236:            private boolean _active = true;
237:
238:            private boolean _debug;
239:
240:            private String asResourceName(String rawName) {
241:                if (rawName.startsWith("http:") || rawName.startsWith("/")) {
242:                    return escape(rawName);
243:                } else {
244:                    return escape("/" + rawName);
245:                }
246:            }
247:
248:            private static String escape(String urlString) {
249:                if (urlString.indexOf(' ') < 0)
250:                    return urlString;
251:                StringBuffer sb = new StringBuffer();
252:
253:                int start = 0;
254:                do {
255:                    int index = urlString.indexOf(' ', start);
256:                    if (index < 0) {
257:                        sb.append(urlString.substring(start));
258:                        break;
259:                    } else {
260:                        sb.append(urlString.substring(start, index)).append(
261:                                "%20");
262:                        start = index + 1;
263:                    }
264:                } while (true);
265:                return sb.toString();
266:            }
267:
268:            private void handleNewConnection(final Socket socket) {
269:                Thread t = new Thread("PseudoServer " + _serverNum
270:                        + " connection " + (++_connectionNum)) {
271:                    public void run() {
272:                        try {
273:                            serveRequests(socket);
274:                        } catch (IOException e) {
275:                            e.printStackTrace(); //To change body of catch statement use Options | File Templates.
276:                        }
277:                    }
278:                };
279:                t.start();
280:            }
281:
282:            private void serveRequests(Socket socket) throws IOException {
283:                socket.setSoTimeout(_socketTimeout);
284:                socket.setTcpNoDelay(true);
285:
286:                if (_debug)
287:                    System.out.println("** Created server thread: "
288:                            + hashCode());
289:                final BufferedInputStream inputStream = new BufferedInputStream(
290:                        socket.getInputStream());
291:                final HttpResponseStream outputStream = new HttpResponseStream(
292:                        socket.getOutputStream());
293:
294:                while (_active) {
295:                    HttpRequest request = new HttpRequest(inputStream);
296:                    boolean keepAlive = respondToRequest(request, outputStream);
297:                    if (!keepAlive)
298:                        break;
299:                    while (_active && 0 == inputStream.available()) {
300:                        try {
301:                            Thread.sleep(INPUT_POLL_INTERVAL);
302:                        } catch (InterruptedException e) {
303:                        }
304:                    }
305:                }
306:                if (_debug)
307:                    System.out.println("** Closing server thread: "
308:                            + hashCode());
309:                outputStream.close();
310:                socket.close();
311:            }
312:
313:            private boolean respondToRequest(HttpRequest request,
314:                    HttpResponseStream response) {
315:                if (_debug)
316:                    System.out.println("** Server thread " + hashCode()
317:                            + " handling request: " + request);
318:                boolean keepAlive = isKeepAlive(request);
319:                WebResource resource = null;
320:                try {
321:                    response.restart();
322:                    response.setProtocol(getResponseProtocol(request));
323:                    resource = getResource(request);
324:                    if (resource == null) {
325:                        response.setResponse(HttpURLConnection.HTTP_NOT_FOUND,
326:                                "unable to find " + request.getURI());
327:                    } else {
328:                        if (resource.closesConnection())
329:                            keepAlive = false;
330:                        if (resource.getResponseCode() != HttpURLConnection.HTTP_OK) {
331:                            response
332:                                    .setResponse(resource.getResponseCode(), "");
333:                        }
334:                        String[] headers = resource.getHeaders();
335:                        for (int i = 0; i < headers.length; i++) {
336:                            if (_debug)
337:                                System.out.println("** Server thread "
338:                                        + hashCode() + " sending header: "
339:                                        + headers[i]);
340:                            response.addHeader(headers[i]);
341:                        }
342:                    }
343:                } catch (UnknownMethodException e) {
344:                    response.setResponse(HttpURLConnection.HTTP_BAD_METHOD,
345:                            "unsupported method: " + e.getMethod());
346:                } catch (Throwable t) {
347:                    t.printStackTrace();
348:                    response.setResponse(HttpURLConnection.HTTP_INTERNAL_ERROR,
349:                            t.toString());
350:                }
351:                try {
352:                    response.write(resource);
353:                } catch (IOException e) {
354:                    System.out.println("*** Failed to send reply: " + e);
355:                }
356:                return keepAlive;
357:            }
358:
359:            private boolean isKeepAlive(HttpRequest request) {
360:                return request.wantsKeepAlive()
361:                        && _maxProtocolLevel.equals("1.1");
362:            }
363:
364:            private String getResponseProtocol(HttpRequest request) {
365:                return _maxProtocolLevel.equalsIgnoreCase("1.1") ? request
366:                        .getProtocol() : "HTTP/1.0";
367:            }
368:
369:            private WebResource getResource(HttpRequest request)
370:                    throws IOException {
371:                Object resource = _resources.get(request.getURI());
372:                if (resource == null)
373:                    resource = _resources.get(withoutParameters(request
374:                            .getURI()));
375:
376:                if (request.getCommand().equals("GET")
377:                        && resource instanceof  WebResource) {
378:                    return (WebResource) resource;
379:                } else if (resource instanceof  PseudoServlet) {
380:                    return getResource((PseudoServlet) resource, request);
381:                } else if (request.getURI().endsWith(".class")) {
382:                    for (Iterator iterator = _classpathDirs.iterator(); iterator
383:                            .hasNext();) {
384:                        String directory = (String) iterator.next();
385:                        if (request.getURI().startsWith(directory)) {
386:                            String resourceName = request.getURI().substring(
387:                                    directory.length() + 1);
388:                            return new WebResource(getClass().getClassLoader()
389:                                    .getResourceAsStream(resourceName),
390:                                    "application/class", 200);
391:                        }
392:                    }
393:                    return null;
394:                } else if (request.getURI().endsWith(".zip")
395:                        || request.getURI().endsWith(".jar")) {
396:                    for (Iterator iterator = _classpathDirs.iterator(); iterator
397:                            .hasNext();) {
398:                        String directory = (String) iterator.next();
399:                        if (request.getURI().startsWith(directory)) {
400:                            String resourceName = request.getURI().substring(
401:                                    directory.length() + 1);
402:                            String classPath = System
403:                                    .getProperty("java.class.path");
404:                            StringTokenizer st = new StringTokenizer(classPath,
405:                                    ":;,");
406:                            while (st.hasMoreTokens()) {
407:                                String file = st.nextToken();
408:                                if (file.endsWith(resourceName)) {
409:                                    File f = new File(file);
410:                                    return new WebResource(new FileInputStream(
411:                                            f), "application/zip", 200);
412:                                }
413:                            }
414:                        }
415:                    }
416:                    return null;
417:                } else {
418:                    return null;
419:                }
420:            }
421:
422:            private String withoutParameters(String uri) {
423:                return uri.indexOf('?') < 0 ? uri : uri.substring(0, uri
424:                        .indexOf('?'));
425:            }
426:
427:            private WebResource getResource(PseudoServlet servlet,
428:                    HttpRequest request) throws IOException {
429:                servlet.init(request);
430:                return servlet.getResponse(request.getCommand());
431:            }
432:
433:            private ServerSocket getServerSocket() throws IOException {
434:                synchronized (this ) {
435:                    if (_serverSocket == null)
436:                        _serverSocket = ServerSocketFactory.newServerSocket();
437:                }
438:                return _serverSocket;
439:            }
440:
441:            private ServerSocket _serverSocket;
442:
443:        }
444:
445:        class HttpResponseStream {
446:
447:            final private static String CRLF = "\r\n";
448:
449:            void restart() {
450:                _headersWritten = false;
451:                _headers.clear();
452:                _responseCode = HttpURLConnection.HTTP_OK;
453:                _responseText = "OK";
454:            }
455:
456:            void close() throws IOException {
457:                flushHeaders();
458:                _pw.close();
459:            }
460:
461:            HttpResponseStream(OutputStream stream) {
462:                _stream = stream;
463:                try {
464:                    setCharacterSet("us-ascii");
465:                } catch (UnsupportedEncodingException e) {
466:                    _pw = new PrintWriter(new OutputStreamWriter(_stream));
467:                }
468:            }
469:
470:            void setProtocol(String protocol) {
471:                _protocol = protocol;
472:            }
473:
474:            void setResponse(int responseCode, String responseText) {
475:                _responseCode = responseCode;
476:                _responseText = responseText;
477:            }
478:
479:            void addHeader(String header) {
480:                _headers.addElement(header);
481:            }
482:
483:            void write(String contents, String charset) throws IOException {
484:                flushHeaders();
485:                setCharacterSet(charset);
486:                sendText(contents);
487:            }
488:
489:            void write(WebResource resource) throws IOException {
490:                flushHeaders();
491:                if (resource != null)
492:                    resource.writeTo(_stream);
493:                _stream.flush();
494:            }
495:
496:            private void setCharacterSet(String characterSet)
497:                    throws UnsupportedEncodingException {
498:                if (_pw != null)
499:                    _pw.flush();
500:                _pw = new PrintWriter(new OutputStreamWriter(_stream,
501:                        characterSet));
502:            }
503:
504:            private void flushHeaders() {
505:                if (!_headersWritten) {
506:                    sendResponse(_responseCode, _responseText);
507:                    for (Enumeration e = _headers.elements(); e
508:                            .hasMoreElements();) {
509:                        sendLine((String) e.nextElement());
510:                    }
511:                    sendText(CRLF);
512:                    _headersWritten = true;
513:                    _pw.flush();
514:                }
515:            }
516:
517:            private void sendResponse(int responseCode, String responseText) {
518:                sendLine(_protocol + ' ' + responseCode + ' ' + responseText);
519:            }
520:
521:            private void sendLine(String text) {
522:                sendText(text);
523:                sendText(CRLF);
524:            }
525:
526:            private void sendText(String text) {
527:                _pw.write(text);
528:            }
529:
530:            private OutputStream _stream;
531:            private PrintWriter _pw;
532:
533:            private Vector _headers = new Vector();
534:            private String _protocol = "HTTP/1.0";
535:            private int _responseCode = HttpURLConnection.HTTP_OK;
536:            private String _responseText = "OK";
537:
538:            private boolean _headersWritten;
539:
540:        }
541:
542:        class ServerSocketFactory {
543:
544:            static private ArrayList _sockets = new ArrayList();
545:
546:            static private int _outstandingSockets;
547:
548:            static private Object _releaseSemaphore = new Object();
549:
550:            static synchronized ServerSocket newServerSocket()
551:                    throws IOException {
552:                if (_sockets.isEmpty()
553:                        && _outstandingSockets > PseudoServer
554:                                .getWaitThreshhold()) {
555:                    try {
556:                        synchronized (_releaseSemaphore) {
557:                            _releaseSemaphore.wait(PseudoServer
558:                                    .getSocketReleaseWaitTime());
559:                        }
560:                    } catch (InterruptedException e) {
561:                    }
562:                    ;
563:                }
564:                _outstandingSockets++;
565:                if (!_sockets.isEmpty()) {
566:                    return (ServerSocket) _sockets.remove(0);
567:                } else {
568:                    ServerSocket serverSocket = new ServerSocket(0);
569:                    serverSocket.setSoTimeout(1000);
570:                    return serverSocket;
571:                }
572:            }
573:
574:            static synchronized void release(ServerSocket serverSocket)
575:                    throws IOException {
576:                if (_sockets.size() >= 2 * PseudoServer.getWaitThreshhold()) {
577:                    serverSocket.close();
578:                } else {
579:                    _sockets.add(serverSocket);
580:                    _outstandingSockets--;
581:                    synchronized (_releaseSemaphore) {
582:                        _releaseSemaphore.notify();
583:                    }
584:                }
585:            }
586:        }
587:
588:        class RecordingOutputStream extends OutputStream {
589:
590:            private OutputStream _nestedStream;
591:            private PrintStream _log;
592:
593:            public RecordingOutputStream(OutputStream nestedStream,
594:                    PrintStream log) {
595:                _nestedStream = nestedStream;
596:                _log = log;
597:            }
598:
599:            public void write(int b) throws IOException {
600:                _nestedStream.write(b);
601:                _log.println("sending " + Integer.toHexString(b));
602:            }
603:
604:            public void write(byte b[], int offset, int len) throws IOException {
605:                _nestedStream.write(b, offset, len);
606:                _log.print("sending");
607:                for (int i = offset; i < offset + len; i++) {
608:                    _log.print(' ' + Integer.toHexString(b[i]));
609:                }
610:                _log.println();
611:            }
612:        }
613:
614:        class RecordingInputStream extends InputStream {
615:
616:            private InputStream _nestedStream;
617:            private PrintStream _log;
618:
619:            public RecordingInputStream(InputStream nestedStream,
620:                    PrintStream log) {
621:                _nestedStream = nestedStream;
622:                _log = log;
623:            }
624:
625:            public int read() throws IOException {
626:                int value = _nestedStream.read();
627:                if (value != -1)
628:                    _log.print(' ' + Integer.toHexString(value));
629:                return value;
630:            }
631:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.