Source Code Cross Referenced for Lookup.java in  » Net » dnsjava » org » xbill » DNS » 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 » Net » dnsjava » org.xbill.DNS 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        // Copyright (c) 2002-2004 Brian Wellington (bwelling@xbill.org)
002:
003:        package org.xbill.DNS;
004:
005:        import java.util.*;
006:        import java.io.*;
007:        import java.net.*;
008:
009:        /**
010:         * The Lookup object issues queries to caching DNS servers.  The input consists
011:         * of a name, an optional type, and an optional class.  Caching is enabled
012:         * by default and used when possible to reduce the number of DNS requests.
013:         * A Resolver, which defaults to an ExtendedResolver initialized with the
014:         * resolvers located by the ResolverConfig class, performs the queries.  A
015:         * search path of domain suffixes is used to resolve relative names, and is
016:         * also determined by the ResolverConfig class.
017:         *
018:         * A Lookup object may be reused, but should not be used by multiple threads.
019:         *
020:         * @see Cache
021:         * @see Resolver
022:         * @see ResolverConfig
023:         *
024:         * @author Brian Wellington
025:         */
026:
027:        public final class Lookup {
028:
029:            private static Resolver defaultResolver;
030:            private static Name[] defaultSearchPath;
031:            private static Map defaultCaches;
032:
033:            private Resolver resolver;
034:            private Name[] searchPath;
035:            private Cache cache;
036:            private boolean temporary_cache;
037:            private int credibility;
038:            private Name name;
039:            private int type;
040:            private int dclass;
041:            private boolean verbose;
042:            private int iterations;
043:            private boolean foundAlias;
044:            private boolean done;
045:            private boolean doneCurrent;
046:            private List aliases;
047:            private Record[] answers;
048:            private int result;
049:            private String error;
050:            private boolean nxdomain;
051:            private boolean badresponse;
052:            private String badresponse_error;
053:            private boolean networkerror;
054:            private boolean timedout;
055:            private boolean nametoolong;
056:            private boolean referral;
057:
058:            private static final Name[] noAliases = new Name[0];
059:
060:            /** The lookup was successful. */
061:            public static final int SUCCESSFUL = 0;
062:
063:            /**
064:             * The lookup failed due to a data or server error. Repeating the lookup
065:             * would not be helpful.
066:             */
067:            public static final int UNRECOVERABLE = 1;
068:
069:            /**
070:             * The lookup failed due to a network error. Repeating the lookup may be
071:             * helpful.
072:             */
073:            public static final int TRY_AGAIN = 2;
074:
075:            /** The host does not exist. */
076:            public static final int HOST_NOT_FOUND = 3;
077:
078:            /** The host exists, but has no records associated with the queried type. */
079:            public static final int TYPE_NOT_FOUND = 4;
080:
081:            public static synchronized void refreshDefault() {
082:
083:                try {
084:                    defaultResolver = new ExtendedResolver();
085:                } catch (UnknownHostException e) {
086:                    throw new RuntimeException("Failed to initialize resolver");
087:                }
088:                defaultSearchPath = ResolverConfig.getCurrentConfig()
089:                        .searchPath();
090:                defaultCaches = new HashMap();
091:            }
092:
093:            static {
094:                refreshDefault();
095:            }
096:
097:            /**
098:             * Gets the Resolver that will be used as the default by future Lookups.
099:             * @return The default resolver.
100:             */
101:            public static synchronized Resolver getDefaultResolver() {
102:                return defaultResolver;
103:            }
104:
105:            /**
106:             * Sets the default Resolver to be used as the default by future Lookups.
107:             * @param resolver The default resolver.
108:             */
109:            public static synchronized void setDefaultResolver(Resolver resolver) {
110:                defaultResolver = resolver;
111:            }
112:
113:            /**
114:             * Gets the Cache that will be used as the default for the specified
115:             * class by future Lookups.
116:             * @param dclass The class whose cache is being retrieved.
117:             * @return The default cache for the specified class.
118:             */
119:            public static synchronized Cache getDefaultCache(int dclass) {
120:                DClass.check(dclass);
121:                Cache c = (Cache) defaultCaches.get(Mnemonic.toInteger(dclass));
122:                if (c == null) {
123:                    c = new Cache(dclass);
124:                    defaultCaches.put(Mnemonic.toInteger(dclass), c);
125:                }
126:                return c;
127:            }
128:
129:            /**
130:             * Sets the Cache to be used as the default for the specified class by future
131:             * Lookups.
132:             * @param cache The default cache for the specified class.
133:             * @param dclass The class whose cache is being set.
134:             */
135:            public static synchronized void setDefaultCache(Cache cache,
136:                    int dclass) {
137:                DClass.check(dclass);
138:                defaultCaches.put(Mnemonic.toInteger(dclass), cache);
139:            }
140:
141:            /**
142:             * Gets the search path that will be used as the default by future Lookups.
143:             * @return The default search path.
144:             */
145:            public static synchronized Name[] getDefaultSearchPath() {
146:                return defaultSearchPath;
147:            }
148:
149:            /**
150:             * Sets the search path to be used as the default by future Lookups.
151:             * @param domains The default search path.
152:             */
153:            public static synchronized void setDefaultSearchPath(Name[] domains) {
154:                defaultSearchPath = domains;
155:            }
156:
157:            /**
158:             * Sets the search path that will be used as the default by future Lookups.
159:             * @param domains The default search path.
160:             * @throws TextParseException A name in the array is not a valid DNS name.
161:             */
162:            public static synchronized void setDefaultSearchPath(
163:                    String[] domains) throws TextParseException {
164:                if (domains == null) {
165:                    defaultSearchPath = null;
166:                    return;
167:                }
168:                Name[] newdomains = new Name[domains.length];
169:                for (int i = 0; i < domains.length; i++)
170:                    newdomains[i] = Name.fromString(domains[i], Name.root);
171:                defaultSearchPath = newdomains;
172:            }
173:
174:            private final void reset() {
175:                iterations = 0;
176:                foundAlias = false;
177:                done = false;
178:                doneCurrent = false;
179:                aliases = null;
180:                answers = null;
181:                result = -1;
182:                error = null;
183:                nxdomain = false;
184:                badresponse = false;
185:                badresponse_error = null;
186:                networkerror = false;
187:                timedout = false;
188:                nametoolong = false;
189:                referral = false;
190:                if (temporary_cache)
191:                    cache.clearCache();
192:            }
193:
194:            /**
195:             * Create a Lookup object that will find records of the given name, type,
196:             * and class.  The lookup will use the default cache, resolver, and search
197:             * path, and look for records that are reasonably credible.
198:             * @param name The name of the desired records
199:             * @param type The type of the desired records
200:             * @param dclass The class of the desired records
201:             * @throws IllegalArgumentException The type is a meta type other than ANY.
202:             * @see Cache
203:             * @see Resolver
204:             * @see Credibility
205:             * @see Name
206:             * @see Type
207:             * @see DClass
208:             */
209:            public Lookup(Name name, int type, int dclass) {
210:                Type.check(type);
211:                DClass.check(dclass);
212:                if (!Type.isRR(type) && type != Type.ANY)
213:                    throw new IllegalArgumentException("Cannot query for "
214:                            + "meta-types other than ANY");
215:                this .name = name;
216:                this .type = type;
217:                this .dclass = dclass;
218:                synchronized (Lookup.class) {
219:                    this .resolver = getDefaultResolver();
220:                    this .searchPath = getDefaultSearchPath();
221:                    this .cache = getDefaultCache(dclass);
222:                }
223:                this .credibility = Credibility.NORMAL;
224:                this .verbose = Options.check("verbose");
225:                this .result = -1;
226:            }
227:
228:            /**
229:             * Create a Lookup object that will find records of the given name and type
230:             * in the IN class.
231:             * @param name The name of the desired records
232:             * @param type The type of the desired records
233:             * @throws IllegalArgumentException The type is a meta type other than ANY.
234:             * @see #Lookup(Name,int,int)
235:             */
236:            public Lookup(Name name, int type) {
237:                this (name, type, DClass.IN);
238:            }
239:
240:            /**
241:             * Create a Lookup object that will find records of type A at the given name
242:             * in the IN class.
243:             * @param name The name of the desired records
244:             * @see #Lookup(Name,int,int)
245:             */
246:            public Lookup(Name name) {
247:                this (name, Type.A, DClass.IN);
248:            }
249:
250:            /**
251:             * Create a Lookup object that will find records of the given name, type,
252:             * and class.
253:             * @param name The name of the desired records
254:             * @param type The type of the desired records
255:             * @param dclass The class of the desired records
256:             * @throws TextParseException The name is not a valid DNS name
257:             * @throws IllegalArgumentException The type is a meta type other than ANY.
258:             * @see #Lookup(Name,int,int)
259:             */
260:            public Lookup(String name, int type, int dclass)
261:                    throws TextParseException {
262:                this (Name.fromString(name), type, dclass);
263:            }
264:
265:            /**
266:             * Create a Lookup object that will find records of the given name and type
267:             * in the IN class.
268:             * @param name The name of the desired records
269:             * @param type The type of the desired records
270:             * @throws TextParseException The name is not a valid DNS name
271:             * @throws IllegalArgumentException The type is a meta type other than ANY.
272:             * @see #Lookup(Name,int,int)
273:             */
274:            public Lookup(String name, int type) throws TextParseException {
275:                this (Name.fromString(name), type, DClass.IN);
276:            }
277:
278:            /**
279:             * Create a Lookup object that will find records of type A at the given name
280:             * in the IN class.
281:             * @param name The name of the desired records
282:             * @throws TextParseException The name is not a valid DNS name
283:             * @see #Lookup(Name,int,int)
284:             */
285:            public Lookup(String name) throws TextParseException {
286:                this (Name.fromString(name), Type.A, DClass.IN);
287:            }
288:
289:            /**
290:             * Sets the resolver to use when performing this lookup.  This overrides the
291:             * default value.
292:             * @param resolver The resolver to use.
293:             */
294:            public void setResolver(Resolver resolver) {
295:                this .resolver = resolver;
296:            }
297:
298:            /**
299:             * Sets the search path to use when performing this lookup.  This overrides the
300:             * default value.
301:             * @param domains An array of names containing the search path.
302:             */
303:            public void setSearchPath(Name[] domains) {
304:                this .searchPath = domains;
305:            }
306:
307:            /**
308:             * Sets the search path to use when performing this lookup. This overrides the
309:             * default value.
310:             * @param domains An array of names containing the search path.
311:             * @throws TextParseException A name in the array is not a valid DNS name.
312:             */
313:            public void setSearchPath(String[] domains)
314:                    throws TextParseException {
315:                if (domains == null) {
316:                    this .searchPath = null;
317:                    return;
318:                }
319:                Name[] newdomains = new Name[domains.length];
320:                for (int i = 0; i < domains.length; i++)
321:                    newdomains[i] = Name.fromString(domains[i], Name.root);
322:                this .searchPath = newdomains;
323:            }
324:
325:            /**
326:             * Sets the cache to use when performing this lookup.  This overrides the
327:             * default value.  If the results of this lookup should not be permanently
328:             * cached, null can be provided here.
329:             * @param cache The cache to use.
330:             */
331:            public void setCache(Cache cache) {
332:                if (cache == null) {
333:                    this .cache = new Cache(dclass);
334:                    this .temporary_cache = true;
335:                } else {
336:                    this .cache = cache;
337:                    this .temporary_cache = false;
338:                }
339:            }
340:
341:            /**
342:             * Sets the minimum credibility level that will be accepted when performing
343:             * the lookup.  This defaults to Credibility.NORMAL.
344:             * @param credibility The minimum credibility level.
345:             */
346:            public void setCredibility(int credibility) {
347:                this .credibility = credibility;
348:            }
349:
350:            private void follow(Name name, Name oldname) {
351:                foundAlias = true;
352:                badresponse = false;
353:                networkerror = false;
354:                timedout = false;
355:                nxdomain = false;
356:                referral = false;
357:                iterations++;
358:                if (iterations >= 6 || name.equals(oldname)) {
359:                    result = UNRECOVERABLE;
360:                    error = "CNAME loop";
361:                    done = true;
362:                    return;
363:                }
364:                if (aliases == null)
365:                    aliases = new ArrayList();
366:                aliases.add(oldname);
367:                lookup(name);
368:            }
369:
370:            private void processResponse(Name name, SetResponse response) {
371:                if (response.isSuccessful()) {
372:                    RRset[] rrsets = response.answers();
373:                    List l = new ArrayList();
374:                    Iterator it;
375:                    int i;
376:
377:                    for (i = 0; i < rrsets.length; i++) {
378:                        it = rrsets[i].rrs();
379:                        while (it.hasNext())
380:                            l.add(it.next());
381:                    }
382:
383:                    result = SUCCESSFUL;
384:                    answers = (Record[]) l.toArray(new Record[l.size()]);
385:                    done = true;
386:                } else if (response.isNXDOMAIN()) {
387:                    nxdomain = true;
388:                    doneCurrent = true;
389:                    if (iterations > 0) {
390:                        result = HOST_NOT_FOUND;
391:                        done = true;
392:                    }
393:                } else if (response.isNXRRSET()) {
394:                    result = TYPE_NOT_FOUND;
395:                    answers = null;
396:                    done = true;
397:                } else if (response.isCNAME()) {
398:                    CNAMERecord cname = response.getCNAME();
399:                    follow(cname.getTarget(), name);
400:                } else if (response.isDNAME()) {
401:                    DNAMERecord dname = response.getDNAME();
402:                    Name newname = null;
403:                    try {
404:                        follow(name.fromDNAME(dname), name);
405:                    } catch (NameTooLongException e) {
406:                        result = UNRECOVERABLE;
407:                        error = "Invalid DNAME target";
408:                        done = true;
409:                    }
410:                } else if (response.isDelegation()) {
411:                    // We shouldn't get a referral.  Ignore it.
412:                    referral = true;
413:                }
414:            }
415:
416:            private void lookup(Name current) {
417:                SetResponse sr = cache
418:                        .lookupRecords(current, type, credibility);
419:                if (verbose) {
420:                    System.err.println("lookup " + current + " "
421:                            + Type.string(type));
422:                    System.err.println(sr);
423:                }
424:                processResponse(current, sr);
425:                if (done || doneCurrent)
426:                    return;
427:
428:                Record question = Record.newRecord(current, type, dclass);
429:                Message query = Message.newQuery(question);
430:                Message response = null;
431:                try {
432:                    response = resolver.send(query);
433:                } catch (IOException e) {
434:                    // A network error occurred.  Press on.
435:                    if (e instanceof  InterruptedIOException)
436:                        timedout = true;
437:                    else
438:                        networkerror = true;
439:                    return;
440:                }
441:                int rcode = response.getHeader().getRcode();
442:                if (rcode != Rcode.NOERROR && rcode != Rcode.NXDOMAIN) {
443:                    // The server we contacted is broken or otherwise unhelpful.
444:                    // Press on.
445:                    badresponse = true;
446:                    badresponse_error = Rcode.string(rcode);
447:                    return;
448:                }
449:
450:                if (!query.getQuestion().equals(response.getQuestion())) {
451:                    // The answer doesn't match the question.  That's not good.
452:                    badresponse = true;
453:                    badresponse_error = "response does not match query";
454:                    return;
455:                }
456:
457:                sr = cache.addMessage(response);
458:                if (sr == null)
459:                    sr = cache.lookupRecords(current, type, credibility);
460:                if (verbose) {
461:                    System.err.println("queried " + current + " "
462:                            + Type.string(type));
463:                    System.err.println(sr);
464:                }
465:                processResponse(current, sr);
466:            }
467:
468:            private void resolve(Name current, Name suffix) {
469:                doneCurrent = false;
470:                Name tname = null;
471:                if (suffix == null)
472:                    tname = current;
473:                else {
474:                    try {
475:                        tname = Name.concatenate(current, suffix);
476:                    } catch (NameTooLongException e) {
477:                        nametoolong = true;
478:                        return;
479:                    }
480:                }
481:                lookup(tname);
482:            }
483:
484:            /**
485:             * Performs the lookup, using the specified Cache, Resolver, and search path.
486:             * @return The answers, or null if none are found.
487:             */
488:            public Record[] run() {
489:                if (done)
490:                    reset();
491:                if (name.isAbsolute())
492:                    resolve(name, null);
493:                else if (searchPath == null)
494:                    resolve(name, Name.root);
495:                else {
496:                    if (name.labels() > 1)
497:                        resolve(name, Name.root);
498:                    if (done)
499:                        return answers;
500:
501:                    for (int i = 0; i < searchPath.length; i++) {
502:                        resolve(name, searchPath[i]);
503:                        if (done)
504:                            return answers;
505:                        else if (foundAlias)
506:                            break;
507:                    }
508:                }
509:                if (!done) {
510:                    if (badresponse) {
511:                        result = TRY_AGAIN;
512:                        error = badresponse_error;
513:                        done = true;
514:                    } else if (timedout) {
515:                        result = TRY_AGAIN;
516:                        error = "timed out";
517:                        done = true;
518:                    } else if (networkerror) {
519:                        result = TRY_AGAIN;
520:                        error = "network error";
521:                        done = true;
522:                    } else if (nxdomain) {
523:                        result = HOST_NOT_FOUND;
524:                        done = true;
525:                    } else if (referral) {
526:                        result = UNRECOVERABLE;
527:                        error = "referral";
528:                        done = true;
529:                    } else if (nametoolong) {
530:                        result = UNRECOVERABLE;
531:                        error = "name too long";
532:                        done = true;
533:                    }
534:                }
535:                return answers;
536:            }
537:
538:            private void checkDone() {
539:                if (done && result != -1)
540:                    return;
541:                StringBuffer sb = new StringBuffer("Lookup of " + name + " ");
542:                if (dclass != DClass.IN)
543:                    sb.append(DClass.string(dclass) + " ");
544:                sb.append(Type.string(type) + " isn't done");
545:                throw new IllegalStateException(sb.toString());
546:            }
547:
548:            /**
549:             * Returns the answers from the lookup.
550:             * @return The answers, or null if none are found.
551:             * @throws IllegalStateException The lookup has not completed.
552:             */
553:            public Record[] getAnswers() {
554:                checkDone();
555:                return answers;
556:            }
557:
558:            /**
559:             * Returns all known aliases for this name.  Whenever a CNAME/DNAME is
560:             * followed, an alias is added to this array.  The last element in this
561:             * array will be the owner name for records in the answer, if there are any.
562:             * @return The aliases.
563:             * @throws IllegalStateException The lookup has not completed.
564:             */
565:            public Name[] getAliases() {
566:                checkDone();
567:                if (aliases == null)
568:                    return noAliases;
569:                return (Name[]) aliases.toArray(new Name[aliases.size()]);
570:            }
571:
572:            /**
573:             * Returns the result code of the lookup.
574:             * @return The result code, which can be SUCCESSFUL, UNRECOVERABLE, TRY_AGAIN,
575:             * HOST_NOT_FOUND, or TYPE_NOT_FOUND.
576:             * @throws IllegalStateException The lookup has not completed.
577:             */
578:            public int getResult() {
579:                checkDone();
580:                return result;
581:            }
582:
583:            /**
584:             * Returns an error string describing the result code of this lookup.
585:             * @return A string, which may either directly correspond the result code
586:             * or be more specific.
587:             * @throws IllegalStateException The lookup has not completed.
588:             */
589:            public String getErrorString() {
590:                checkDone();
591:                if (error != null)
592:                    return error;
593:                switch (result) {
594:                case SUCCESSFUL:
595:                    return "successful";
596:                case UNRECOVERABLE:
597:                    return "unrecoverable error";
598:                case TRY_AGAIN:
599:                    return "try again";
600:                case HOST_NOT_FOUND:
601:                    return "host not found";
602:                case TYPE_NOT_FOUND:
603:                    return "type not found";
604:                }
605:                throw new IllegalStateException("unknown result");
606:            }
607:
608:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.