Source Code Cross Referenced for CheckLinks.java in  » Web-Services » xins » org » xins » server » 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 Services » xins » org.xins.server 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /*
002:         * $Id: CheckLinks.java,v 1.37 2007/05/22 11:13:26 agoubard Exp $
003:         *
004:         * Copyright 2003-2007 Orange Nederland Breedband B.V.
005:         * See the COPYRIGHT file for redistribution and use restrictions.
006:         */
007:        package org.xins.server;
008:
009:        import java.io.IOException;
010:        import java.io.InterruptedIOException;
011:        import java.net.ConnectException;
012:        import java.net.UnknownHostException;
013:        import java.util.ArrayList;
014:        import java.util.Iterator;
015:        import java.util.List;
016:
017:        import org.apache.commons.httpclient.DefaultHttpMethodRetryHandler;
018:        import org.apache.commons.httpclient.HttpClient;
019:        import org.apache.commons.httpclient.HttpMethodBase;
020:        import org.apache.commons.httpclient.HttpRecoverableException;
021:        import org.apache.commons.httpclient.params.HttpMethodParams;
022:        import org.apache.commons.httpclient.methods.OptionsMethod;
023:
024:        import org.xins.common.MandatoryArgumentChecker;
025:        import org.xins.common.Utils;
026:        import org.xins.common.service.Descriptor;
027:        import org.xins.common.service.TargetDescriptor;
028:        import org.xins.common.xml.ElementBuilder;
029:
030:        /**
031:         * Checks all the links in the given <code>descriptor</code>s list and builds
032:         * a <code>FunctionResult</code>. It connects to each link in
033:         * {@link TargetDescriptor}s in {@link Descriptor}s list using a
034:         * {@link URLChecker} and calculates the total links count and
035:         * total links failures. The returned {@link FunctionResult} contains
036:         * information about total links checked, failures and details.
037:         *
038:         * The following example uses a {@link CheckLinks} object to get the
039:         * {@link FunctionResult}.
040:         *
041:         * <blockquote><pre>
042:         * FunctionResult result = CheckLinks.checkLinks(descriptorList);
043:         *
044:         * // Returns parameters
045:         * result.getParameters();
046:         * </pre></blockquote>
047:         *
048:         * @version $Revision: 1.37 $ $Date: 2007/05/22 11:13:26 $
049:         * @author <a href="mailto:tauseef.rehman@orange-ftgroup.com">Tauseef Rehman</a>
050:         */
051:        class CheckLinks {
052:
053:            /**
054:             * The failure message to be added in the <code>FunctionResult</code> when
055:             * the exception is <code>UnknownHostException</code>.
056:             */
057:            private static final String UNKNOWN_HOST = "UnknownHost";
058:
059:            /**
060:             * The failure message to be added in the <code>FunctionResult</code> when
061:             * the exception is <code>ConnectTimeoutException</code> or the message
062:             * of the exception starts with "Connect timed out".
063:             */
064:            private static final String CONNECTION_TIMEOUT = "ConnectionTimeout";
065:
066:            /**
067:             * The failure message to be added in the <code>FunctionResult</code> when
068:             * the exception is <code>ConnectException</code>.
069:             */
070:            private static final String CONNECTION_REFUSAL = "ConnectionRefusal";
071:
072:            /**
073:             * The failure message to be added in the <code>FunctionResult</code> when
074:             * the exception is <code>SocketTimeoutException</code>.
075:             */
076:            private static final String SOCKET_TIMEOUT = "SocketTimeout";
077:
078:            /**
079:             * The failure message to be added in the <code>FunctionResult</code> when
080:             * the exception is <code>IOException</code>.
081:             */
082:            private static final String OTHER_IO_ERROR = "OtherIOError";
083:
084:            /**
085:             * The failure message to be added in the <code>FunctionResult</code> when
086:             * the exception is an unknown <code>Exception</code>.
087:             */
088:            private static final String OTHER_FAILURE = "OtherFailure";
089:
090:            /**
091:             * The success message to be added in the <code>FunctionResult</code>.
092:             */
093:            private static final String SUCCESS = "Success";
094:
095:            /**
096:             * HTTP retry handler that does not allow any retries.
097:             */
098:            private static DefaultHttpMethodRetryHandler NO_RETRIES = new DefaultHttpMethodRetryHandler(
099:                    0, false);
100:
101:            /**
102:             * Checks all the links in <code>TargetDescriptor</code>s inside the
103:             * <code>Descriptor</code> list and builds a <code>FunctionResult</code>.
104:             * First gets all the {@link TargetDescriptor}s from the
105:             * {@link Descriptor}s list then creates {@link URLChecker} threads with
106:             * {@link TargetDescriptor}s and runs them. When all the threads have
107:             * finished execution, the {@link FunctionResult} is built and returned.
108:             * The returned {@link FunctionResult} contains all the links which were
109:             * checked with their results.
110:             *
111:             * @param descriptors
112:             *    the list of {@link Descriptor}s defined in the runtime properties,
113:             *    cannot be <code>null</code>.
114:             *
115:             * @return
116:             *    the constructed {@link FunctionResult} object, never
117:             *    <code>null</code>.
118:             *
119:             * @throws IllegalArgumentException
120:             *    if <code>descriptors == null</code>.
121:             */
122:            static FunctionResult checkLinks(List descriptors)
123:                    throws IllegalArgumentException {
124:
125:                // Check preconditions
126:                MandatoryArgumentChecker.check("descriptors", descriptors);
127:
128:                List threads = new ArrayList();
129:                if (descriptors.size() > 0) {
130:
131:                    // Get all the targets from the descriptor list
132:                    List targetDescriptors = getTargetDescriptors(descriptors);
133:
134:                    // Create the thread for each target and run them
135:                    threads = createAndRunUrlCheckers(targetDescriptors);
136:
137:                    // Get the biggest time-out from all the targets
138:                    int timeout = getBiggestTimeout(targetDescriptors);
139:
140:                    // Wait till all the threads finish their execution or timedout.
141:                    waitTillThreadsRunning(threads, timeout);
142:
143:                    // Confirm all threads have finished their execution.
144:                    confirmThreadsStopped(threads);
145:                }
146:
147:                // Start building the result
148:                FunctionResult builder = new FunctionResult();
149:                int errorCount = (descriptors.size() > 0) ? addCheckElements(
150:                        builder, threads) : 0;
151:                builder.param("linkCount", String.valueOf(threads.size()));
152:                builder.param("errorCount", String.valueOf(errorCount));
153:
154:                return builder;
155:            }
156:
157:            /**
158:             * Creates a list of <code>TargetDescriptor</code>s from the
159:             * given <code>Descriptor</code>s list. Each {@link Descriptor} in the
160:             * list contains a list of {@link TargetDescriptor}s, which are added to
161:             * the returned list.
162:             *
163:             * @param descriptors
164:             *    the list of {@link Descriptor}s, cannot be <code>null</code>.
165:             *
166:             * @return
167:             *    the constructed {@link TargetDescriptor}s list, never
168:             *    <code>null</code>.
169:             *
170:             * @throws IllegalArgumentException
171:             *    if <code>descriptors == null</code>.
172:             */
173:            private static List getTargetDescriptors(List descriptors)
174:                    throws IllegalArgumentException {
175:
176:                // Check preconditions
177:                MandatoryArgumentChecker.check("descriptors", descriptors);
178:
179:                Iterator descriptorIterator = descriptors.iterator();
180:                List targetDescriptors = new ArrayList();
181:
182:                // Each descriptor in the list contains target descriptors, so
183:                // iterate over descriptors and get all the target descriptors, then
184:                // iterate over each target descriptor and get the individual
185:                // target descriptors.
186:                while (descriptorIterator.hasNext()) {
187:                    Descriptor descriptor = (Descriptor) descriptorIterator
188:                            .next();
189:
190:                    // Get the iterator on target descriptor
191:                    Iterator targetIterator = descriptor.iterateTargets();
192:                    while (targetIterator.hasNext()) {
193:                        TargetDescriptor targetDescriptor = (TargetDescriptor) targetIterator
194:                                .next();
195:
196:                        // Add all the target descriptors in a list
197:                        targetDescriptors.add(targetDescriptor);
198:                    }
199:                }
200:
201:                return targetDescriptors;
202:            }
203:
204:            /**
205:             * Creates and runs a thread for each <code>TargetDescriptor</code> in the
206:             * given list. Each {@link TargetDescriptor} in the list contains a URL. A
207:             * {@link URLChecker} thread is created for each {@link TargetDescriptor},
208:             * which tries to connect to the URL provided in the
209:             * {@link TargetDescriptor}. Each thread is then added to a list which is
210:             * returned.
211:             *
212:             * @param targetDescriptors
213:             *    the list of {@link TargetDescriptor}s which needs to be checked,
214:             *    cannot be <code>null</code>.
215:             *
216:             * @return
217:             *    the constructed {@link URLChecker}s list, never <code>null</code>.
218:             *
219:             * @throws IllegalArgumentException
220:             *    if <code>targetDescriptors == null</code>.
221:             */
222:            private static List createAndRunUrlCheckers(List targetDescriptors)
223:                    throws IllegalArgumentException {
224:
225:                // Check preconditions
226:                MandatoryArgumentChecker.check("targetDescriptors",
227:                        targetDescriptors);
228:
229:                // Iterate over all target descriptors
230:                List threads = new ArrayList();
231:                Iterator targets = targetDescriptors.iterator();
232:                while (targets.hasNext()) {
233:                    TargetDescriptor target = (TargetDescriptor) targets.next();
234:
235:                    // Create a thread for the target descriptor
236:                    URLChecker urlThread = new URLChecker(target);
237:
238:                    // Start the thread with target descriptor
239:                    urlThread.start();
240:
241:                    // Store the thread just started in a list
242:                    threads.add(urlThread);
243:                }
244:
245:                return threads;
246:            }
247:
248:            /**
249:             * Returns the biggest time-out of all the URLs defined in
250:             * <code>TargetDescriptor</code>s list. Each {@link TargetDescriptor} in
251:             * the list has total time-out. The biggest of all of them is returned.
252:             * This time-out is then used to setup the time-outs of the
253:             * {@link URLChecker} threads.
254:             *
255:             * @param targetDescriptors
256:             *    the list of {@link TargetDescriptor}s, cannot be <code>null</code>.
257:             *
258:             * @return
259:             *    the biggest time-out from the list, or <code>-1</code> if none of the
260:             *    target descriptors defines a time-out.
261:             *
262:             * @throws IllegalArgumentException
263:             *    if <code>targetDescriptors == null</code>.
264:             */
265:            private static int getBiggestTimeout(List targetDescriptors)
266:                    throws IllegalArgumentException {
267:
268:                // Check preconditions
269:                MandatoryArgumentChecker.check("targetDescriptors",
270:                        targetDescriptors);
271:
272:                Iterator targets = targetDescriptors.iterator();
273:                int biggestTimeout = -1;
274:
275:                // Iterate over all target descriptors
276:                while (targets.hasNext()) {
277:                    TargetDescriptor target = (TargetDescriptor) targets.next();
278:
279:                    // Try to get the biggest time out of all the target descriptors
280:                    if (biggestTimeout < target.getTotalTimeOut()) {
281:                        biggestTimeout = target.getTotalTimeOut();
282:                    }
283:                }
284:
285:                return biggestTimeout;
286:            }
287:
288:            /**
289:             * Sets up the time-out for each thread and waits till each thread finishes
290:             * execution. The time-out is the biggest time-out of all the URLs in
291:             * {@link TargetDescriptor}s. Timeout for every next thread also considers
292:             * the time which is already spent and that time is subtracted from the
293:             * time-out for the current thread.
294:             *
295:             * @param threads
296:             *    the list of {@link URLChecker} threads, cannot be <code>null</code>.
297:             *
298:             * @param timeout
299:             *    the time-out for {@link URLChecker} threads.
300:             *
301:             * @throws IllegalArgumentException
302:             *    if <code>threads == null</code>.
303:             */
304:            private static void waitTillThreadsRunning(List threads, int timeout)
305:                    throws IllegalArgumentException {
306:
307:                // Check preconditions
308:                MandatoryArgumentChecker.check("threads", threads);
309:
310:                Iterator threadIterator = threads.iterator();
311:                long threadTimeout = timeout;
312:
313:                // Storing the time approximately when the first thread was started
314:                long startTime = System.currentTimeMillis();
315:                try {
316:
317:                    // Iterate over all the threads
318:                    while (threadIterator.hasNext()) {
319:                        URLChecker urlThread = (URLChecker) threadIterator
320:                                .next();
321:                        urlThread.join(threadTimeout);
322:
323:                        // If the previous thread was setup with a certain time-out
324:                        // the next thread should be setup with a time-out subtracted
325:                        // by the time which is already passed.
326:                        long endTime = System.currentTimeMillis();
327:                        long timePassed = endTime - startTime;
328:                        threadTimeout = timeout - timePassed;
329:
330:                        // If the time-out becomes negative, it means that the total
331:                        // time-out interval has passed now we do not need to setup
332:                        // time-out for threads and they all should have finished
333:                        // execution by now.
334:                        if (threadTimeout <= 0) {
335:                            return;
336:                        }
337:                    }
338:                } catch (InterruptedException exception) {
339:
340:                    // The exception is thrown when another thread has interrupted
341:                    // the current thread. This should never happen so it should log
342:                    // a programming error and throw a ProgrammingException.
343:                    throw Utils.logProgrammingError(exception);
344:                }
345:            }
346:
347:            /**
348:             * Confimrs that each <code>URLChecker</code> has finished its execution.
349:             * If some threads are still running, inforce a connection time-out and let
350:             * it run and ignore.
351:             *
352:             * @param threads
353:             *    the list of {@link URLChecker} threads, cannot be <code>null</code>.
354:             *
355:             * @throws IllegalArgumentException
356:             *    if <code>threads == null</code>.
357:             */
358:            private static void confirmThreadsStopped(List threads)
359:                    throws IllegalArgumentException {
360:
361:                // Check preconditions
362:                MandatoryArgumentChecker.check("threads", threads);
363:
364:                Iterator threadIterator = threads.iterator();
365:
366:                // Iterate over all the threads
367:                while (threadIterator.hasNext()) {
368:                    URLChecker urlThread = (URLChecker) threadIterator.next();
369:
370:                    // Check if thread is still alive.
371:                    if (urlThread.isAlive()) {
372:
373:                        // Enforce a time-out for the thread and log it.
374:                        urlThread.enforceTimeout();
375:                        Log.log_3505(urlThread.getURL());
376:                    }
377:                }
378:            }
379:
380:            /**
381:             * Builds the <code>FunctionResult</code> for all the URLs checked. It
382:             * iterates over the list of all {@link URLChecker} threads and gets the
383:             * information like the total time each thread took to execute and the
384:             * result of the execution. The information is added in an
385:             * {@link ElementBuilder} object using which {@link org.xins.common.xml.Element}
386:             * is created which then is added to the passed {@link FunctionResult}.
387:             *
388:             * @param builder
389:             *    the {@link FunctionResult} where the result is added, cannot be
390:             *    <code>null</code>.
391:             *
392:             * @param threads
393:             *    the list of {@link URLChecker} threads, cannot be <code>null</code>.
394:             *
395:             * @return
396:             *    the total number of URLs without success.
397:             *
398:             * @throws IllegalArgumentException
399:             *    if <code>builder == null || threads == null</code>.
400:             */
401:            private static int addCheckElements(FunctionResult builder,
402:                    List threads) throws IllegalArgumentException {
403:
404:                // Check preconditions
405:                MandatoryArgumentChecker.check("builder", builder, "threads",
406:                        threads);
407:
408:                Iterator threadIterator = threads.iterator();
409:                int errorCount = 0;
410:
411:                // Iterate over the threads of target descriptors and create the
412:                // check element.
413:                while (threadIterator.hasNext()) {
414:                    URLChecker urlThread = (URLChecker) threadIterator.next();
415:                    ElementBuilder eb = new ElementBuilder("check");
416:                    eb.setAttribute("url", urlThread.getURL());
417:                    eb.setAttribute("duration", Long.toString(urlThread
418:                            .getDuration()));
419:                    eb.setAttribute("result", getResult(urlThread));
420:                    builder.add(eb.createElement());
421:
422:                    if (!urlThread.getSuccess()) {
423:                        errorCount++;
424:                    }
425:                }
426:
427:                return errorCount;
428:            }
429:
430:            /**
431:             * Returns the value for the result parameter which is added in the
432:             * <code>FunctionBuilder</code>. The value of the result depends on the
433:             * success or failure of the passed {@link URLChecker} thread. If the
434:             * {@link URLChecker} thread gives a success, the status code of the
435:             * {@link URLChecker} thread is used to create the value for result
436:             * parameter, otherwise the exception in the {@link URLChecker} thread
437:             * determines the value for the result parameter.
438:             *
439:             * @param urlThread
440:             *    the {@link URLChecker} thread for which the result value is to
441:             *    detemined, cannot be <code>null</code>.
442:             *
443:             * @return
444:             *    the result message, never <code>null</code>.
445:             *
446:             * @throws IllegalArgumentException
447:             *    if <code>urlThread == null || urlThread.hasRun() == false</code>.
448:             */
449:            private static String getResult(URLChecker urlThread)
450:                    throws IllegalArgumentException {
451:
452:                // Check preconditions
453:                MandatoryArgumentChecker.check("urlThread", urlThread);
454:                if (!urlThread.hasRun()) {
455:                    throw new IllegalArgumentException(
456:                            "urlThread().hasRun() == false");
457:                }
458:
459:                if (urlThread.getSuccess()) {
460:                    return SUCCESS;
461:                } else {
462:                    return getResult(urlThread.getException(), urlThread
463:                            .getURL());
464:                }
465:            }
466:
467:            /**
468:             * Returns the value for the result parameter which is added in the
469:             * <code>FunctionBuilder</code> when the <code>URLChecker</code> thread
470:             * failed to connect the URL. The value for the result parameter depends
471:             * on the exception occured in the {@link URLChecker} thread. The
472:             * exception is passed to this method. Based on the type of exception, an
473:             * appropriate value is returned.
474:             *
475:             * @param exception
476:             *    the {@link Throwable} exception occured in the {@link URLChecker}
477:             *    thread, cannot be <code>null</code>.
478:             *
479:             * @param url
480:             *    the url which threw the exception, cannot be <code>null</code>.
481:             *
482:             * @return
483:             *    the result message, never <code>null</code>.
484:             *
485:             * @throws IllegalArgumentException
486:             *    if <code>exception == null</code>.
487:             */
488:            private static String getResult(Throwable exception, String url)
489:                    throws IllegalArgumentException {
490:
491:                // Check preconditions.
492:                MandatoryArgumentChecker.check("exception", exception, "url",
493:                        url);
494:
495:                String exceptionName = exception.getClass().getName();
496:                String result;
497:
498:                // DNS error, unknown host name
499:                if (exception instanceof  UnknownHostException) {
500:                    result = UNKNOWN_HOST;
501:
502:                    // Connection time-out
503:                } else if (exceptionName
504:                        .equals("org.apache.commons.httpclient.ConnectTimeoutException")
505:                        || exception.getMessage().startsWith(
506:                                "Connect timed out")) {
507:                    result = CONNECTION_TIMEOUT;
508:
509:                    // Connection refused
510:                } else if (exception instanceof  ConnectException) {
511:                    result = CONNECTION_REFUSAL;
512:
513:                    // SocketTimeoutException is not available in older Java versions,
514:                    // so we do not refer to the class to avoid a NoClassDefFoundError.
515:                } else if (exceptionName
516:                        .equals("java.net.SocketTimeoutException")) {
517:                    result = SOCKET_TIMEOUT;
518:
519:                    // HTTPClient 2.0 socket time out is done using the HttpRecoverableException
520:                } else if (exception instanceof  HttpRecoverableException
521:                        && ((HttpRecoverableException) exception).getReason()
522:                                .indexOf("Read timed out") != -1) {
523:                    result = SOCKET_TIMEOUT;
524:
525:                    // Interrupted I/O (this _may_ indicate a socket time-out)
526:                } else if (exception instanceof  InterruptedIOException) {
527:                    String exMessage = exception.getMessage();
528:
529:                    // XXX: Only tested on Sun JVM
530:                    // TODO: Test on non-Sun JVM
531:                    if (exMessage.startsWith("Read timed out")) {
532:                        result = SOCKET_TIMEOUT;
533:
534:                        // Unspecific I/O error
535:                    } else {
536:                        result = OTHER_IO_ERROR;
537:                    }
538:
539:                    // Other I/O error
540:                } else if (exception instanceof  IOException) {
541:                    result = OTHER_IO_ERROR;
542:
543:                    // Other error, apparently not an I/O error
544:                } else {
545:                    result = OTHER_FAILURE;
546:                }
547:
548:                // Log the result and exception.
549:                Log.log_3502(exception, url, result);
550:
551:                return result;
552:            }
553:
554:            /**
555:             * Creates a new <code>CheckLinks</code> object.
556:             */
557:            private CheckLinks() {
558:                // empty
559:            }
560:
561:            /**
562:             * Tries to connect to a URL provided in the
563:             * <code>TargetDescriptor</code>. Runs as a separate thread. The URL is
564:             * connected by sending a request associated with an HTTP
565:             * <code>OPTIONS</code> method. Also calculates the total time to
566:             * connect to the provided URL.
567:             *
568:             * <p>The following example uses a {@link CheckLinks} object to get the
569:             * {@link FunctionResult}.
570:             *
571:             * <blockquote><pre>TargetDescriptor target = new TargetDescriptor();
572:             * target.setURL("www.hotmail.com");
573:             *
574:             * URLChecker urlThread = new URLChecker(target);
575:             * urlThread.start();
576:             *
577:             * String URL = urlThread.getURL();
578:             * int duration = urlThread.getDuration();
579:             * boolean success = urlThread.getSuccess();
580:             * if (!success) {
581:             *    exception = urlThread.getException();
582:             * }</pre></blockquote>
583:             *
584:             * @version $Revision: 1.37 $ $Date: 2007/05/22 11:13:26 $
585:             * @author <a href="mailto:tauseef.rehman@orange-ftgroup.com">Tauseef Rehman</a>
586:             */
587:            private static final class URLChecker extends Thread {
588:
589:                /**
590:                 * The target descriptor for which the URL needs to be checked. Never
591:                 * <code>null</code>.
592:                 */
593:                private final TargetDescriptor _targetDescriptor;
594:
595:                /**
596:                 * The URL to be checked. Never <code>null</code>.
597:                 */
598:                private final String _url;
599:
600:                /**
601:                 * The exception thrown when accessing the URL. Can be
602:                 * <code>null</code> if the <code>URLChecker</code> has not run yet, or
603:                 * if there was no error.
604:                 */
605:                private Throwable _exception;
606:
607:                /**
608:                 * The result of the URL check. Is <code>true</code> if the
609:                 * <code>URLChecker</code> has run and was successful. If either of
610:                 * these conditions is not met, then <code>false</code>.
611:                 */
612:                private boolean _success;
613:
614:                /**
615:                 * The time taken to check the URL. Initially <code>-1</code>.
616:                 */
617:                private long _duration;
618:
619:                /**
620:                 * The status code returned when the URL was called. Initially
621:                 * <code>-1</code>, when the <code>URLChecker</code> was not run yet.
622:                 */
623:                private int _statusCode;
624:
625:                /**
626:                 * Constructs a new <code>URLChecker</code> for the specified target
627:                 * descriptor.
628:                 *
629:                 * @param targetDescriptor
630:                 *    the {@link TargetDescriptor}, whose URL needs to be checked,
631:                 *    cannot be <code>null</code>.
632:                 *
633:                 * @throws IllegalArgumentException
634:                 *    if <code>targetDescriptor == null</code>.
635:                 */
636:                public URLChecker(TargetDescriptor targetDescriptor)
637:                        throws IllegalArgumentException {
638:
639:                    // Check preconditions
640:                    MandatoryArgumentChecker.check("targetDescriptor",
641:                            targetDescriptor);
642:
643:                    // Initialize fields
644:                    _targetDescriptor = targetDescriptor;
645:                    _url = targetDescriptor.getURL();
646:                    _duration = -1;
647:                    _statusCode = -1;
648:
649:                    // Check postconditions
650:                    if (_url == null) {
651:                        throw Utils.logProgrammingError("_url == null");
652:                    }
653:                }
654:
655:                /**
656:                 * Runs this thread. It tries to connect to the URL provided in the
657:                 * {@link TargetDescriptor}. The URL is connected by sending a request
658:                 * associated with an HTTP <code>OPTIONS</code> method. It also
659:                 * calculates the total time to connect to the provided URL and saves
660:                 * the exception in case an exception occurs.
661:                 *
662:                 * @throws IllegalStateException
663:                 *    if this <code>URLChecker</code> has already run.
664:                 */
665:                public void run() throws IllegalStateException {
666:
667:                    // Check preconditions
668:                    if (hasRun()) {
669:                        throw new IllegalStateException(
670:                                "This URLChecker for URL: " + _url
671:                                        + "has already run.");
672:                    }
673:
674:                    // Logging the start of this thread.
675:                    Log.log_3503(_url, _targetDescriptor.getTotalTimeOut(),
676:                            _targetDescriptor.getConnectionTimeOut(),
677:                            _targetDescriptor.getSocketTimeOut());
678:
679:                    // Register current time, to compute total duration later
680:                    long startTime = System.currentTimeMillis();
681:
682:                    HttpMethodBase optionsMethod = null;
683:                    try {
684:                        HttpClient client = new HttpClient();
685:
686:                        // Set the socket time-out for the URL.
687:                        client.setTimeout(_targetDescriptor.getSocketTimeOut());
688:
689:                        // Set the connection time-out for the URL.
690:                        client
691:                                .setHttpConnectionFactoryTimeout(_targetDescriptor
692:                                        .getConnectionTimeOut());
693:
694:                        // Create a new OptionsMethod with the URL, this will represent
695:                        // a request for information about the communication options
696:                        // available on the request/response chain identified by the url.
697:                        // This method allows the client to determine the options and/or
698:                        // requirements associated with a resource, or the capabilities
699:                        // of a server, without implying a resource action or initiating
700:                        // a resource retrieval.
701:                        optionsMethod = new OptionsMethod(_url);
702:                        optionsMethod.getParams().setParameter(
703:                                HttpMethodParams.RETRY_HANDLER, NO_RETRIES);
704:
705:                        // Execute the OptionsMethod.
706:                        _statusCode = client.executeMethod(optionsMethod);
707:
708:                        // Successfully executed, so set the success as true.
709:                        _success = true;
710:                    } catch (Throwable exception) {
711:
712:                        // Save the exception and set the success as false as the
713:                        // execution was failed.
714:                        _exception = exception;
715:                        _success = false;
716:                    } finally {
717:                        releaseConnection(optionsMethod);
718:                    }
719:
720:                    // Calculate the total time taken to check the URL.
721:                    _duration = System.currentTimeMillis() - startTime;
722:
723:                    // Logging the stopping of this thread.
724:                    Log.log_3504(_url, _duration);
725:                }
726:
727:                /**
728:                 * Releases the connection used by the passed
729:                 * <code>HttpMethodBase</code>. If the connection is not released
730:                 * successfully and an exception is thrown, then it is just logged and
731:                 * ignored. If the argument is <code>null</code> then nothing is done.
732:                 *
733:                 * @param method
734:                 *    the {@link HttpMethodBase} potentially having an unreleased
735:                 *    connection, can be <code>null</code>.
736:                 */
737:                private void releaseConnection(HttpMethodBase method) {
738:
739:                    if (method != null) {
740:
741:                        // Release the connection
742:                        try {
743:                            method.releaseConnection();
744:
745:                            // Just ignore (and log) any exception as we do not want to fail
746:                            // if the connection is not properly released.
747:                        } catch (Throwable ignorable) {
748:                            Utils.logIgnoredException(ignorable);
749:                        }
750:                    }
751:                }
752:
753:                /**
754:                 * Checks if this <code>URLChecker</code> has already run.
755:                 *
756:                 * @return
757:                 *    <code>true</code> if this <code>URLChecker</code> has already run,
758:                 *    or <code>false</code> otherwise.
759:                 */
760:                boolean hasRun() {
761:                    return (_duration >= 0);
762:                }
763:
764:                /**
765:                 * Checks if this <code>URLChecker</code> has already run and if not,
766:                 * throws an exception.
767:                 *
768:                 * @throws IllegalStateException
769:                 *    if this <code>URLChecker</code> has not run yet.
770:                 */
771:                private void assertHasRun() throws IllegalStateException {
772:                    if (!hasRun()) {
773:                        String message = "This URLChecker has not run yet. URL: \""
774:                                + _url + "\".";
775:                        throw new IllegalStateException(message);
776:                    }
777:                }
778:
779:                /**
780:                 * Returns the total time it took to connect to the URL.
781:                 *
782:                 * @return
783:                 *    the total duration in milliseconds, or <code>-1</code> if this
784:                 *    thread has not run.
785:                 *
786:                 * @throws IllegalStateException
787:                 *    if this <code>URLChecker</code> has not run yet.
788:                 */
789:                public long getDuration() throws IllegalStateException {
790:                    assertHasRun();
791:                    return _duration;
792:                }
793:
794:                /**
795:                 * Returns the flag indicating if the URL was connected successfully.
796:                 *
797:                 * @return
798:                 *    the success flag, Is <code>true</code> if this thread has run and
799:                 *    was successful. If either of these conditions is not met,
800:                 *    then <code>false</code>.
801:                 *
802:                 * @throws IllegalStateException
803:                 *    if this <code>URLChecker</code> has not run yet.
804:                 */
805:                public boolean getSuccess() throws IllegalStateException {
806:                    assertHasRun();
807:                    return _success;
808:                }
809:
810:                /**
811:                 * Returns the status code of the method execution.
812:                 *
813:                 * @return
814:                 *    the status code returned when the URL was called. <code>-1</code>,
815:                 *    when this thread has not run.
816:                 *
817:                 * @throws IllegalStateException
818:                 *    if this <code>URLChecker</code> has not run yet.
819:                 */
820:                public int getStatusCode() throws IllegalStateException {
821:                    assertHasRun();
822:                    return _statusCode;
823:                }
824:
825:                /**
826:                 * Returns the URL which was connected.
827:                 *
828:                 * @return
829:                 *    the URL, never <code>null</code>.
830:                 *
831:                 * @throws IllegalStateException
832:                 *    if this <code>URLChecker</code> has not run yet.
833:                 */
834:                public String getURL() throws IllegalStateException {
835:                    assertHasRun();
836:                    return _url;
837:                }
838:
839:                /**
840:                 * Returns the exception thrown while trying to connect to the URL.
841:                 *
842:                 * @return
843:                 *    the exception, can be <code>null</code>.
844:                 *
845:                 * @throws IllegalStateException
846:                 *    if this <code>URLChecker</code> has not run yet.
847:                 */
848:                public Throwable getException() throws IllegalStateException {
849:                    assertHasRun();
850:                    return _exception;
851:                }
852:
853:                /**
854:                 * Enforces a time-out on the <code>URLChecker</code> thread. Actualy
855:                 * the thread is allowed to run and ignored. So set the duration as the
856:                 * initial connection time-out value and create a new
857:                 * {@link ConnectException}.
858:                 */
859:                public void enforceTimeout() {
860:                    if (!hasRun()) {
861:
862:                        // Set the duration as was defined for connection time-out
863:                        _duration = _targetDescriptor.getConnectionTimeOut();
864:
865:                        // Create a new ConnectException.
866:                        _exception = new ConnectException("Connect timed out");
867:
868:                        // XXX: Currently it is observed that mostly the URLs which are
869:                        // expected to throw a ConnectTimeoutException keeps on running
870:                        // but we need to take care of the situation when because of some
871:                        // other reason the thread is still active.
872:                    }
873:                }
874:
875:            }
876:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.