Source Code Cross Referenced for HttpClient.java in  » Web-Server » xsocket » org » xsocket » connection » http » client » 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 » xsocket » org.xsocket.connection.http.client 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /*
002:         *  Copyright (c) xsocket.org, 2006 - 2008. All rights reserved.
003:         *
004:         *  This library is free software; you can redistribute it and/or
005:         *  modify it under the terms of the GNU Lesser General Public
006:         *  License as published by the Free Software Foundation; either
007:         *  version 2.1 of the License, or (at your option) any later version.
008:         *
009:         *  This library is distributed in the hope that it will be useful,
010:         *  but WITHOUT ANY WARRANTY; without even the implied warranty of
011:         *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
012:         *  Lesser General Public License for more details.
013:         *
014:         *  You should have received a copy of the GNU Lesser General Public
015:         *  License along with this library; if not, write to the Free Software
016:         *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
017:         *
018:         * Please refer to the LGPL license at: http://www.gnu.org/copyleft/lesser.txt
019:         * The latest copy of this software may be found on http://www.xsocket.org/
020:         */
021:        package org.xsocket.connection.http.client;
022:
023:        import java.io.Closeable;
024:        import java.io.IOException;
025:        import java.net.ConnectException;
026:        import java.net.MalformedURLException;
027:        import java.net.SocketTimeoutException;
028:        import java.net.URI;
029:        import java.net.URISyntaxException;
030:        import java.net.URL;
031:        import java.nio.channels.ClosedChannelException;
032:        import java.text.SimpleDateFormat;
033:        import java.util.Date;
034:        import java.util.LinkedList;
035:        import java.util.List;
036:        import java.util.concurrent.Executor;
037:        import java.util.logging.Level;
038:        import java.util.logging.Logger;
039:
040:        import javax.net.ssl.SSLContext;
041:
042:        import org.xsocket.ILifeCycle;
043:        import org.xsocket.connection.IConnectionPool;
044:        import org.xsocket.connection.INonBlockingConnection;
045:        import org.xsocket.connection.NonBlockingConnection;
046:        import org.xsocket.connection.NonBlockingConnectionPool;
047:        import org.xsocket.connection.http.BodyDataSink;
048:        import org.xsocket.connection.http.NonBlockingBodyDataSource;
049:        import org.xsocket.connection.http.HttpRequest;
050:        import org.xsocket.connection.http.HttpRequestHeader;
051:        import org.xsocket.connection.http.HttpResponse;
052:        import org.xsocket.connection.http.HttpResponseHeader;
053:        import org.xsocket.connection.http.client.HttpClientConnection.BlockingResponseHandler;
054:        import org.xsocket.connection.http.client.HttpClientConnection.ResponseHandlerAdapter;
055:
056:        /**
057:         * Higher level client-side abstraction of the client side endpoint. The HttpClient uses am internal pool 
058:         * of {@link HttpClientConnection} to perform the requests. 
059:         *
060:         * @author grro@xsocket.org
061:         */
062:        public final class HttpClient implements  IHttpClientEndpoint,
063:                IConnectionPool, Closeable {
064:
065:            private static final Logger LOG = Logger.getLogger(HttpClient.class
066:                    .getName());
067:
068:            public static final int DEFAULT_POOLED_IDLE_TIMEOUT_MILLIS = 5 * 1000;
069:            public static final int DEFAULT_POOLED_LIFE_TIMEOUT_MILLIS = 10 * 1000;
070:
071:            private static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat(
072:                    "yyyy.MM.dd HH:mm:ss");
073:
074:            private static final boolean DEFAULT_IS_TRANSACTION_LOG = true;
075:            public static final int DEFAULT_MAX_REDIRECTS = 5;
076:            public static final boolean DEFAULT_TREAT_302_REDIRECT_AS_303 = false;
077:            public static final Integer DEFAULT_RECEIVE_TIMEOUT_MILLIS = Integer.MAX_VALUE;
078:
079:            private int maxRedirects = DEFAULT_MAX_REDIRECTS;
080:            private boolean isTreat302RedirectAs303 = DEFAULT_TREAT_302_REDIRECT_AS_303;
081:            private int receiveTimeoutMillis = DEFAULT_RECEIVE_TIMEOUT_MILLIS;
082:            private boolean isTransactionLog = DEFAULT_IS_TRANSACTION_LOG;
083:
084:            private SSLContext sslCtx = null;
085:            private NonBlockingConnectionPool pool = null;
086:
087:            private boolean isPooled = true;
088:            private boolean isSSLSupported = false;
089:
090:            // auto handle
091:            boolean isAutohandle100ContinueResponse = DEFAULT_AUTOHANDLE_100CONTINUE_RESPONSE;
092:
093:            // statistics
094:            private TransactionLog transactionLog = new TransactionLog(20);
095:
096:            /**
097:             * constructor 
098:             */
099:            public HttpClient() {
100:                this (null);
101:            }
102:
103:            /**
104:             * constructor 
105:             * 
106:             * @param sslCtx   the ssl context to use
107:             */
108:            public HttpClient(SSLContext sslCtx) {
109:                if (sslCtx != null) {
110:                    this .sslCtx = sslCtx;
111:                    pool = new NonBlockingConnectionPool(sslCtx);
112:                    isSSLSupported = true;
113:                } else {
114:                    pool = new NonBlockingConnectionPool();
115:                    isSSLSupported = false;
116:                }
117:
118:                pool.setPooledIdleTimeoutMillis(DEFAULT_IDLE_TIMEOUT_MILLIS);
119:                pool.setPooledLifeTimeoutMillis(DEFAULT_LIFE_TIMEOUT_MILLIS);
120:            }
121:
122:            public final void setAutohandle100ContinueResponse(
123:                    boolean isAutohandle100ContinueResponse) {
124:                this .isAutohandle100ContinueResponse = isAutohandle100ContinueResponse;
125:            }
126:
127:            public boolean isAutohandle100ContinueResponse() {
128:                return isAutohandle100ContinueResponse;
129:            }
130:
131:            /**
132:             * set the max redirects
133:             * 
134:             * @param maxRedirects  the max redirects 
135:             */
136:            public void setMaxRedirects(int maxRedirects) {
137:                this .maxRedirects = maxRedirects;
138:            }
139:
140:            /**
141:             * get the max redirects 
142:             * 
143:             * @return the max redirects
144:             */
145:            public int getMaxRedirects() {
146:                return maxRedirects;
147:            }
148:
149:            /**
150:             * sets if a 302 response should be treat as a 303 response
151:             *  
152:             * @param isTreat303RedirectAs302 true, if a 303 response should be treat a a 303 response 
153:             */
154:            public void setTreat302RedirectAs303(boolean isTreat303RedirectAs302) {
155:                this .isTreat302RedirectAs303 = isTreat303RedirectAs302;
156:            }
157:
158:            /**
159:             * gets if a 302 response should be treat as a 303 response
160:             * 
161:             * @return true, if a 302 response should be treat as a 303 response
162:             */
163:            public boolean isTreat302RedirectAs303() {
164:                return isTreat302RedirectAs303;
165:            }
166:
167:            /**
168:             * activates the transaction log
169:             *  
170:             * @param isTransactionLog true, if transaction log sholud be activated 
171:             */
172:            void setTransactionLog(boolean isTransactionLog) {
173:                this .isTransactionLog = isTransactionLog;
174:            }
175:
176:            /**
177:             * returns if the transaction log is activated 
178:             * 
179:             * @return true, if the transaction log is activated
180:             */
181:            boolean isTransactionLog() {
182:                return isTransactionLog;
183:            }
184:
185:            /**
186:             * get the max size of the transaction log
187:             * 
188:             * @return the max size of the transaction log
189:             */
190:            int getTransactionLogMaxSize() {
191:                return transactionLog.getMaxSize();
192:            }
193:
194:            /**
195:             * sets the max size of the transaction log
196:             * 
197:             * @param maxSize the max size of the transaction log
198:             */
199:            void setTransactionLogMaxSize(int maxSize) {
200:                transactionLog.setMaxSize(maxSize);
201:            }
202:
203:            /**
204:             * set the worker pool which will be assigned to the connections for call back handling
205:             * @param workerpool the worker pool
206:             */
207:            public void setWorkerpool(Executor workerpool) {
208:                pool.setWorkerpool(workerpool);
209:            }
210:
211:            /**
212:             * returns is pooling is used
213:             *  
214:             * @return true, if pooling is used 
215:             */
216:            public boolean isPooled() {
217:                return isPooled;
218:            }
219:
220:            /**
221:             * sets if pooling is used
222:             * 
223:             * @param isPooled true, if pooling is used
224:             */
225:            public void setPooled(boolean isPooled) {
226:                this .isPooled = isPooled;
227:            }
228:
229:            /**
230:             * {@inheritDoc}
231:             */
232:            public void setResponseTimeoutMillis(int receiveTimeoutMillis) {
233:                this .receiveTimeoutMillis = receiveTimeoutMillis;
234:            }
235:
236:            /**
237:             * {@inheritDoc}
238:             */
239:            public int getResponseTimeoutMillis() {
240:                return receiveTimeoutMillis;
241:            }
242:
243:            /**
244:             * {@inheritDoc}
245:             */
246:            public void close() throws IOException {
247:                pool.close();
248:            }
249:
250:            /**
251:             * {@inheritDoc}
252:             */
253:            public boolean isOpen() {
254:                return pool.isOpen();
255:            }
256:
257:            /**
258:             * returns a unique id 
259:             * 
260:             * @return the id 
261:             */
262:            public String getId() {
263:                return Integer.toString(this .hashCode());
264:            }
265:
266:            /**
267:             * {@inheritDoc}
268:             */
269:            public void addListener(ILifeCycle listener) {
270:                pool.addListener(listener);
271:            }
272:
273:            /**
274:             * {@inheritDoc}
275:             */
276:            public boolean removeListener(ILifeCycle listener) {
277:                return pool.removeListener(listener);
278:            }
279:
280:            /**
281:             * {@inheritDoc}
282:             */
283:            public void setPooledIdleTimeoutMillis(int idleTimeoutMillis) {
284:                pool.setPooledIdleTimeoutMillis(idleTimeoutMillis);
285:            }
286:
287:            /**
288:             * {@inheritDoc}
289:             */
290:            public int getPooledIdleTimeoutMillis() {
291:                return pool.getPooledIdleTimeoutMillis();
292:            }
293:
294:            /**
295:             * {@inheritDoc}
296:             */
297:            public void setPooledLifeTimeoutMillis(int lifeTimeoutMillis) {
298:                pool.setPooledLifeTimeoutMillis(lifeTimeoutMillis);
299:            }
300:
301:            /**
302:             * {@inheritDoc}
303:             */
304:            public int getPooledLifeTimeoutMillis() {
305:                return pool.getPooledLifeTimeoutMillis();
306:            }
307:
308:            /**
309:             * {@inheritDoc}
310:             */
311:            public long getCreationMaxWaitMillis() {
312:                return pool.getCreationMaxWaitMillis();
313:            }
314:
315:            /**
316:             * {@inheritDoc}
317:             */
318:            public void setCreationMaxWaitMillis(long maxWaitMillis) {
319:                pool.setCreationMaxWaitMillis(maxWaitMillis);
320:            }
321:
322:            /**
323:             * {@inheritDoc}
324:             */
325:            public void setMaxIdlePooled(int maxIdle) {
326:                pool.setMaxIdlePooled(maxIdle);
327:            }
328:
329:            /**
330:             * {@inheritDoc}
331:             */
332:            public int getMaxIdlePooled() {
333:                return pool.getMaxIdlePooled();
334:            }
335:
336:            /**
337:             * {@inheritDoc}
338:             */
339:            public void setMaxActivePooled(int maxActive) {
340:                pool.setMaxActivePooled(maxActive);
341:            }
342:
343:            /**
344:             * {@inheritDoc}
345:             */
346:            public int getMaxActivePooled() {
347:                return pool.getMaxActivePooled();
348:            }
349:
350:            /**
351:             * {@inheritDoc}
352:             */
353:            public int getNumPooledActive() {
354:                return pool.getNumPooledActive();
355:            }
356:
357:            /**
358:             * {@inheritDoc}
359:             */
360:            public int getNumPooledIdle() {
361:                return pool.getNumPooledIdle();
362:            }
363:
364:            /**
365:             * {@inheritDoc}
366:             */
367:            int getNumPendingGet() {
368:                return pool.getNumPendingGet();
369:            }
370:
371:            /**
372:             * {@inheritDoc}
373:             */
374:            public int getNumCreated() {
375:                return pool.getNumCreated();
376:            }
377:
378:            /**
379:             * {@inheritDoc}
380:             */
381:            public int getNumDestroyed() {
382:                return pool.getNumDestroyed();
383:            }
384:
385:            /**
386:             * {@inheritDoc}
387:             */
388:            public int getNumTimeoutPooledIdle() {
389:                return pool.getNumTimeoutPooledIdle();
390:            }
391:
392:            /**
393:             * {@inheritDoc}
394:             */
395:            public int getNumTimeoutPooledLifetime() {
396:                return pool.getNumTimeoutPooledLifetime();
397:            }
398:
399:            /**
400:             * {@inheritDoc}
401:             */
402:            public List<String> getActiveConnectionInfos() {
403:                return pool.getActiveConnectionInfos();
404:            }
405:
406:            /**
407:             * {@inheritDoc}
408:             */
409:            public List<String> getIdleConnectionInfos() {
410:                return pool.getIdleConnectionInfos();
411:            }
412:
413:            /**
414:             * returns the transaction log 
415:             * @return the transaction log
416:             */
417:            List<String> getTransactionInfos() {
418:                return transactionLog.getTransactions();
419:            }
420:
421:            /**
422:             * {@inheritDoc}
423:             */
424:            public HttpResponse call(HttpRequest request) throws IOException,
425:                    SocketTimeoutException {
426:
427:                // get connection
428:                URI targetURI = request.getTargetURI();
429:                HttpClientConnection con = getConnection(request.isSecure(),
430:                        targetURI.getHost(), targetURI.getPort(), targetURI
431:                                .getScheme());
432:
433:                // create a response handler 
434:                BlockingResponseHandler responseHandler = new BlockingResponseHandler(
435:                        con, getResponseTimeoutMillis());
436:
437:                // send the request and wait for the response
438:                con.send(request, responseHandler);
439:                HttpResponse response = responseHandler.getResponse();
440:
441:                addTransactionInfo(request, response);
442:                return response;
443:            }
444:
445:            /**
446:             * performs a request, by handling redirects 
447:             * 
448:             * @param request  the request 
449:             * @return the response 
450:             * @throws IOException   if an exception occurs 
451:             * @throws ConnectException if an error occurred while attempting to connect to a remote address and port. 
452:             * @throws SocketTimeoutException if the received timeout is exceed
453:             */
454:            public HttpResponse callFollowRedirects(HttpRequest request)
455:                    throws IOException, ConnectException,
456:                    SocketTimeoutException {
457:                return callFollowRedirects(request, 0);
458:            }
459:
460:            private HttpResponse callFollowRedirects(HttpRequest request,
461:                    int redirectCounter) throws IOException, ConnectException,
462:                    SocketTimeoutException {
463:
464:                if (redirectCounter > maxRedirects) {
465:                    throw new IOException("max redirects " + maxRedirects
466:                            + " reached");
467:                }
468:
469:                HttpResponse response = null;
470:
471:                // duplicate body is redirect is activated
472:                NonBlockingBodyDataSource copiedBody = null;
473:                if (request.hasBody()) {
474:                    copiedBody = request.getNonBlockingBody().duplicate();
475:                }
476:
477:                // get connection and perform call 
478:                URI targetURI = request.getTargetURI();
479:                HttpClientConnection con = getConnection(request.isSecure(),
480:                        targetURI.getHost(), targetURI.getPort(), targetURI
481:                                .getScheme());
482:                response = con.call(request);
483:
484:                addTransactionInfo(request, response);
485:
486:                if (isRedirectResponse(request.getRequestHeader(), response
487:                        .getResponseHeader())) {
488:                    URL newLocation = getRedirectURI(response, request
489:                            .isSecure(), targetURI.getHost(), targetURI
490:                            .getPort());
491:
492:                    try {
493:                        HttpRequestHeader newRequestHeader = new HttpRequestHeader(
494:                                request.getMethod(), newLocation
495:                                        .toExternalForm());
496:                        newRequestHeader.copyHeaderFrom(request
497:                                .getRequestHeader(), "HOST", "CONTENT-LENGTH");
498:
499:                        HttpRequest newRequest = null;
500:                        if ((response.getStatus() == 303)
501:                                || ((response.getStatus() == 302) && isTreat302RedirectAs303)) {
502:                            newRequest = new HttpRequest(newRequestHeader);
503:                            newRequest.setMethod("GET");
504:
505:                        } else {
506:                            newRequest = new HttpRequest(newRequestHeader,
507:                                    copiedBody);
508:                        }
509:
510:                        if (LOG.isLoggable(Level.FINE)) {
511:                            LOG.fine("Sending redirect ");
512:                        }
513:                        response = callFollowRedirects(newRequest,
514:                                ++redirectCounter);
515:                    } catch (URISyntaxException use) {
516:                        throw new IOException(use.toString());
517:                    }
518:                }
519:
520:                return response;
521:            }
522:
523:            /**
524:             * {@inheritDoc}
525:             */
526:            public void send(HttpRequest request,
527:                    IHttpResponseHandler responseHandler) throws IOException,
528:                    ConnectException {
529:
530:                // get connection
531:                URI targetURI = request.getTargetURI();
532:                HttpClientConnection con = getConnection(request.isSecure(),
533:                        targetURI.getHost(), targetURI.getPort(), targetURI
534:                                .getScheme());
535:
536:                // perform call
537:                ResponseHandlerAdapter responseHandlerAdapter = new ResponseHandlerAdapter(
538:                        responseHandler, con, getResponseTimeoutMillis());
539:                con.send(request, responseHandlerAdapter);
540:            }
541:
542:            /**
543:             * {@inheritDoc}
544:             */
545:            public BodyDataSink send(HttpRequestHeader requestHeader,
546:                    int contentLength, IHttpResponseHandler responseHandler)
547:                    throws IOException, ConnectException {
548:
549:                // get connection
550:                URI targetURI = requestHeader.getTargetURI();
551:                HttpClientConnection con = getConnection(requestHeader
552:                        .isSecure(), targetURI.getHost(), targetURI.getPort(),
553:                        targetURI.getScheme());
554:
555:                // perform call
556:                ResponseHandlerAdapter responseHandlerAdapter = new ResponseHandlerAdapter(
557:                        responseHandler, con, getResponseTimeoutMillis());
558:                return con.sendPlain(requestHeader, contentLength,
559:                        responseHandlerAdapter);
560:
561:            }
562:
563:            /**
564:             * {@inheritDoc}
565:             */
566:            public BodyDataSink send(HttpRequestHeader requestHeader,
567:                    IHttpResponseHandler responseHandler) throws IOException,
568:                    ConnectException {
569:
570:                // get connection
571:                URI targetURI = requestHeader.getTargetURI();
572:                HttpClientConnection con = getConnection(requestHeader
573:                        .isSecure(), targetURI.getHost(), targetURI.getPort(),
574:                        targetURI.getScheme());
575:
576:                // perform call
577:                return con.sendChunked(requestHeader,
578:                        new ResponseHandlerAdapter(responseHandler, con,
579:                                getResponseTimeoutMillis()));
580:            }
581:
582:            /**
583:             * sends a request, by following redirects 
584:             * 
585:             * @param request           the request 
586:             * @param responseHandler   the response handler
587:             * @throws IOException if an exception occurs
588:             * @throws ConnectException if an error occurred while attempting to connect to a remote address and port. 
589:             */
590:            public void sendFollowRedirects(HttpRequest request,
591:                    IHttpResponseHandler responseHandler) throws IOException,
592:                    ConnectException {
593:                sendFollowRedirects(request, responseHandler, 0);
594:            }
595:
596:            private void sendFollowRedirects(HttpRequest request,
597:                    IHttpResponseHandler responseHandler, int redirectCounter)
598:                    throws IOException, ConnectException {
599:
600:                // duplicate body and create RedirectAdapter is redirect is activated
601:                NonBlockingBodyDataSource copiedBody = null;
602:                if (request.hasBody()) {
603:                    copiedBody = request.getNonBlockingBody().duplicate();
604:                }
605:
606:                // get connection
607:                URI targetURI = request.getTargetURI();
608:                HttpClientConnection con = getConnection(request.isSecure(),
609:                        targetURI.getHost(), targetURI.getPort(), targetURI
610:                                .getScheme());
611:
612:                // perform call
613:                RedirectResponseHandlerAdapter responseHandlerAdapter = new RedirectResponseHandlerAdapter(
614:                        responseHandler, con, request.getRequestHeader(),
615:                        copiedBody, redirectCounter, getResponseTimeoutMillis());
616:                con.send(request, responseHandlerAdapter);
617:            }
618:
619:            private void addTransactionInfo(HttpRequest request,
620:                    HttpResponse response) {
621:
622:                if (isTransactionLog) {
623:                    String info = null;
624:                    if (request.getQueryString() != null) {
625:                        info = "[" + DATE_FORMAT.format(new Date()) + "] "
626:                                + request.getRemoteHost() + ":"
627:                                + request.getRemotePort() + " "
628:                                + request.getMethod() + " "
629:                                + request.getRequestURI()
630:                                + request.getQueryString() + " -> "
631:                                + response.getStatus() + " "
632:                                + response.getReason();
633:                    } else {
634:                        info = "[" + DATE_FORMAT.format(new Date()) + "] "
635:                                + request.getRemoteHost() + ":"
636:                                + request.getRemotePort() + " "
637:                                + request.getMethod() + " "
638:                                + request.getRequestURI() + " -> "
639:                                + response.getStatus() + " "
640:                                + response.getReason();
641:                    }
642:
643:                    if (response.containsHeader("connection")) {
644:                        info = info + " (connection: "
645:                                + response.getHeader("connection") + ")";
646:                    }
647:
648:                    transactionLog.add(info);
649:                }
650:            }
651:
652:            private HttpClientConnection getConnection(boolean isSSL,
653:                    String host, int port, String scheme) throws IOException,
654:                    ConnectException {
655:
656:                if (port == -1) {
657:                    if (scheme.equalsIgnoreCase("HTTP")) {
658:                        port = 80;
659:                    } else if (scheme.equalsIgnoreCase("HTTPS")) {
660:                        port = 443;
661:                    } else {
662:                        throw new IOException("wrong address host=" + host
663:                                + " port=" + port + " scheme=" + scheme);
664:                    }
665:                }
666:
667:                if ((isSSL == true) && !isSSLSupported) {
668:                    throw new IOException(
669:                            "ssl connection are not supported (use pool sslContext parameter constructor)");
670:                }
671:
672:                INonBlockingConnection tcpConnection = null;
673:
674:                if (isPooled) {
675:                    try {
676:                        tcpConnection = pool.getNonBlockingConnection(host,
677:                                port, isSSL);
678:
679:                        if (!tcpConnection.isOpen()) {
680:                            System.out.println("Stop");
681:                        }
682:                    } catch (IOException ioe) {
683:                        throw new ConnectException("could not connect to "
684:                                + host + ":" + port + " (" + ioe.toString()
685:                                + ")");
686:                    }
687:
688:                } else {
689:                    try {
690:                        if (sslCtx != null) {
691:                            tcpConnection = new NonBlockingConnection(host,
692:                                    port, sslCtx, true);
693:                            ((NonBlockingConnection) tcpConnection)
694:                                    .setWorkerpool(pool.getWorkerpool());
695:
696:                        } else {
697:                            tcpConnection = new NonBlockingConnection(host,
698:                                    port);
699:                            ((NonBlockingConnection) tcpConnection)
700:                                    .setWorkerpool(pool.getWorkerpool());
701:                        }
702:                    } catch (IOException ioe) {
703:                        throw new ConnectException(
704:                                "could not establish new tcp connection to "
705:                                        + host + ":" + port + " reason: "
706:                                        + ioe.toString());
707:                    }
708:                }
709:
710:                HttpClientConnection httpConnection = new HttpClientConnection(
711:                        tcpConnection);
712:                httpConnection.setResponseTimeoutMillis(receiveTimeoutMillis);
713:                httpConnection
714:                        .setAutohandle100ContinueResponse(isAutohandle100ContinueResponse);
715:                httpConnection.setCloseAfterResponse(true);
716:
717:                return httpConnection;
718:            }
719:
720:            private boolean isRedirectResponse(HttpRequestHeader requestHeader,
721:                    HttpResponseHeader responseHeader) {
722:
723:                switch (responseHeader.getStatus()) {
724:
725:                // 300 Multiple choices
726:                case 300:
727:                    return false;
728:
729:                    // 301 Moved permanently
730:                case 301:
731:                    if (requestHeader.getMethod().equalsIgnoreCase("GET")
732:                            || requestHeader.getMethod().equalsIgnoreCase(
733:                                    "HEAD")) {
734:                        return true;
735:                    }
736:
737:                    return false;
738:
739:                    // 302 found
740:                case 302:
741:                    if (isTreat302RedirectAs303) {
742:                        return true;
743:                    }
744:
745:                    if (requestHeader.getMethod().equalsIgnoreCase("GET")
746:                            || requestHeader.getMethod().equalsIgnoreCase(
747:                                    "HEAD")) {
748:                        return true;
749:                    }
750:
751:                    return false;
752:
753:                    // 303 See other
754:                case 303:
755:                    return true;
756:
757:                    // 304 Not modified
758:                case 304:
759:                    return false;
760:
761:                    // 305 Use proxy
762:                case 305:
763:                    return false;
764:
765:                    // 306 (unused)
766:                case 306:
767:                    return false;
768:
769:                    // 307 temporary redirect
770:                case 307:
771:                    return false;
772:
773:                default:
774:                    return false;
775:                }
776:            }
777:
778:            private static final URL getRedirectURI(HttpResponse response,
779:                    boolean isSSL, String originalHost, int originalPort) {
780:                if (response.getStatus() == 302) {
781:                    String location = response.getHeader("Location");
782:
783:                    // absolute URL? 
784:                    try {
785:                        return new URL(location);
786:
787:                    } catch (MalformedURLException mue) {
788:                        // no
789:                        try {
790:                            if (isSSL) {
791:                                if (originalPort == -1) {
792:                                    return new URL("https://" + originalHost
793:                                            + location);
794:                                } else {
795:                                    return new URL("https://" + originalHost
796:                                            + ":" + originalPort + location);
797:                                }
798:                            } else {
799:                                if (originalPort == -1) {
800:                                    return new URL("http://" + originalHost
801:                                            + location);
802:                                } else {
803:                                    return new URL("http://" + originalHost
804:                                            + ":" + originalPort + location);
805:                                }
806:                            }
807:                        } catch (MalformedURLException e) {
808:                            if (LOG.isLoggable(Level.FINE)) {
809:                                LOG
810:                                        .fine("could not create relocation url . reason "
811:                                                + e.toString());
812:                            }
813:                        }
814:                    }
815:                }
816:
817:                return null;
818:            }
819:
820:            /**
821:             * {@inheritDoc}
822:             */
823:            @Override
824:            public String toString() {
825:                StringBuilder sb = new StringBuilder(super .toString());
826:
827:                sb.append("\r\nactive connections:");
828:                for (String connectionInfo : getActiveConnectionInfos()) {
829:                    sb.append("\r\n " + connectionInfo);
830:                }
831:
832:                sb.append("\r\nidle connections:");
833:                for (String connectionInfo : getIdleConnectionInfos()) {
834:                    sb.append("\r\n " + connectionInfo);
835:                }
836:
837:                sb.append("\r\ntransaction log:");
838:                for (String transactionInfo : getTransactionInfos()) {
839:                    sb.append("\r\n " + transactionInfo);
840:                }
841:
842:                return sb.toString();
843:            }
844:
845:            class RedirectResponseHandlerAdapter extends ResponseHandlerAdapter {
846:
847:                private IHttpResponseHandler responseHandler = null;
848:
849:                // redirect support
850:                private int currentRedirects = 0;
851:                private HttpRequestHeader originalRequestHeader = null;
852:                private NonBlockingBodyDataSource originalRequestBody = null;
853:
854:                public RedirectResponseHandlerAdapter(
855:                        IHttpResponseHandler responseHandler,
856:                        HttpClientConnection httpConnection,
857:                        HttpRequestHeader originalRequestHeader,
858:                        NonBlockingBodyDataSource originalRequestBody,
859:                        int currentRedirects, int receiveTimeoutMillis)
860:                        throws IOException {
861:                    super (responseHandler, httpConnection, receiveTimeoutMillis);
862:                    this .responseHandler = responseHandler;
863:                    this .originalRequestHeader = originalRequestHeader;
864:                    this .originalRequestBody = originalRequestBody;
865:                    this .currentRedirects = currentRedirects;
866:                }
867:
868:                @Override
869:                public void performOnResponse(HttpResponse response) {
870:
871:                    try {
872:                        // redirect handling
873:                        if (isRedirectResponse(originalRequestHeader, response
874:                                .getResponseHeader())) {
875:
876:                            try {
877:                                URL newLocation = getRedirectURI(response,
878:                                        originalRequestHeader.isSecure(),
879:                                        originalRequestHeader.getRemoteHost(),
880:                                        originalRequestHeader.getRemotePort());
881:
882:                                HttpRequestHeader newRequestHeader = new HttpRequestHeader(
883:                                        originalRequestHeader.getMethod(),
884:                                        newLocation.toExternalForm());
885:                                newRequestHeader.copyHeaderFrom(
886:                                        originalRequestHeader, "HOST",
887:                                        "CONTENT-LENGTH");
888:
889:                                HttpRequest newRequest = null;
890:                                if ((response.getStatus() == 303)
891:                                        || ((response.getStatus() == 302) && isTreat302RedirectAs303)) {
892:                                    newRequest = new HttpRequest(
893:                                            newRequestHeader);
894:                                    newRequest.setMethod("GET");
895:
896:                                } else {
897:                                    newRequest = new HttpRequest(
898:                                            newRequestHeader,
899:                                            originalRequestBody);
900:                                }
901:
902:                                sendFollowRedirects(newRequest,
903:                                        responseHandler, ++currentRedirects);
904:                            } catch (URISyntaxException use) {
905:                                throw new IOException(use.toString());
906:                            }
907:
908:                        } else {
909:                            super .performOnResponse(response);
910:                        }
911:
912:                    } catch (IOException ioe) {
913:                        if (LOG.isLoggable(Level.FINE)) {
914:                            LOG.fine("error occured by calling on response "
915:                                    + ioe.toString());
916:                        }
917:                    }
918:                }
919:            }
920:
921:            @SuppressWarnings("unchecked")
922:            private static final class TransactionLog {
923:
924:                private LinkedList<String> transactions = new LinkedList<String>();
925:                private int maxSize = 0;
926:
927:                TransactionLog(int maxSize) {
928:                    this .maxSize = maxSize;
929:                }
930:
931:                void setMaxSize(int maxSize) {
932:                    this .maxSize = maxSize;
933:                }
934:
935:                int getMaxSize() {
936:                    return maxSize;
937:                }
938:
939:                void add(String transactionInfo) {
940:                    transactions.add(transactionInfo);
941:                    if (transactions.size() > maxSize) {
942:                        try {
943:                            transactions.removeFirst();
944:                        } catch (Exception e) {
945:                            if (LOG.isLoggable(Level.FINE)) {
946:                                LOG
947:                                        .fine("error occured by removing list entry "
948:                                                + e.toString());
949:                            }
950:                        }
951:                    }
952:                }
953:
954:                public List<String> getTransactions() {
955:                    return (List<String>) transactions.clone();
956:                }
957:
958:            }
959:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.