Source Code Cross Referenced for HttpBasicServer.java in  » Web-Server » Jigsaw » org » w3c » www » protocol » http » 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 » Web Server » Jigsaw » org.w3c.www.protocol.http 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        // HttpBasicServer.java
0002:        // $Id: HttpBasicServer.java,v 1.73 2005/06/03 09:13:35 ylafon Exp $
0003:        // (c) COPYRIGHT MIT and INRIA, 1996.
0004:        // Please first read the full copyright statement in file COPYRIGHT.html
0005:
0006:        package org.w3c.www.protocol.http;
0007:
0008:        import java.util.Date;
0009:
0010:        import java.io.BufferedInputStream;
0011:        import java.io.DataOutputStream;
0012:        import java.io.IOException;
0013:        import java.io.InputStream;
0014:        import java.io.OutputStream;
0015:        import java.io.PrintStream;
0016:
0017:        import java.net.InetAddress;
0018:        import java.net.UnknownHostException;
0019:
0020:        import org.w3c.www.mime.MimeHeaderHolder;
0021:        import org.w3c.www.mime.MimeParser;
0022:        import org.w3c.www.mime.MimeParserException;
0023:        import org.w3c.www.mime.MimeParserFactory;
0024:
0025:        import org.w3c.www.http.HTTP;
0026:        import org.w3c.www.http.HttpEntityMessage;
0027:        import org.w3c.www.http.HttpMessage;
0028:        import org.w3c.www.http.HttpReplyMessage;
0029:        import org.w3c.www.http.HttpRequestMessage;
0030:        import org.w3c.www.http.HttpStreamObserver;
0031:        import org.w3c.www.http.ChunkedOutputStream;
0032:
0033:        /**
0034:         * The basic server class, to run requests.
0035:         * A server instance (ie an object conforming to the <code>HttpServer</code>
0036:         * interface is resposnsible for running all requests to a given host.
0037:         * <p>To do so, it manages a connnnection pool (ie a set of available
0038:         * connections) which it negotiates with the global HTTP manager. It keeps
0039:         * track of the connections it creates in order to serialize requests
0040:         * to the target server (when possible). In order to avoid deadlock due
0041:         * to implicit ordering of requests, a server that manages persistent
0042:         * (ie > 1.0) connections will always be able to open at least two
0043:         * connections to the same target.
0044:         * <p>Connections are kept track of by the server instance, which maintains
0045:         * at all point in time a list of <em>idle</em> connections. The way this is
0046:         * done may seem quite tricky, but beleive me, it's the best way I have
0047:         * found to handle it (there is here a typical deadlock situation - the same
0048:         * which is found in org.w3c.jigsaw.http.Client 
0049:         * - due to the fact that the server instances need to be locked in order
0050:         * to change the connection pool, and at the same time each connection of 
0051:         * the pool might have to notify the pool  of some events. This can easily
0052:         * produce a deadlock...This situation is avoided here, by having the server 
0053:         * locked only when appropriate...
0054:         */
0055:
0056:        public class HttpBasicServer extends HttpServer {
0057:            private static final String STATE_CONNECTION = "org.w3c.www.protocol.http.HttpBasicServer.connection";
0058:
0059:            private static final String PROTOCOL = "http";
0060:            private static final boolean debug = false;
0061:
0062:            /**
0063:             * Request mode - Full HTTP/1.1 compliant mode.
0064:             */
0065:            protected final static int RQ_HTTP11 = 1;
0066:            /**
0067:             * Request mode - Full two stage HTTP/1.1 compliant mode.
0068:             */
0069:            protected final static int RQ_HTTP11_TS = 2;
0070:            /**
0071:             * Request mode - HTTP/1.0 with no keep-alive support.
0072:             */
0073:            protected final static int RQ_HTTP10 = 3;
0074:            /**
0075:             * Request mode - HTTP/1.0 with keep-alive support.
0076:             */
0077:            protected final static int RQ_HTTP10_KA = 4;
0078:            /**
0079:             * Request mode - Unknown target server.
0080:             */
0081:            protected final static int RQ_UNKNOWN = 5;
0082:
0083:            /**
0084:             * Our central HTTP manager.
0085:             */
0086:            protected HttpManager manager = null;
0087:            /**
0088:             * The host name of the server we handle.
0089:             */
0090:            protected String host = null;
0091:            /**
0092:             * The port number of the server we handle.
0093:             */
0094:            protected int port = -1;
0095:            /**
0096:             * The timeout on the socket
0097:             */
0098:            protected int timeout = 300000;
0099:            /**
0100:             * The connectiontimeout for the socket
0101:             */
0102:            protected int conn_timeout = 3000;
0103:
0104:            // Informations pertaining to the server:
0105:            boolean contacted = false;
0106:            short major = -1;
0107:            short minor = -1;
0108:            boolean keepalive = false;
0109:
0110:            InetAddress addrs[] = null;
0111:            int addrptr = 0;
0112:            Date lookupLimit = null;
0113:
0114:            /**
0115:             * set the inet addresses of this host, and timestamp it
0116:             * to avoid caching IPs forever
0117:             * @param hostAddrs, an array of InetAddress
0118:             */
0119:            protected void setHostAddr(InetAddress hostAddrs[]) {
0120:                this .addrs = hostAddrs;
0121:                // reset the pointer in case the number of ip diminished
0122:                addrptr = 0;
0123:                // FIXME now defaults to 300s (5mn) but needs to be a parameter
0124:                lookupLimit = new Date(System.currentTimeMillis() + 300 * 1000);
0125:            }
0126:
0127:            /**
0128:             * check the validity of the host address
0129:             * if invalid, it will update the InetAddress associated with this host
0130:             */
0131:            protected void updateHostAddr() throws HttpException {
0132:                Date now = new Date();
0133:                if ((lookupLimit == null) || lookupLimit.before(now)) {
0134:                    // Get this server IP addreses:
0135:                    try {
0136:                        InetAddress hostAddrs[];
0137:                        // Is the given string a valid IP address ?
0138:                        int hostlen = host.length();
0139:                        boolean isstring = true;
0140:                        for (int i = 0; i < hostlen; i++) {
0141:                            char c = host.charAt(i);
0142:                            if (isstring = !(((c <= '9') && (c >= '0')) || (c == '.'))) {
0143:                                break;
0144:                            }
0145:                        }
0146:                        if (isstring) {
0147:                            // String host name, get all IP addresses:
0148:                            hostAddrs = InetAddress.getAllByName(host);
0149:                        } else {
0150:                            // Numeric IP address, convert to InetAddress:
0151:                            hostAddrs = new InetAddress[1];
0152:                            hostAddrs[0] = InetAddress.getByName(host);
0153:                        }
0154:                        if (hostAddrs != null) {
0155:                            setHostAddr(hostAddrs);
0156:                        }
0157:                    } catch (UnknownHostException ex) {
0158:                        String msg = ("The host name [" + host
0159:                                + "] couldn't be resolved. " + "Details: \""
0160:                                + ex.getMessage() + "\"");
0161:                        HttpException hex = new HttpException(ex, msg);
0162:                        state.ex = hex;
0163:                        state.state = HttpServerState.ERROR;
0164:                        throw hex;
0165:                    }
0166:                }
0167:            }
0168:
0169:            /**
0170:             * HttpServer implementation - Get this servers' protocol.
0171:             * @return A String encoding the protocol used to dialog with the target
0172:             * server.
0173:             */
0174:
0175:            public String getProtocol() {
0176:                return PROTOCOL;
0177:            }
0178:
0179:            /**
0180:             * HttpServer implementation - Get this server's major version number.
0181:             * @return The server's major number version, or <strong>-1</strong>
0182:             * if still unknown.
0183:             */
0184:
0185:            public short getMajorVersion() {
0186:                return major;
0187:            }
0188:
0189:            /**
0190:             * HttpServer implementation - Get this server's minor version number.
0191:             * @return The server's minor number version, or <strong>-1</strong>
0192:             * if still unknown.
0193:             */
0194:
0195:            public short getMinorVersion() {
0196:                return minor;
0197:            }
0198:
0199:            /**
0200:             * Set the timeout for the next connections
0201:             * @param timeout The timeout in milliseconds
0202:             */
0203:
0204:            public synchronized void setTimeout(int timeout) {
0205:                this .timeout = timeout;
0206:            }
0207:
0208:            /**
0209:             * Set the connection timeout for the next connections
0210:             * @param timeout The timeout in milliseconds
0211:             */
0212:
0213:            public synchronized void setConnTimeout(int conn_timeout) {
0214:                this .conn_timeout = conn_timeout;
0215:            }
0216:
0217:            /**
0218:             * Connections management - Allocate a new connection for this server.
0219:             * The connection is bound to the next available IP address, so that
0220:             * we are able to round-robin on them. If one of the DNS advertized
0221:             * IP address fails, we just try the next one, until one of them
0222:             * succeed or all of them fail.
0223:             * @return A freshly allocated connection, inserted in the idle connection
0224:             * list.
0225:             * @exception IOException If the server is unreachable through all of
0226:             * Its IP addresses.
0227:             */
0228:
0229:            protected int connid = 0;
0230:
0231:            protected HttpBasicConnection allocateConnection()
0232:                    throws IOException {
0233:                // Create the new connection, try until all ip addrs have been checked
0234:                HttpBasicConnection conn = null;
0235:                try {
0236:                    updateHostAddr();
0237:                } catch (HttpException hex) {
0238:                    // unable to update, will continue with the old version
0239:                    // as it may be a temporary DNS problem
0240:                    if (addrs == null) {
0241:                        throw new IOException(hex.getMessage());
0242:                    }
0243:                }
0244:                for (int loop = 0; loop < addrs.length; loop++) {
0245:                    InetAddress addr = null;
0246:                    int i = addrptr;
0247:                    do {
0248:                        if ((addr = addrs[i]) != null)
0249:                            break;
0250:                        i = (i + 1) % addrs.length;
0251:                    } while (i != addrptr);
0252:                    addrptr = (addrptr + 1) % addrs.length;
0253:                    if (addr == null) {
0254:                        throw new IOException("Host " + host
0255:                                + " resolved to a null" + " InetAddr");
0256:                    }
0257:                    try {
0258:                        int l_connid;
0259:                        synchronized (this ) {
0260:                            l_connid = connid++;
0261:                        }
0262:                        conn = new HttpBasicConnection(this , l_connid, addr,
0263:                                port, timeout, conn_timeout, manager
0264:                                        .getReplyFactory());
0265:                        break;
0266:                    } catch (IOException ex) {
0267:                        ex.printStackTrace();
0268:                    }
0269:                }
0270:                // If successfull, register the connection as one of ours:
0271:                if (conn == null)
0272:                    throw new IOException("Unable to connect to " + host);
0273:                synchronized (manager) {
0274:                    state.incrConnectionCount();
0275:                    //	    state.allconns.add(conn); (used for debug)
0276:                    manager.notifyConnection(conn);
0277:                }
0278:                return conn;
0279:            }
0280:
0281:            /**
0282:             * Connections management - Register a connection as being idle.
0283:             * When a connection is created, or when it becomes idle again (after
0284:             * having been used to handle a request), it has to be registered back to
0285:             * the idle list of connection for the server. All connections
0286:             * contained in this idle list are candidates for being elected to handle
0287:             * some pending or incoming request to the host we manager.
0288:             * @param conn The connection that is now idle.
0289:             */
0290:
0291:            public void registerConnection(HttpConnection conn) {
0292:                synchronized (manager) {
0293:                    state.registerConnection(conn);
0294:                    manager.notifyIdle(conn);
0295:                }
0296:            }
0297:
0298:            /**
0299:             * Unregister a connection from the idle list.
0300:             * Unregistering a connection means that the server shouldn't keep
0301:             * track of it any more. This can happen in two situations:
0302:             * <ul>
0303:             * <li>The connection won't be reusable, so there is no point
0304:             * for the server to try to keep track of it. In this case, the
0305:             * connection is forgotten, and the caller will terminate it by invoking
0306:             * the connection's input stream close method.
0307:             * <li>The connection has successfully handle a connection, and the
0308:             * connection is about to be reused. During the time of the request
0309:             * processing, the server looses track of this connection, which will
0310:             * register itself again when back to idle.
0311:             * @param conn The connection to unregister from the idle list.
0312:             */
0313:
0314:            public synchronized void unregisterConnection(HttpConnection conn) {
0315:                manager.notifyUse(conn);
0316:            }
0317:
0318:            public void deleteConnection(HttpConnection conn) {
0319:                synchronized (manager) {
0320:                    state.decrConnectionCount();
0321:                    //	    state.allconns.remove(conn); (used for debug)
0322:                    state.unregisterConnection(conn);
0323:                    manager.deleteConnection(conn);
0324:                }
0325:            }
0326:
0327:            /**
0328:             * Connections management - Get an idle connection to run a request.
0329:             * The server has been asked to run a new request, and it now wants 
0330:             * a connection to run it on. This method will try various ways of
0331:             * aqcuiring a connection:
0332:             * <ul>
0333:             * <li>It will look for an idle connection.
0334:             * <li>It will then try to negotiate with the HTTP manager the creation
0335:             * of a new connection to the target server.
0336:             * <li>If this fails too, it will just wait until a connection becomes
0337:             * available.
0338:             * </ul>
0339:             * The connection returned is marked for use (ie it is unregistered from
0340:             * the idle connection list), it is up to the caller to make sure that
0341:             * if possible, the connection registers itself again to the idle list
0342:             * after the processing is done.
0343:             * <p>This method can return <strong>null</strong> to indicate to the 
0344:             * caller that it should try again, in the hope that the target
0345:             * server has multiple (different) IP addresses.
0346:             * @return A connection marked in use, and which should be marked as
0347:             * idle after the processing it is use for is done, or <strong>null
0348:             * </strong> if a fresh connection cannot be established.
0349:             */
0350:
0351:            protected HttpBasicConnection getConnection() throws IOException {
0352:                int _waits = 0;
0353:                while (_waits < 3) {
0354:                    // Ask for a spare connection first:
0355:                    HttpBasicConnection conn = null;
0356:                    while (true) {
0357:                        conn = (HttpBasicConnection) manager
0358:                                .getConnection(this );
0359:                        if (conn == null)
0360:                            break;
0361:                        try {
0362:                            if (conn.sock_m == null) {
0363:                                // otherwise handled by markUsed isAlive call
0364:                                conn.input.available();
0365:                            }
0366:                        } catch (IOException ex) {
0367:                            // mark that connection as dead
0368:                            // unregisterConnection(conn);
0369:                            conn.close();
0370:                            continue;
0371:                        }
0372:                        if (conn.markUsed()) {
0373:                            return conn;
0374:                        }
0375:                    }
0376:                    // Negotiate the creation of a new connection:
0377:                    if (manager.negotiateConnection(this )) {
0378:                        conn = allocateConnection();
0379:                        if (conn.markUsed()) {
0380:                            return conn;
0381:                        } else {
0382:                            // Failed to establish a fresh connection !
0383:                            return null;
0384:                        }
0385:                    }
0386:                    // Wait for a connection to become available:
0387:                    try {
0388:                        long _stime = System.currentTimeMillis();
0389:                        manager.waitForConnection(this );
0390:                        long _etime = System.currentTimeMillis();
0391:                        // if we waited enough... (it avoid bumping _waits if multiple
0392:                        // notify() are sent when closing a bunch of connections
0393:                        if (_etime - _stime > 20000) {
0394:                            if (debug) {
0395:                                System.err.println("wait " + _waits
0396:                                        + " diff is " + (_etime - _stime));
0397:                                System.err.println("ManagerState: " + manager);
0398:                            }
0399:                            _waits++;
0400:                        }
0401:                    } catch (InterruptedException ex) {
0402:                        // interrupted, probably a timeout -> fail
0403:                        return null;
0404:                    }
0405:                }
0406:                return null;
0407:            }
0408:
0409:            /**
0410:             * Display this server into a String.
0411:             * @return A String based representation of the server object.
0412:             */
0413:
0414:            public String toString() {
0415:                return host + ":" + port;
0416:            }
0417:
0418:            /**
0419:             * A full round-trip has been run with the target server, update infos.
0420:             * Each server instance maintains a set of informations to be reused
0421:             * if needed when recontacting the server later. After a full round
0422:             * trip has been performed with the server, it is time to update
0423:             * the target server version number, and keeps-alive flag.
0424:             * @param reply The first reply we got from this server.
0425:             */
0426:
0427:            protected synchronized void updateServerInfo(Reply reply) {
0428:                if (contacted)
0429:                    return;
0430:                major = reply.getMajorVersion();
0431:                minor = reply.getMinorVersion();
0432:                keepalive = reply.keepsAlive();
0433:                contacted = true;
0434:                if (debug)
0435:                    System.out.println("*** " + this  + " major=" + major
0436:                            + ", minor=" + minor + ", ka=" + keepalive);
0437:            }
0438:
0439:            /**
0440:             * HttpServer implementation - Initialize this server to its target.
0441:             * @param manager The central HTTP manager.
0442:             * @param state The manager's state for that server.
0443:             * @param host The target server's host name.
0444:             * @param port The target server's port number.
0445:             * @param timeout The timeout for the connection handled by the server
0446:             * @exception HttpException If the server host couldn't be resolved
0447:             * to one or more IP addresses.
0448:             */
0449:
0450:            public void initialize(HttpManager manager, HttpServerState state,
0451:                    String host, int port, int timeout) throws HttpException {
0452:                initialize(manager, state, host, port, timeout, conn_timeout);
0453:            }
0454:
0455:            /**
0456:             * HttpServer implementation - Initialize this server to its target.
0457:             * @param manager The central HTTP manager.
0458:             * @param state The manager's state for that server.
0459:             * @param host The target server's host name.
0460:             * @param port The target server's port number.
0461:             * @param timeout The timeout for the connection handled by the server
0462:             * @param timeout The connection timeout in millisecond for the sockets
0463:             * @exception HttpException If the server host couldn't be resolved
0464:             * to one or more IP addresses.
0465:             */
0466:
0467:            public void initialize(HttpManager manager, HttpServerState state,
0468:                    String host, int port, int timeout, int conn_timeout)
0469:                    throws HttpException {
0470:                this .manager = manager;
0471:                this .state = state;
0472:                this .host = host;
0473:                this .port = port;
0474:                this .timeout = timeout;
0475:                this .conn_timeout = conn_timeout;
0476:                // Get this server IP addreses:
0477:                this .lookupLimit = null;
0478:                updateHostAddr();
0479:                this .state.state = HttpServerState.OK;
0480:            }
0481:
0482:            // FIXME doc
0483:            protected void notifyObserver(RequestObserver obs, Request request,
0484:                    int code) {
0485:                RequestEvent evt = new RequestEvent(this , request, code);
0486:                obs.notifyProgress(evt);
0487:            }
0488:
0489:            protected void notifyObserver(RequestObserver obs, RequestEvent evt) {
0490:                obs.notifyProgress(evt);
0491:            }
0492:
0493:            /**
0494:             * Is this request a two stage request.
0495:             * @return A boolean, <strong>true</strong> if the request is two
0496:             * stage, <strong>false</strong> otherwise.
0497:             */
0498:
0499:            protected boolean isTwoStage_10(Request request) {
0500:                return request.hasOutputStream();
0501:            }
0502:
0503:            /**
0504:             * Is this request a two stage request.
0505:             * @return A boolean, <strong>true</strong> if the request is two
0506:             * stage, <strong>false</strong> otherwise.
0507:             */
0508:
0509:            protected boolean isTwoStage_11(Request request) {
0510:                boolean hasOutput = request.hasOutputStream();
0511:                if (hasOutput) {
0512:                    if (request.getExpect() != null) // don't test yet the 100-Continue
0513:                        return true;
0514:                }
0515:                return false;
0516:            }
0517:
0518:            /**
0519:             * Get the current mode of running request for that server.
0520:             * This method check our knowledge of the target server, and deduce
0521:             * the mode in which the given request should be run.
0522:             * @return An integer code, indicating the mode in which the request should
0523:             * be run:
0524:             * <dl>
0525:             * <dt>RQ_HTTP11<dl>The request should be run as an HTTP/1.1 request.
0526:             * <dt>RQ_HTTP10<dl>The request should be run as an HTTP/1.0 request.
0527:             * <dt>RQ_HTTP10_KA<dl>HTTP/1.0 with keep-alive support.
0528:             * <dt>RQ_UNKNOWN</dl>This is the first request, we don't know yet.
0529:             * </dl>
0530:             */
0531:
0532:            protected int getRequestMode(Request request) {
0533:                // Fast check for the server (we don't support HTTP/0.9):
0534:                if ((!contacted) || (major < 1))
0535:                    return RQ_UNKNOWN;
0536:                // Is this a 1.0 or 1.1 request ?
0537:                if (minor < 1) {
0538:                    return keepalive ? RQ_HTTP10_KA : RQ_HTTP10;
0539:                } else {
0540:                    // Check for the method now:
0541:                    return isTwoStage_11(request) ? RQ_HTTP11_TS : RQ_HTTP11;
0542:                }
0543:            }
0544:
0545:            /**
0546:             * Run a fully HTTP/1.1 compliant request.
0547:             * This request has no body, so we can do whatever we want with it,
0548:             * and retry as many time as we want.
0549:             * @param conn The connection to run the request on.
0550:             * @param request The request to run.
0551:             * @return A Reply instance, if success; <strong>null</strong> if the 
0552:             * request should be retried.
0553:             * @exception IOException If some IO error occured.
0554:             * @exception MimeParserException If some MIME parsing error occured.
0555:             */
0556:
0557:            protected Reply http11_run(HttpBasicConnection conn, Request request)
0558:                    throws IOException, MimeParserException {
0559:                if (debug)
0560:                    System.out.println(conn + ": runs[11] " + request.getURL());
0561:                RequestObserver o = request.getObserver();
0562:                OutputStream os = conn.getOutputStream();
0563:                MimeParser p = conn.getParser();
0564:                Reply reply = null;
0565:                boolean needsChunk = false;
0566:
0567:                if (request.hasOutputStream()) {
0568:                    if (request.getContentLength() < 0) {
0569:                        needsChunk = true;
0570:                        String tes[] = request.getTransferEncoding();
0571:                        if (tes == null) {
0572:                            // FIXME intern this
0573:                            request.addTransferEncoding("chunked");
0574:                        } else {
0575:                            boolean addIt = true;
0576:                            for (int i = 0; !addIt && (i < tes.length); i++) {
0577:                                addIt = addIt && !tes[i].equals("chunked");
0578:                            }
0579:                            if (addIt) {
0580:                                // FIXME intern this
0581:                                request.addTransferEncoding("chunked");
0582:                            } else {
0583:                                if (os instanceof  ChunkedOutputStream) {
0584:                                    needsChunk = false;
0585:                                }
0586:                            }
0587:                        }
0588:                    }
0589:                }
0590:
0591:                try {
0592:                    request.emit(os, Request.EMIT_HEADERS);
0593:                    os.flush();
0594:                    if (o != null) {
0595:                        notifyObserver(o, new ConnectedEvent(this , request, os));
0596:                    }
0597:                    // We don't expect a "100-continue" so let's dump the body
0598:                    // If any...
0599:                    if (request.hasOutputStream()) {
0600:                        String exp = request.getExpect();
0601:                        if ((exp != null)
0602:                                && (exp.equalsIgnoreCase("100-continue"))) {
0603:                            if (o != null) {
0604:                                // client is expecting a 100 continue let's fake one
0605:                                notifyObserver(o, new ContinueEvent(this ,
0606:                                        request));
0607:                            }
0608:                        }
0609:                        if (needsChunk) {
0610:                            DataOutputStream dos = new DataOutputStream(os);
0611:                            ChunkedOutputStream cos = new ChunkedOutputStream(
0612:                                    dos);
0613:                            request.emit(cos, Request.EMIT_BODY);
0614:                            cos.flush();
0615:                            cos.close(false);
0616:                            request.emit(os, Request.EMIT_FOOTERS);
0617:                        } else {
0618:                            request.emit(os, Request.EMIT_BODY
0619:                                    | Request.EMIT_FOOTERS);
0620:                        }
0621:                        os.flush();
0622:                    }
0623:                    reply = (Reply) p.parse(manager.isLenient());
0624:                    // "eat" the 100 replies FIXME it indicates an error in
0625:                    // the upstream server
0626:                    while ((reply.getStatus() / 100) == 1) {
0627:                        if (o != null) {
0628:                            notifyObserver(o, new ContinueEvent(this , request,
0629:                                    reply));
0630:                        }
0631:                        reply = (Reply) p.parse(manager.isLenient());
0632:                    }
0633:                } catch (MimeParserException ex) {
0634:                    return null;
0635:                } catch (IOException ioex) {
0636:                    return null;
0637:                    // Ok, we should give it another chance:
0638:                }
0639:                if (reply != null) {
0640:                    conn.setCloseOnEOF(reply.hasConnection("close"));
0641:                }
0642:                return reply;
0643:            }
0644:
0645:            /**
0646:             * Run a two stage HTTP/1.1 compliant request.
0647:             * The neat thing about this sort of request is that as they support 
0648:             * <strong>100</strong> status codes, we <em>know</em> when we have
0649:             * to retry them.
0650:             * @param conn The connection to run the request on.
0651:             * @param request The request to run.
0652:             * @return A Reply instance, if success; <strong>null</strong> if the 
0653:             * request should be retried.
0654:             * @exception IOException If some IO error occured.
0655:             * @exception MimeParserException If some MIME parsing error occured.
0656:             */
0657:
0658:            protected Reply http11_ts_run(HttpBasicConnection conn,
0659:                    Request request) throws IOException, MimeParserException {
0660:                if (debug)
0661:                    System.out.println(conn + ": runs[11ts] "
0662:                            + request.getURL());
0663:                RequestObserver o = request.getObserver();
0664:                OutputStream os = conn.getOutputStream();
0665:                MimeParser p = conn.getParser();
0666:                Reply reply = null;
0667:                boolean needsChunk = false;
0668:
0669:                if (request.getContentLength() < 0) {
0670:                    needsChunk = true;
0671:                    String tes[] = request.getTransferEncoding();
0672:                    if (tes == null) {
0673:                        request.addTransferEncoding("chunked"); // FIXME intern this
0674:                    } else {
0675:                        boolean addIt = true;
0676:                        for (int i = 0; !addIt && (i < tes.length); i++) {
0677:                            addIt = addIt && !tes[i].equals("chunked");
0678:                        }
0679:                        if (addIt) {
0680:                            // FIXME intern thi
0681:                            request.addTransferEncoding("chunked");
0682:                        } else {
0683:                            if (os instanceof  ChunkedOutputStream) {
0684:                                needsChunk = false;
0685:                            }
0686:                        }
0687:                    }
0688:                }
0689:
0690:                try {
0691:                    request.emit(os, Request.EMIT_HEADERS);
0692:                    os.flush();
0693:                    if (o != null)
0694:                        notifyObserver(o, new ConnectedEvent(this , request, os));
0695:                    reply = (Reply) p.parse(manager.isLenient());
0696:
0697:                    boolean bodySent = false;
0698:                    while ((reply.getStatus() / 100) == 1
0699:                            || reply.getStatus() == HTTP.EXPECTATION_FAILED) {
0700:                        if (reply.getStatus() == HTTP.EXPECTATION_FAILED)
0701:                            return reply; // FIXME observer?
0702:                        reply = null;
0703:                        // Notify the observer if any:
0704:                        if (o != null) {
0705:                            notifyObserver(o, new ContinueEvent(this , request,
0706:                                    reply));
0707:                        }
0708:                        // Finish the request normally:
0709:                        if (!bodySent) {
0710:                            bodySent = true;
0711:                            if (needsChunk) {
0712:                                DataOutputStream dos = new DataOutputStream(os);
0713:                                ChunkedOutputStream cos = new ChunkedOutputStream(
0714:                                        dos);
0715:                                request.emit(cos, Request.EMIT_BODY);
0716:                                cos.flush();
0717:                                cos.close(false);
0718:                                request.emit(os, Request.EMIT_FOOTERS);
0719:                            } else {
0720:                                request.emit(os, Request.EMIT_BODY
0721:                                        | Request.EMIT_FOOTERS);
0722:                            }
0723:                            os.flush();
0724:                        }
0725:                        reply = (Reply) p.parse(manager.isLenient());
0726:                        // if we don't have any observer, eat the 100 continue!
0727:                        while ((reply.getStatus() / 100) == 1) {
0728:                            if (o != null) {
0729:                                notifyObserver(o, new ContinueEvent(this ,
0730:                                        request, reply));
0731:                            }
0732:                            reply = (Reply) p.parse(manager.isLenient());
0733:                        }
0734:                    }
0735:                } catch (MimeParserException ex) {
0736:                    return null;
0737:                } catch (IOException ieox) {
0738:                    return null;
0739:                }
0740:                if (reply != null) {
0741:                    conn.setCloseOnEOF(reply.hasConnection("close"));
0742:                }
0743:                return reply;
0744:            }
0745:
0746:            /**
0747:             * Run an HTTP/1.0 request that has support for keep alive.
0748:             * This kind of request are the worst one with regard to the retry 
0749:             * strategy we can adopt.
0750:             * @param conn The connection to run the request on.
0751:             * @param request The request to run.
0752:             * @return A Reply instance, if success; <strong>null</strong> if the 
0753:             * request should be retried.
0754:             * @exception IOException If some IO error occured.
0755:             * @exception MimeParserException If some MIME parsing error occured.
0756:             */
0757:
0758:            protected Reply http10_ka_run(HttpBasicConnection conn,
0759:                    Request request) throws IOException, MimeParserException {
0760:                if (debug)
0761:                    System.out.println(conn + ": runs[10_ka] "
0762:                            + request.getURL());
0763:                RequestObserver o = request.getObserver();
0764:                OutputStream os = conn.getOutputStream();
0765:                MimeParser p = conn.getParser();
0766:                Reply reply = null;
0767:                String exp = request.getExpect();
0768:
0769:                if ((exp != null) && (exp.equalsIgnoreCase("100-continue"))) {
0770:                    reply = request.makeReply(HTTP.EXPECTATION_FAILED);
0771:                    reply
0772:                            .setContent("100-continue is not supported by upstream "
0773:                                    + "HTTP/1.0 Server");
0774:                    return reply;
0775:                }
0776:                if (request.getConnection() == null) {
0777:                    if (request.hasProxy()) {
0778:                        request.addProxyConnection("Keep-Alive");
0779:                    } else {
0780:                        request.addConnection("Keep-Alive");
0781:                    }
0782:                }
0783:                try {
0784:                    request.emit(os, Request.EMIT_HEADERS);
0785:                    os.flush();
0786:                } catch (IOException ioex) {
0787:                    return null;
0788:                }
0789:                if (o != null)
0790:                    notifyObserver(o, new ConnectedEvent(this , request, os));
0791:                // If this is a two stage method, emit a fake continue event:
0792:                if (isTwoStage_10(request)) {
0793:                    if (o != null)
0794:                        notifyObserver(o, new ContinueEvent(this , request));
0795:                    request.emit(os, Request.EMIT_BODY | Request.EMIT_FOOTERS);
0796:                    os.flush();
0797:                }
0798:                try {
0799:                    reply = (Reply) p.parse(manager.isLenient());
0800:                    // if ever we switch to 1.1 in the meantime...
0801:                    while ((reply.getStatus() / 100) == 1) {
0802:                        if (o != null) {
0803:                            notifyObserver(o, new ContinueEvent(this , request,
0804:                                    reply));
0805:                        }
0806:                        reply = null;
0807:                        reply = (Reply) p.parse(manager.isLenient());
0808:                    }
0809:                } catch (IOException ex) {
0810:                    // at this point, we try to parse the reply if we have a body
0811:                    if (isTwoStage_10(request)) {
0812:                        try {
0813:                            reply = (Reply) p.parse(manager.isLenient());
0814:                        } catch (MimeParserException mex) {
0815:                            // a stale connection?
0816:                            return null;
0817:                        }
0818:                        try {
0819:                            request.getOutputStream().close();
0820:                        } catch (Exception cex) {
0821:                        }
0822:                        ;
0823:                        return reply;
0824:                    }
0825:                    return null;
0826:                } catch (MimeParserException ex) {
0827:                }
0828:                if (reply != null) {
0829:                    conn.setCloseOnEOF(reply.hasConnection("close"));
0830:                }
0831:                return reply;
0832:            }
0833:
0834:            /**
0835:             * Run a simple HTTP/1.0 request.
0836:             * This server doesn't support keep-alive, we know the connection is
0837:             * always fresh, we don't need to go into the retry buisness.
0838:             * <p>That's <strong>cool</strong> !
0839:             * @param conn The connection to run the request on.
0840:             * @param request The request to run.
0841:             * @return A Reply instance, if success; <strong>null</strong> if the 
0842:             * request should be retried.
0843:             * @exception IOException If some IO error occured.
0844:             * @exception MimeParserException If some MIME parsing error occured.
0845:             */
0846:
0847:            protected Reply http10_run(HttpBasicConnection conn, Request request)
0848:                    throws IOException, MimeParserException {
0849:                if (debug)
0850:                    System.out.println(conn + ": runs[10] " + request.getURL());
0851:                RequestObserver o = request.getObserver();
0852:                OutputStream os = conn.getOutputStream();
0853:                MimeParser p = conn.getParser();
0854:                Reply reply = null;
0855:                String exp = request.getExpect();
0856:
0857:                if ((exp != null) && (exp.equalsIgnoreCase("100-continue"))) {
0858:                    reply = request.makeReply(HTTP.EXPECTATION_FAILED);
0859:                    reply
0860:                            .setContent("100-continue is not supported by upstream "
0861:                                    + "HTTP/1.0 Server");
0862:                    return reply;
0863:                }
0864:                // Emit the request headers:
0865:                request.emit(os, Request.EMIT_HEADERS);
0866:                os.flush();
0867:                if (o != null) {
0868:                    notifyObserver(o, new ConnectedEvent(this , request, os));
0869:                    // If this is a two stage method, emit a fake continue event:
0870:                    if (isTwoStage_10(request))
0871:                        notifyObserver(o, new ContinueEvent(this , request));
0872:                }
0873:                // Then emit the body:
0874:                try {
0875:                    request.emit(os, Request.EMIT_BODY | Request.EMIT_FOOTERS);
0876:                    os.flush();
0877:                } catch (IOException ex) {
0878:                    // at this point, we try to parse the reply if we have a body
0879:                    if (isTwoStage_10(request)) {
0880:                        try {
0881:                            reply = (Reply) p.parse(manager.isLenient());
0882:                        } catch (MimeParserException mex) {
0883:                            // perhaps nothing so...
0884:                            throw ex;
0885:                        }
0886:                        if (reply != null) {
0887:                            // close the request stream
0888:                            try {
0889:                                request.getOutputStream().close();
0890:                            } catch (Exception cex) {
0891:                            }
0892:                            ;
0893:                            return reply;
0894:                        }
0895:                    }
0896:                    // no reply throw the exception again
0897:                    throw ex;
0898:                }
0899:                // HTTP 100 status codes *are* forbidden here, unless the server
0900:                // switches...
0901:                try {
0902:                    reply = (Reply) p.parse(manager.isLenient());
0903:                    while ((reply.getStatus() / 100) == 1) {
0904:                        if (o != null) {
0905:                            notifyObserver(o, new ContinueEvent(this , request,
0906:                                    reply));
0907:                        }
0908:                        reply = null;
0909:                        reply = (Reply) p.parse(manager.isLenient());
0910:                    }
0911:                } catch (MimeParserException ex) {
0912:                    // be nice to lamers
0913:                }
0914:                conn.setCloseOnEOF(true);
0915:                return reply;
0916:            }
0917:
0918:            /**
0919:             * Run that request, we don't know what server we have at the other end.
0920:             * We know the connection is fresh, we use the <code>http10_run</code>
0921:             * and update the server infos by the end of processing.
0922:             * @param conn The connection to run the request on.
0923:             * @param request The request to run.
0924:             * @return A Reply instance, if success; <strong>null</strong> if the 
0925:             * request should be retried.
0926:             * @exception IOException If some IO error occured.
0927:             * @exception MimeParserException If some MIME parsing error occured.
0928:             */
0929:
0930:            protected Reply http_unknown(HttpBasicConnection conn,
0931:                    Request request) throws IOException, MimeParserException {
0932:                boolean eventfaked = false;
0933:                if (debug)
0934:                    System.out.println(conn + ": runs[unknown] "
0935:                            + request.getURL());
0936:                // Update the request with server specific information:
0937:                if (request.getConnection() == null) {
0938:                    if (request.hasProxy()) {
0939:                        request.addProxyConnection("Keep-Alive");
0940:                    } else {
0941:                        request.addConnection("Keep-Alive");
0942:                    }
0943:                }
0944:                // FIXME neeeds to handle a first request using a chunked body
0945:                // or without body. we need to chack if the server is 1.1
0946:                // then issue the request if it's ok. (expect 100 continue with
0947:                // a timeout?
0948:                // Emit the request:
0949:                RequestObserver o = request.getObserver();
0950:                OutputStream os = conn.getOutputStream();
0951:                MimeParser p = conn.getParser();
0952:                Reply reply = null;
0953:                // Emit the request headers:
0954:                request.emit(os, Request.EMIT_HEADERS);
0955:                if (o != null) {
0956:                    notifyObserver(o, new ConnectedEvent(this , request, os));
0957:                    // If this is a two stage method, try to be nice:
0958:                    if (isTwoStage_10(request)) {
0959:                        // Always emit a fake continue event:
0960:                        eventfaked = true;
0961:                        notifyObserver(o, new ContinueEvent(this , request));
0962:                    }
0963:                }
0964:                // Then emit the body:
0965:                try {
0966:                    request.emit(os, Request.EMIT_BODY | Request.EMIT_FOOTERS);
0967:                    os.flush();
0968:                } catch (IOException ex) {
0969:                    // at this point, we try to parse the reply if we have a body
0970:                    if (isTwoStage_10(request)) {
0971:                        try {
0972:                            reply = (Reply) p.parse(manager.isLenient());
0973:                        } catch (MimeParserException mex) {
0974:                            // perhaps nothing so...
0975:                            throw ex;
0976:                        }
0977:                        if (reply != null) {
0978:                            // close the request stream
0979:                            try {
0980:                                request.getOutputStream().close();
0981:                            } catch (Exception cex) {
0982:                            }
0983:                            ;
0984:                            return reply;
0985:                        }
0986:                    }
0987:                    // no reply throw the exception again
0988:                    throw ex;
0989:                }
0990:                try {
0991:                    reply = (Reply) p.parse(manager.isLenient());
0992:                    while ((reply.getStatus() / 100) == 1) {
0993:                        // If we already faked an event, skip that one:
0994:                        if (eventfaked) {
0995:                            eventfaked = false;
0996:                            continue;
0997:                        }
0998:                        // Notify the observer, if any:
0999:                        if (o != null)
1000:                            notifyObserver(o, new ContinueEvent(this , request,
1001:                                    reply));
1002:                        // Get next reply:
1003:                        reply = (Reply) p.parse(manager.isLenient());
1004:                    }
1005:                    // Now, we know about that server, update infos:
1006:                    if (reply != null) {
1007:                        updateServerInfo(reply);
1008:                    }
1009:                } catch (MimeParserException ex) {
1010:                    // be nice to lamers
1011:                }
1012:                if (reply != null) {
1013:                    if ((major == 1) && ((minor == 1) || keepalive)) {
1014:                        conn.setCloseOnEOF(false);
1015:                    } else {
1016:                        conn.setCloseOnEOF(true);
1017:                    }
1018:                }
1019:                return reply;
1020:            }
1021:
1022:            /**
1023:             * Exceute given request on given conection, according to server.
1024:             * @param conn The connection to use to run that request.
1025:             * @param request The request to execute.
1026:             * @exception IOException If some IO error occurs, or if the 
1027:             * request is interrupted.
1028:             * @exception MimeParserException If taregt server doesn't conform to 
1029:             * the HTTP specification.
1030:             */
1031:
1032:            protected Reply doRequest(HttpBasicConnection conn, Request request)
1033:                    throws IOException, MimeParserException {
1034:                // Check for an interrupted request ?
1035:                if (request.isInterrupted())
1036:                    throw new IOException("Interrupted Request");
1037:                // Mark that request as being processed by that connection:
1038:                request.setState(STATE_CONNECTION, conn);
1039:                // Process the request:
1040:                switch (getRequestMode(request)) {
1041:                case RQ_HTTP11:
1042:                    return http11_run(conn, request);
1043:                case RQ_HTTP11_TS:
1044:                    return http11_ts_run(conn, request);
1045:                case RQ_HTTP10_KA:
1046:                    return http10_ka_run(conn, request);
1047:                case RQ_HTTP10:
1048:                    return http10_run(conn, request);
1049:                case RQ_UNKNOWN:
1050:                    return http_unknown(conn, request);
1051:                default:
1052:                    throw new RuntimeException("Implementation bug.");
1053:                }
1054:                // not reached
1055:            }
1056:
1057:            /**
1058:             * Interrupt given request, that was launched by ourself.
1059:             * @param request The request to interrupt.
1060:             */
1061:
1062:            protected void interruptRequest(Request request) {
1063:                HttpBasicConnection c = null;
1064:                c = (HttpBasicConnection) request.getState(STATE_CONNECTION);
1065:                if (c == null) {
1066:                    // That request has terminated, or has not started
1067:                    ;
1068:                } else {
1069:                    // Just kill the connection, to trigger some IO exception:
1070:                    c.markIdle(true);
1071:                }
1072:            }
1073:
1074:            /**
1075:             * Run the given request in synchronous mode.
1076:             * @param request The request to run.
1077:             * @return A Reply instance, containing the reply headers, and the 
1078:             * optional reply entity, to be read by the calling thread.
1079:             * @exception HttpException If the request processing failed.
1080:             */
1081:
1082:            public Reply runRequest(Request request) throws HttpException {
1083:                RequestObserver o = request.getObserver();
1084:                if (debug) {
1085:                    System.out.println("Running request: " + request.getURL());
1086:                    request.dump(System.out);
1087:                }
1088:                // Acquire a connection to run the request:
1089:                HttpBasicConnection conn = null;
1090:                Reply reply = null;
1091:                Exception lastex = null;
1092:                try {
1093:                    // Notify that request is being queued:
1094:                    if (o != null)
1095:                        notifyObserver(o, request, RequestEvent.EVT_QUEUED);
1096:                    // Allocate a connection and run the request:
1097:                    int maxretry = 1;
1098:                    if (!request.hasOutputStream()) {
1099:                        String method = request.getMethod();
1100:                        if (method.length() <= 6) {
1101:                            method = method.intern();
1102:                            if ((method == HTTP.GET) || (method == HTTP.HEAD)
1103:                                    || (method == HTTP.OPTIONS)
1104:                                    || (method == HTTP.TRACE)) {
1105:                                maxretry = 3;
1106:                            }
1107:                        }
1108:                    }
1109:                    for (int i = 0; (reply == null) && (i < maxretry); i++) {
1110:                        // getConnection can return null, check documentation:
1111:                        if ((conn = getConnection()) == null) {
1112:                            continue;
1113:                        }
1114:                        // if we can't check a connection is OK, we need a hack
1115:                        // (ie if jdk < 1.4...
1116:                        if (maxretry == 1) {
1117:                            if (manager.keepbody) {
1118:                                if (request.hasOutputStream()) {
1119:                                    BufferedInputStream bis;
1120:                                    bis = new BufferedInputStream(request
1121:                                            .getOutputStream());
1122:                                    request.setOutputStream(bis);
1123:                                    int cl = request.getContentLength();
1124:                                    if (cl < 0)
1125:                                        cl = 65536;
1126:                                    bis.mark(cl);
1127:                                }
1128:                            } else {
1129:                                // get only a fresh connection
1130:                                while (conn.cached) {
1131:                                    conn.markIdle(true);
1132:                                    conn = getConnection();
1133:                                }
1134:                            }
1135:                            // idempotent method, so we won't redo it
1136:                        }
1137:                        // Some connection ready, try using it:
1138:                        try {
1139:                            if ((reply = doRequest(conn, request)) == null) {
1140:                                // if a cached connection fails, it may be due
1141:                                // to a socket in bad shape...
1142:                                // workaround for the missing socket.isAlive() method
1143:                                // Get rid of that useless connection:
1144:                                if (conn.cached) {
1145:                                    //			    conn.markIdle(true);
1146:                                    --i;
1147:                                    if (request.hasOutputStream()
1148:                                            && manager.keepbody) {
1149:                                        request.getOutputStream().reset();
1150:                                    }
1151:                                }
1152:                                conn.markIdle(true);
1153:                            }
1154:                        } catch (MimeParserException mex) {
1155:                            lastex = mex;
1156:                            conn.markIdle(true);
1157:                            throw (mex);
1158:                        } catch (Exception ioex) {
1159:                            lastex = ioex;
1160:                            if (debug)
1161:                                ioex.printStackTrace();
1162:                            // connection 1.0 failed so it was not a cached connection
1163:                            // restore the body if ther was one.
1164:                            try {
1165:                                if (request.hasOutputStream()) {
1166:                                    request.getOutputStream().reset();
1167:                                }
1168:                            } catch (IOException mrex) {
1169:                                // mark/reset not supported on the stream
1170:                            } finally {
1171:                                // Get rid of that useless connection:
1172:                                conn.markIdle(true);
1173:                            }
1174:                        } catch (Throwable thro) {
1175:                            conn.markIdle(true);
1176:                        }
1177:                    }
1178:                    if (request.hasOutputStream()) {
1179:                        request.getOutputStream().close();
1180:                    }
1181:                    // Did the request really failed ?
1182:                    if (reply == null) {
1183:                        String msg = ("Unable to contact target server " + this 
1184:                                + " after " + maxretry + " tries.");
1185:                        if (o != null)
1186:                            notifyObserver(o, request,
1187:                                    RequestEvent.EVT_UNREACHABLE);
1188:                        if (lastex != null) {
1189:                            throw new HttpException(request, null, lastex, msg);
1190:                        } else {
1191:                            throw new HttpException(request, msg);
1192:                        }
1193:                    }
1194:                    reply.matchesRequest(request);
1195:                    if (o != null)
1196:                        notifyObserver(o, request, RequestEvent.EVT_REPLIED);
1197:                    // Can we try to reuse the connection ?
1198:                    if (reply.keepsAlive()) {
1199:                        reply.setStreamObserver(conn);
1200:                        // If the reply has no input stream, register the connection:
1201:                        if (!reply.hasInputStream()) {
1202:                            conn.markIdle(false);
1203:                        }
1204:                    } else {
1205:                        conn.detach();
1206:                    }
1207:                    if (debug) {
1208:                        System.out.println("Request done !");
1209:                        reply.dump(System.out);
1210:                    }
1211:                } catch (IOException ex) {
1212:                    ex.printStackTrace();
1213:                    if (conn != null)
1214:                        conn.markIdle(true);
1215:                    if (o != null)
1216:                        notifyObserver(o, request, RequestEvent.EVT_CLOSED);
1217:                    throw new HttpException(request, ex);
1218:                } catch (MimeParserException ex) {
1219:                    ex.printStackTrace();
1220:                    if (conn != null)
1221:                        conn.markIdle(true);
1222:                    if (o != null)
1223:                        notifyObserver(o, request, RequestEvent.EVT_CLOSED);
1224:                    throw new HttpException(request, ex);
1225:                }
1226:                return reply;
1227:            }
1228:
1229:            HttpBasicServer() {
1230:            }
1231:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.