Source Code Cross Referenced for DnsContext.java in  » 6.0-JDK-Modules-com.sun » jndi » com » sun » jndi » 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 » 6.0 JDK Modules com.sun » jndi » com.sun.jndi.dns 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:         * Copyright 2000-2007 Sun Microsystems, Inc.  All Rights Reserved.
0003:         * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
0004:         *
0005:         * This code is free software; you can redistribute it and/or modify it
0006:         * under the terms of the GNU General Public License version 2 only, as
0007:         * published by the Free Software Foundation.  Sun designates this
0008:         * particular file as subject to the "Classpath" exception as provided
0009:         * by Sun in the LICENSE file that accompanied this code.
0010:         *
0011:         * This code is distributed in the hope that it will be useful, but WITHOUT
0012:         * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
0013:         * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
0014:         * version 2 for more details (a copy is included in the LICENSE file that
0015:         * accompanied this code).
0016:         *
0017:         * You should have received a copy of the GNU General Public License version
0018:         * 2 along with this work; if not, write to the Free Software Foundation,
0019:         * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
0020:         *
0021:         * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
0022:         * CA 95054 USA or visit www.sun.com if you need additional information or
0023:         * have any questions.
0024:         */
0025:
0026:        package com.sun.jndi.dns;
0027:
0028:        import java.util.Enumeration;
0029:        import java.util.Hashtable;
0030:
0031:        import javax.naming.*;
0032:        import javax.naming.directory.*;
0033:        import javax.naming.spi.DirectoryManager;
0034:
0035:        import com.sun.jndi.toolkit.ctx.*;
0036:
0037:        /**
0038:         * A DnsContext is a directory context representing a DNS node.
0039:         *
0040:         * @author Scott Seligman
0041:         * @version 1.30 07/05/05
0042:         */
0043:
0044:        public class DnsContext extends ComponentDirContext {
0045:
0046:            DnsName domain; // fully-qualified domain name of this context,
0047:            // with a root (empty) label at position 0
0048:            Hashtable environment;
0049:            private boolean envShared; // true if environment is possibly shared
0050:            // and so must be copied on write
0051:            private boolean parentIsDns; // was this DnsContext created by
0052:            // another?  see composeName()
0053:            private String[] servers;
0054:            private Resolver resolver;
0055:
0056:            private boolean authoritative; // must all responses be authoritative?
0057:            private boolean recursion; // request recursion on queries?
0058:            private int timeout; // initial timeout on UDP queries in ms
0059:            private int retries; // number of UDP retries
0060:
0061:            static final NameParser nameParser = new DnsNameParser();
0062:
0063:            // Timeouts for UDP queries use exponential backoff:  each retry
0064:            // is for twice as long as the last.  The following constants set
0065:            // the defaults for the initial timeout (in ms) and the number of
0066:            // retries, and name the environment properties used to override
0067:            // these defaults.
0068:            private static final int DEFAULT_INIT_TIMEOUT = 1000;
0069:            private static final int DEFAULT_RETRIES = 4;
0070:            private static final String INIT_TIMEOUT = "com.sun.jndi.dns.timeout.initial";
0071:            private static final String RETRIES = "com.sun.jndi.dns.timeout.retries";
0072:
0073:            // The resource record type and class to use for lookups, and the
0074:            // property used to modify them
0075:            private CT lookupCT;
0076:            private static final String LOOKUP_ATTR = "com.sun.jndi.dns.lookup.attr";
0077:
0078:            // Property used to disallow recursion on queries
0079:            private static final String RECURSION = "com.sun.jndi.dns.recursion";
0080:
0081:            // ANY == ResourceRecord.QCLASS_STAR == ResourceRecord.QTYPE_STAR
0082:            private static final int ANY = ResourceRecord.QTYPE_STAR;
0083:
0084:            // The zone tree used for list operations
0085:            private static final ZoneNode zoneTree = new ZoneNode(null);
0086:
0087:            /**
0088:             * Returns a DNS context for a given domain and servers.
0089:             * Each server is of the form "server[:port]".
0090:             * IPv6 literal host names include delimiting brackets.
0091:             * There must be at least one server.
0092:             * The environment must not be null; it is cloned before being stored.
0093:             */
0094:            public DnsContext(String domain, String[] servers,
0095:                    Hashtable environment) throws NamingException {
0096:
0097:                this .domain = new DnsName(domain.endsWith(".") ? domain
0098:                        : domain + ".");
0099:                this .servers = servers;
0100:                this .environment = (Hashtable) environment.clone();
0101:                envShared = false;
0102:                parentIsDns = false;
0103:                resolver = null;
0104:
0105:                initFromEnvironment();
0106:            }
0107:
0108:            /*
0109:             * Returns a clone of a DNS context, just like DnsContext(DnsContext)
0110:             * but with a different domain name and with parentIsDns set to true.
0111:             */
0112:            DnsContext(DnsContext ctx, DnsName domain) {
0113:                this (ctx);
0114:                this .domain = domain;
0115:                parentIsDns = true;
0116:            }
0117:
0118:            /*
0119:             * Returns a clone of a DNS context.  The context's modifiable
0120:             * private state is independent of the original's (so closing one
0121:             * context, for example, won't close the other).  The two contexts
0122:             * share <tt>environment</tt>, but it's copy-on-write so there's
0123:             * no conflict.
0124:             */
0125:            private DnsContext(DnsContext ctx) {
0126:                environment = ctx.environment;
0127:                envShared = ctx.envShared = true;
0128:                parentIsDns = ctx.parentIsDns;
0129:                domain = ctx.domain;
0130:                servers = ctx.servers;
0131:                resolver = ctx.resolver;
0132:                authoritative = ctx.authoritative;
0133:                recursion = ctx.recursion;
0134:                timeout = ctx.timeout;
0135:                retries = ctx.retries;
0136:                lookupCT = ctx.lookupCT;
0137:            }
0138:
0139:            public void close() {
0140:                if (resolver != null) {
0141:                    resolver.close();
0142:                    resolver = null;
0143:                }
0144:            }
0145:
0146:            //---------- Environment operations
0147:
0148:            /*
0149:             * Override default with a noncloning version.
0150:             */
0151:            protected Hashtable p_getEnvironment() {
0152:                return environment;
0153:            }
0154:
0155:            public Hashtable getEnvironment() throws NamingException {
0156:                return (Hashtable) environment.clone();
0157:            }
0158:
0159:            public Object addToEnvironment(String propName, Object propVal)
0160:                    throws NamingException {
0161:
0162:                if (propName.equals(LOOKUP_ATTR)) {
0163:                    lookupCT = getLookupCT((String) propVal);
0164:                } else if (propName.equals(Context.AUTHORITATIVE)) {
0165:                    authoritative = "true".equalsIgnoreCase((String) propVal);
0166:                } else if (propName.equals(RECURSION)) {
0167:                    recursion = "true".equalsIgnoreCase((String) propVal);
0168:                } else if (propName.equals(INIT_TIMEOUT)) {
0169:                    int val = Integer.parseInt((String) propVal);
0170:                    if (timeout != val) {
0171:                        timeout = val;
0172:                        resolver = null;
0173:                    }
0174:                } else if (propName.equals(RETRIES)) {
0175:                    int val = Integer.parseInt((String) propVal);
0176:                    if (retries != val) {
0177:                        retries = val;
0178:                        resolver = null;
0179:                    }
0180:                }
0181:
0182:                if (!envShared) {
0183:                    return environment.put(propName, propVal);
0184:                } else if (environment.get(propName) != propVal) {
0185:                    // copy on write
0186:                    environment = (Hashtable) environment.clone();
0187:                    envShared = false;
0188:                    return environment.put(propName, propVal);
0189:                } else {
0190:                    return propVal;
0191:                }
0192:            }
0193:
0194:            public Object removeFromEnvironment(String propName)
0195:                    throws NamingException {
0196:
0197:                if (propName.equals(LOOKUP_ATTR)) {
0198:                    lookupCT = getLookupCT(null);
0199:                } else if (propName.equals(Context.AUTHORITATIVE)) {
0200:                    authoritative = false;
0201:                } else if (propName.equals(RECURSION)) {
0202:                    recursion = true;
0203:                } else if (propName.equals(INIT_TIMEOUT)) {
0204:                    if (timeout != DEFAULT_INIT_TIMEOUT) {
0205:                        timeout = DEFAULT_INIT_TIMEOUT;
0206:                        resolver = null;
0207:                    }
0208:                } else if (propName.equals(RETRIES)) {
0209:                    if (retries != DEFAULT_RETRIES) {
0210:                        retries = DEFAULT_RETRIES;
0211:                        resolver = null;
0212:                    }
0213:                }
0214:
0215:                if (!envShared) {
0216:                    return environment.remove(propName);
0217:                } else if (environment.get(propName) != null) {
0218:                    // copy-on-write
0219:                    environment = (Hashtable) environment.clone();
0220:                    envShared = false;
0221:                    return environment.remove(propName);
0222:                } else {
0223:                    return null;
0224:                }
0225:            }
0226:
0227:            /*
0228:             * Update PROVIDER_URL property.  Call this only when environment
0229:             * is not being shared.
0230:             */
0231:            void setProviderUrl(String url) {
0232:                // assert !envShared;
0233:                environment.put(Context.PROVIDER_URL, url);
0234:            }
0235:
0236:            /*
0237:             * Read environment properties and set parameters.
0238:             */
0239:            private void initFromEnvironment()
0240:                    throws InvalidAttributeIdentifierException {
0241:
0242:                lookupCT = getLookupCT((String) environment.get(LOOKUP_ATTR));
0243:                authoritative = "true".equalsIgnoreCase((String) environment
0244:                        .get(Context.AUTHORITATIVE));
0245:                String val = (String) environment.get(RECURSION);
0246:                recursion = ((val == null) || "true".equalsIgnoreCase(val));
0247:                val = (String) environment.get(INIT_TIMEOUT);
0248:                timeout = (val == null) ? DEFAULT_INIT_TIMEOUT : Integer
0249:                        .parseInt(val);
0250:                val = (String) environment.get(RETRIES);
0251:                retries = (val == null) ? DEFAULT_RETRIES : Integer
0252:                        .parseInt(val);
0253:            }
0254:
0255:            private CT getLookupCT(String attrId)
0256:                    throws InvalidAttributeIdentifierException {
0257:                return (attrId == null) ? new CT(ResourceRecord.CLASS_INTERNET,
0258:                        ResourceRecord.TYPE_TXT) : fromAttrId(attrId);
0259:            }
0260:
0261:            //---------- Naming operations
0262:
0263:            public Object c_lookup(Name name, Continuation cont)
0264:                    throws NamingException {
0265:
0266:                cont.setSuccess();
0267:                if (name.isEmpty()) {
0268:                    DnsContext ctx = new DnsContext(this );
0269:                    ctx.resolver = new Resolver(servers, timeout, retries);
0270:                    // clone for parallelism
0271:                    return ctx;
0272:                }
0273:                try {
0274:                    DnsName fqdn = fullyQualify(name);
0275:                    ResourceRecords rrs = getResolver().query(fqdn,
0276:                            lookupCT.rrclass, lookupCT.rrtype, recursion,
0277:                            authoritative);
0278:                    Attributes attrs = rrsToAttrs(rrs, null);
0279:                    DnsContext ctx = new DnsContext(this , fqdn);
0280:                    return DirectoryManager.getObjectInstance(ctx, name, this ,
0281:                            environment, attrs);
0282:                } catch (NamingException e) {
0283:                    cont.setError(this , name);
0284:                    throw cont.fillInException(e);
0285:                } catch (Exception e) {
0286:                    cont.setError(this , name);
0287:                    NamingException ne = new NamingException(
0288:                            "Problem generating object using object factory");
0289:                    ne.setRootCause(e);
0290:                    throw cont.fillInException(ne);
0291:                }
0292:            }
0293:
0294:            public Object c_lookupLink(Name name, Continuation cont)
0295:                    throws NamingException {
0296:                return c_lookup(name, cont);
0297:            }
0298:
0299:            public NamingEnumeration c_list(Name name, Continuation cont)
0300:                    throws NamingException {
0301:                cont.setSuccess();
0302:                try {
0303:                    DnsName fqdn = fullyQualify(name);
0304:                    NameNode nnode = getNameNode(fqdn);
0305:                    DnsContext ctx = new DnsContext(this , fqdn);
0306:                    return new NameClassPairEnumeration(ctx, nnode
0307:                            .getChildren());
0308:
0309:                } catch (NamingException e) {
0310:                    cont.setError(this , name);
0311:                    throw cont.fillInException(e);
0312:                }
0313:            }
0314:
0315:            public NamingEnumeration c_listBindings(Name name, Continuation cont)
0316:                    throws NamingException {
0317:                cont.setSuccess();
0318:                try {
0319:                    DnsName fqdn = fullyQualify(name);
0320:                    NameNode nnode = getNameNode(fqdn);
0321:                    DnsContext ctx = new DnsContext(this , fqdn);
0322:                    return new BindingEnumeration(ctx, nnode.getChildren());
0323:
0324:                } catch (NamingException e) {
0325:                    cont.setError(this , name);
0326:                    throw cont.fillInException(e);
0327:                }
0328:            }
0329:
0330:            public void c_bind(Name name, Object obj, Continuation cont)
0331:                    throws NamingException {
0332:                cont.setError(this , name);
0333:                throw cont
0334:                        .fillInException(new OperationNotSupportedException());
0335:            }
0336:
0337:            public void c_rebind(Name name, Object obj, Continuation cont)
0338:                    throws NamingException {
0339:                cont.setError(this , name);
0340:                throw cont
0341:                        .fillInException(new OperationNotSupportedException());
0342:            }
0343:
0344:            public void c_unbind(Name name, Continuation cont)
0345:                    throws NamingException {
0346:                cont.setError(this , name);
0347:                throw cont
0348:                        .fillInException(new OperationNotSupportedException());
0349:            }
0350:
0351:            public void c_rename(Name oldname, Name newname, Continuation cont)
0352:                    throws NamingException {
0353:                cont.setError(this , oldname);
0354:                throw cont
0355:                        .fillInException(new OperationNotSupportedException());
0356:            }
0357:
0358:            public Context c_createSubcontext(Name name, Continuation cont)
0359:                    throws NamingException {
0360:                cont.setError(this , name);
0361:                throw cont
0362:                        .fillInException(new OperationNotSupportedException());
0363:            }
0364:
0365:            public void c_destroySubcontext(Name name, Continuation cont)
0366:                    throws NamingException {
0367:                cont.setError(this , name);
0368:                throw cont
0369:                        .fillInException(new OperationNotSupportedException());
0370:            }
0371:
0372:            public NameParser c_getNameParser(Name name, Continuation cont)
0373:                    throws NamingException {
0374:                cont.setSuccess();
0375:                return nameParser;
0376:            }
0377:
0378:            //---------- Directory operations
0379:
0380:            public void c_bind(Name name, Object obj, Attributes attrs,
0381:                    Continuation cont) throws NamingException {
0382:                cont.setError(this , name);
0383:                throw cont
0384:                        .fillInException(new OperationNotSupportedException());
0385:            }
0386:
0387:            public void c_rebind(Name name, Object obj, Attributes attrs,
0388:                    Continuation cont) throws NamingException {
0389:                cont.setError(this , name);
0390:                throw cont
0391:                        .fillInException(new OperationNotSupportedException());
0392:            }
0393:
0394:            public DirContext c_createSubcontext(Name name, Attributes attrs,
0395:                    Continuation cont) throws NamingException {
0396:                cont.setError(this , name);
0397:                throw cont
0398:                        .fillInException(new OperationNotSupportedException());
0399:            }
0400:
0401:            public Attributes c_getAttributes(Name name, String[] attrIds,
0402:                    Continuation cont) throws NamingException {
0403:
0404:                cont.setSuccess();
0405:                try {
0406:                    DnsName fqdn = fullyQualify(name);
0407:                    CT[] cts = attrIdsToClassesAndTypes(attrIds);
0408:                    CT ct = getClassAndTypeToQuery(cts);
0409:                    ResourceRecords rrs = getResolver().query(fqdn, ct.rrclass,
0410:                            ct.rrtype, recursion, authoritative);
0411:                    return rrsToAttrs(rrs, cts);
0412:
0413:                } catch (NamingException e) {
0414:                    cont.setError(this , name);
0415:                    throw cont.fillInException(e);
0416:                }
0417:            }
0418:
0419:            public void c_modifyAttributes(Name name, int mod_op,
0420:                    Attributes attrs, Continuation cont) throws NamingException {
0421:                cont.setError(this , name);
0422:                throw cont
0423:                        .fillInException(new OperationNotSupportedException());
0424:            }
0425:
0426:            public void c_modifyAttributes(Name name, ModificationItem[] mods,
0427:                    Continuation cont) throws NamingException {
0428:                cont.setError(this , name);
0429:                throw cont
0430:                        .fillInException(new OperationNotSupportedException());
0431:            }
0432:
0433:            public NamingEnumeration c_search(Name name,
0434:                    Attributes matchingAttributes, String[] attributesToReturn,
0435:                    Continuation cont) throws NamingException {
0436:                throw new OperationNotSupportedException();
0437:            }
0438:
0439:            public NamingEnumeration c_search(Name name, String filter,
0440:                    SearchControls cons, Continuation cont)
0441:                    throws NamingException {
0442:                throw new OperationNotSupportedException();
0443:            }
0444:
0445:            public NamingEnumeration c_search(Name name, String filterExpr,
0446:                    Object[] filterArgs, SearchControls cons, Continuation cont)
0447:                    throws NamingException {
0448:                throw new OperationNotSupportedException();
0449:            }
0450:
0451:            public DirContext c_getSchema(Name name, Continuation cont)
0452:                    throws NamingException {
0453:                cont.setError(this , name);
0454:                throw cont
0455:                        .fillInException(new OperationNotSupportedException());
0456:            }
0457:
0458:            public DirContext c_getSchemaClassDefinition(Name name,
0459:                    Continuation cont) throws NamingException {
0460:                cont.setError(this , name);
0461:                throw cont
0462:                        .fillInException(new OperationNotSupportedException());
0463:            }
0464:
0465:            //---------- Name-related operations
0466:
0467:            public String getNameInNamespace() {
0468:                return domain.toString();
0469:            }
0470:
0471:            public Name composeName(Name name, Name prefix)
0472:                    throws NamingException {
0473:                Name result;
0474:
0475:                // Any name that's not a CompositeName is assumed to be a DNS
0476:                // compound name.  Convert each to a DnsName for syntax checking.
0477:                if (!(prefix instanceof  DnsName || prefix instanceof  CompositeName)) {
0478:                    prefix = (new DnsName()).addAll(prefix);
0479:                }
0480:                if (!(name instanceof  DnsName || name instanceof  CompositeName)) {
0481:                    name = (new DnsName()).addAll(name);
0482:                }
0483:
0484:                // Each of prefix and name is now either a DnsName or a CompositeName.
0485:
0486:                // If we have two DnsNames, simply join them together.
0487:                if ((prefix instanceof  DnsName) && (name instanceof  DnsName)) {
0488:                    result = (DnsName) (prefix.clone());
0489:                    result.addAll(name);
0490:                    return new CompositeName().add(result.toString());
0491:                }
0492:
0493:                // Wrap compound names in composite names.
0494:                Name prefixC = (prefix instanceof  CompositeName) ? prefix
0495:                        : new CompositeName().add(prefix.toString());
0496:                Name nameC = (name instanceof  CompositeName) ? name
0497:                        : new CompositeName().add(name.toString());
0498:                int prefixLast = prefixC.size() - 1;
0499:
0500:                // Let toolkit do the work at namespace boundaries.
0501:                if (nameC.isEmpty() || nameC.get(0).equals("")
0502:                        || prefixC.isEmpty()
0503:                        || prefixC.get(prefixLast).equals("")) {
0504:                    return super .composeName(nameC, prefixC);
0505:                }
0506:
0507:                result = (prefix == prefixC) ? (CompositeName) prefixC.clone()
0508:                        : prefixC; // prefixC is already a clone
0509:                result.addAll(nameC);
0510:
0511:                if (parentIsDns) {
0512:                    DnsName dnsComp = (prefix instanceof  DnsName) ? (DnsName) prefix
0513:                            .clone()
0514:                            : new DnsName(prefixC.get(prefixLast));
0515:                    dnsComp.addAll((name instanceof  DnsName) ? name
0516:                            : new DnsName(nameC.get(0)));
0517:                    result.remove(prefixLast + 1);
0518:                    result.remove(prefixLast);
0519:                    result.add(prefixLast, dnsComp.toString());
0520:                }
0521:                return result;
0522:            }
0523:
0524:            //---------- Helper methods
0525:
0526:            /*
0527:             * Resolver is not created until needed, to allow time for updates
0528:             * to the environment.
0529:             */
0530:            private synchronized Resolver getResolver() throws NamingException {
0531:                if (resolver == null) {
0532:                    resolver = new Resolver(servers, timeout, retries);
0533:                }
0534:                return resolver;
0535:            }
0536:
0537:            /*
0538:             * Returns the fully-qualified domain name of a name given
0539:             * relative to this context.  Result includes a root label (an
0540:             * empty component at position 0).
0541:             */
0542:            DnsName fullyQualify(Name name) throws NamingException {
0543:                if (name.isEmpty()) {
0544:                    return domain;
0545:                }
0546:                DnsName dnsName = (name instanceof  CompositeName) ? new DnsName(
0547:                        name.get(0)) // parse name
0548:                        : (DnsName) (new DnsName()).addAll(name); // clone & check syntax
0549:
0550:                if (dnsName.hasRootLabel()) {
0551:                    // Be overly generous and allow root label if we're in root domain.
0552:                    if (domain.size() == 1) {
0553:                        return dnsName;
0554:                    } else {
0555:                        throw new InvalidNameException("DNS name " + dnsName
0556:                                + " not relative to " + domain);
0557:                    }
0558:                }
0559:                return (DnsName) dnsName.addAll(0, domain);
0560:            }
0561:
0562:            /*
0563:             * Converts resource records to an attribute set.  Only resource
0564:             * records in the answer section are used, and only those that
0565:             * match the classes and types in cts (see classAndTypeMatch()
0566:             * for matching rules).
0567:             */
0568:            private static Attributes rrsToAttrs(ResourceRecords rrs, CT[] cts) {
0569:
0570:                BasicAttributes attrs = new BasicAttributes(true);
0571:
0572:                for (int i = 0; i < rrs.answer.size(); i++) {
0573:                    ResourceRecord rr = (ResourceRecord) rrs.answer
0574:                            .elementAt(i);
0575:                    int rrtype = rr.getType();
0576:                    int rrclass = rr.getRrclass();
0577:
0578:                    if (!classAndTypeMatch(rrclass, rrtype, cts)) {
0579:                        continue;
0580:                    }
0581:
0582:                    String attrId = toAttrId(rrclass, rrtype);
0583:                    Attribute attr = attrs.get(attrId);
0584:                    if (attr == null) {
0585:                        attr = new BasicAttribute(attrId);
0586:                        attrs.put(attr);
0587:                    }
0588:                    attr.add(rr.getRdata());
0589:                }
0590:                return attrs;
0591:            }
0592:
0593:            /*
0594:             * Returns true if rrclass and rrtype match some element of cts.
0595:             * A match occurs if corresponding classes and types are equal,
0596:             * or if the array value is ANY.  If cts is null, then any class
0597:             * and type match.
0598:             */
0599:            private static boolean classAndTypeMatch(int rrclass, int rrtype,
0600:                    CT[] cts) {
0601:                if (cts == null) {
0602:                    return true;
0603:                }
0604:                for (int i = 0; i < cts.length; i++) {
0605:                    CT ct = cts[i];
0606:                    boolean classMatch = (ct.rrclass == ANY)
0607:                            || (ct.rrclass == rrclass);
0608:                    boolean typeMatch = (ct.rrtype == ANY)
0609:                            || (ct.rrtype == rrtype);
0610:                    if (classMatch && typeMatch) {
0611:                        return true;
0612:                    }
0613:                }
0614:                return false;
0615:            }
0616:
0617:            /*
0618:             * Returns the attribute ID for a resource record given its class
0619:             * and type.  If the record is in the internet class, the
0620:             * corresponding attribute ID is the record's type name (or the
0621:             * integer type value if the name is not known).  If the record is
0622:             * not in the internet class, the class name (or integer class
0623:             * value) is prepended to the attribute ID, separated by a space.
0624:             *
0625:             * A class or type value of ANY represents an indeterminate class
0626:             * or type, and is represented within the attribute ID by "*".
0627:             * For example, the attribute ID "IN *" represents
0628:             * any type in the internet class, and "* NS" represents an NS
0629:             * record of any class.
0630:             */
0631:            private static String toAttrId(int rrclass, int rrtype) {
0632:                String attrId = ResourceRecord.getTypeName(rrtype);
0633:                if (rrclass != ResourceRecord.CLASS_INTERNET) {
0634:                    attrId = ResourceRecord.getRrclassName(rrclass) + " "
0635:                            + attrId;
0636:                }
0637:                return attrId;
0638:            }
0639:
0640:            /*
0641:             * Returns the class and type values corresponding to an attribute
0642:             * ID.  An indeterminate class or type is represented by ANY.  See
0643:             * toAttrId() for the format of attribute IDs.
0644:             *
0645:             * @throws InvalidAttributeIdentifierException
0646:             *		if class or type is unknown
0647:             */
0648:            private static CT fromAttrId(String attrId)
0649:                    throws InvalidAttributeIdentifierException {
0650:
0651:                if (attrId.equals("")) {
0652:                    throw new InvalidAttributeIdentifierException(
0653:                            "Attribute ID cannot be empty");
0654:                }
0655:                int rrclass;
0656:                int rrtype;
0657:                int space = attrId.indexOf(' ');
0658:
0659:                // class
0660:                if (space < 0) {
0661:                    rrclass = ResourceRecord.CLASS_INTERNET;
0662:                } else {
0663:                    String className = attrId.substring(0, space);
0664:                    rrclass = ResourceRecord.getRrclass(className);
0665:                    if (rrclass < 0) {
0666:                        throw new InvalidAttributeIdentifierException(
0667:                                "Unknown resource record class '" + className
0668:                                        + '\'');
0669:                    }
0670:                }
0671:
0672:                // type
0673:                String typeName = attrId.substring(space + 1);
0674:                rrtype = ResourceRecord.getType(typeName);
0675:                if (rrtype < 0) {
0676:                    throw new InvalidAttributeIdentifierException(
0677:                            "Unknown resource record type '" + typeName + '\'');
0678:                }
0679:
0680:                return new CT(rrclass, rrtype);
0681:            }
0682:
0683:            /*
0684:             * Returns an array of the classes and types corresponding to a
0685:             * set of attribute IDs.  See toAttrId() for the format of
0686:             * attribute IDs, and classAndTypeMatch() for the format of the
0687:             * array returned.
0688:             */
0689:            private static CT[] attrIdsToClassesAndTypes(String[] attrIds)
0690:                    throws InvalidAttributeIdentifierException {
0691:                if (attrIds == null) {
0692:                    return null;
0693:                }
0694:                CT[] cts = new CT[attrIds.length];
0695:
0696:                for (int i = 0; i < attrIds.length; i++) {
0697:                    cts[i] = fromAttrId(attrIds[i]);
0698:                }
0699:                return cts;
0700:            }
0701:
0702:            /*
0703:             * Returns the most restrictive resource record class and type
0704:             * that may be used to query for records matching cts.
0705:             * See classAndTypeMatch() for matching rules.
0706:             */
0707:            private static CT getClassAndTypeToQuery(CT[] cts) {
0708:                int rrclass;
0709:                int rrtype;
0710:
0711:                if (cts == null) {
0712:                    // Query all records.
0713:                    rrclass = ANY;
0714:                    rrtype = ANY;
0715:                } else if (cts.length == 0) {
0716:                    // No records are requested, but we need to ask for something.
0717:                    rrclass = ResourceRecord.CLASS_INTERNET;
0718:                    rrtype = ANY;
0719:                } else {
0720:                    rrclass = cts[0].rrclass;
0721:                    rrtype = cts[0].rrtype;
0722:                    for (int i = 1; i < cts.length; i++) {
0723:                        if (rrclass != cts[i].rrclass) {
0724:                            rrclass = ANY;
0725:                        }
0726:                        if (rrtype != cts[i].rrtype) {
0727:                            rrtype = ANY;
0728:                        }
0729:                    }
0730:                }
0731:                return new CT(rrclass, rrtype);
0732:            }
0733:
0734:            //---------- Support for list operations
0735:
0736:            /*
0737:             * Synchronization notes:
0738:             *
0739:             * Any access to zoneTree that walks the tree, whether it modifies
0740:             * the tree or not, is synchronized on zoneTree.
0741:             * [%%% Note:  a read/write lock would allow increased concurrency.]
0742:             * The depth of a ZoneNode can thereafter be accessed without
0743:             * further synchronization.  Access to other fields and methods
0744:             * should be synchronized on the node itself.
0745:             *
0746:             * A zone's contents is a NameNode tree that, once created, is never
0747:             * modified.  The only synchronization needed is to ensure that it
0748:             * gets flushed into shared memory after being created, which is
0749:             * accomplished by ZoneNode.populate().  The contents are accessed
0750:             * via a soft reference, so a ZoneNode may be seen to be populated
0751:             * one moment and unpopulated the next.
0752:             */
0753:
0754:            /*
0755:             * Returns the node in the zone tree corresponding to a
0756:             * fully-qualified domain name.  If the desired portion of the
0757:             * tree has not yet been populated or has been outdated, a zone
0758:             * transfer is done to populate the tree.
0759:             */
0760:            private NameNode getNameNode(DnsName fqdn) throws NamingException {
0761:                dprint("getNameNode(" + fqdn + ")");
0762:
0763:                // Find deepest related zone in zone tree.
0764:                ZoneNode znode;
0765:                DnsName zone;
0766:                synchronized (zoneTree) {
0767:                    znode = zoneTree.getDeepestPopulated(fqdn);
0768:                }
0769:                dprint("Deepest related zone in zone tree: "
0770:                        + ((znode != null) ? znode.getLabel() : "[none]"));
0771:
0772:                NameNode topOfZone;
0773:                NameNode nnode;
0774:
0775:                if (znode != null) {
0776:                    synchronized (znode) {
0777:                        topOfZone = znode.getContents();
0778:                    }
0779:                    // If fqdn is in znode's zone, is not at a zone cut, and
0780:                    // is current, we're done.
0781:                    if (topOfZone != null) {
0782:                        nnode = topOfZone.get(fqdn, znode.depth() + 1); // +1 for root
0783:
0784:                        if ((nnode != null) && !nnode.isZoneCut()) {
0785:                            dprint("Found node " + fqdn + " in zone tree");
0786:                            zone = (DnsName) fqdn.getPrefix(znode.depth() + 1); // +1 for root
0787:                            boolean current = isZoneCurrent(znode, zone);
0788:                            boolean restart = false;
0789:
0790:                            synchronized (znode) {
0791:                                if (topOfZone != znode.getContents()) {
0792:                                    // Zone was modified while we were examining it.
0793:                                    // All bets are off.
0794:                                    restart = true;
0795:                                } else if (!current) {
0796:                                    znode.depopulate();
0797:                                } else {
0798:                                    return nnode; // cache hit!
0799:                                }
0800:                            }
0801:                            dprint("Zone not current; discarding node");
0802:                            if (restart) {
0803:                                return getNameNode(fqdn);
0804:                            }
0805:                        }
0806:                    }
0807:                }
0808:
0809:                // Cache miss...  do it the expensive way.
0810:                dprint("Adding node " + fqdn + " to zone tree");
0811:
0812:                // Find fqdn's zone and add it to the tree.
0813:                zone = getResolver().findZoneName(fqdn,
0814:                        ResourceRecord.CLASS_INTERNET, recursion);
0815:                dprint("Node's zone is " + zone);
0816:                synchronized (zoneTree) {
0817:                    znode = (ZoneNode) zoneTree.add(zone, 1); // "1" to skip root
0818:                }
0819:
0820:                // If znode is now populated we know -- because the first half of
0821:                // getNodeName() didn't find it -- that it was populated by another
0822:                // thread during this method call.  Assume then that it's current.
0823:
0824:                synchronized (znode) {
0825:                    topOfZone = znode.isPopulated() ? znode.getContents()
0826:                            : populateZone(znode, zone);
0827:                }
0828:                // Desired node should now be in znode's populated zone.  Find it.
0829:                nnode = topOfZone.get(fqdn, zone.size());
0830:                if (nnode == null) {
0831:                    throw new ConfigurationException(
0832:                            "DNS error: node not found in its own zone");
0833:                }
0834:                dprint("Found node in newly-populated zone");
0835:                return nnode;
0836:            }
0837:
0838:            /*
0839:             * Does a zone transfer to [re]populate a zone in the zone tree.
0840:             * Returns the zone's new contents.
0841:             */
0842:            private NameNode populateZone(ZoneNode znode, DnsName zone)
0843:                    throws NamingException {
0844:                dprint("Populating zone " + zone);
0845:                // assert Thread.holdsLock(znode);
0846:                ResourceRecords rrs = getResolver().queryZone(zone,
0847:                        ResourceRecord.CLASS_INTERNET, recursion);
0848:                dprint("zone xfer complete: " + rrs.answer.size() + " records");
0849:                return znode.populate(zone, rrs);
0850:            }
0851:
0852:            /*
0853:             * Determine if a ZoneNode's data is current.
0854:             * We base this on a comparison between the cached serial
0855:             * number and the latest SOA record.
0856:             *
0857:             * If there is no SOA record, znode is not (or is no longer) a zone:
0858:             * depopulate znode and return false.
0859:             *
0860:             * Since this method may perform a network operation, it is best
0861:             * to call it with znode unlocked.  Caller must then note that the
0862:             * result may be outdated by the time this method returns.
0863:             */
0864:            private boolean isZoneCurrent(ZoneNode znode, DnsName zone)
0865:                    throws NamingException {
0866:                // former version:  return !znode.isExpired();
0867:
0868:                if (!znode.isPopulated()) {
0869:                    return false;
0870:                }
0871:                ResourceRecord soa = getResolver().findSoa(zone,
0872:                        ResourceRecord.CLASS_INTERNET, recursion);
0873:                synchronized (znode) {
0874:                    if (soa == null) {
0875:                        znode.depopulate();
0876:                    }
0877:                    return (znode.isPopulated() && znode
0878:                            .compareSerialNumberTo(soa) >= 0);
0879:                }
0880:            }
0881:
0882:            //---------- Debugging
0883:
0884:            public static boolean debug = false;
0885:
0886:            private static final void dprint(String msg) {
0887:                if (debug) {
0888:                    System.err.println("** " + msg);
0889:                }
0890:            }
0891:        }
0892:
0893:        //----------
0894:
0895:        /*
0896:         * A pairing of a resource record class and a resource record type.
0897:         * A value of ANY in either field represents an indeterminate value.
0898:         */
0899:        class CT {
0900:            int rrclass;
0901:            int rrtype;
0902:
0903:            CT(int rrclass, int rrtype) {
0904:                this .rrclass = rrclass;
0905:                this .rrtype = rrtype;
0906:            }
0907:        }
0908:
0909:        //----------
0910:
0911:        /*
0912:         * An enumeration of name/classname pairs.
0913:         *
0914:         * Nodes that have children or that are zone cuts are returned with
0915:         * classname DirContext.  Other nodes are returned with classname
0916:         * Object even though they are DirContexts as well, since this might
0917:         * make the namespace easier to browse.
0918:         */
0919:        class NameClassPairEnumeration implements  NamingEnumeration {
0920:
0921:            protected Enumeration nodes; // nodes to be enumerated, or null if none
0922:            protected DnsContext ctx; // context being enumerated
0923:
0924:            NameClassPairEnumeration(DnsContext ctx, Hashtable nodes) {
0925:                this .ctx = ctx;
0926:                this .nodes = (nodes != null) ? nodes.elements() : null;
0927:            }
0928:
0929:            /*
0930:             * ctx will be closed when no longer needed by the enumeration.
0931:             */
0932:            public void close() {
0933:                nodes = null;
0934:                if (ctx != null) {
0935:                    ctx.close();
0936:                    ctx = null;
0937:                }
0938:            }
0939:
0940:            public boolean hasMore() {
0941:                boolean more = ((nodes != null) && nodes.hasMoreElements());
0942:                if (!more) {
0943:                    close();
0944:                }
0945:                return more;
0946:            }
0947:
0948:            public Object next() throws NamingException {
0949:                if (!hasMore()) {
0950:                    throw new java.util.NoSuchElementException();
0951:                }
0952:                NameNode nnode = (NameNode) nodes.nextElement();
0953:                String className = (nnode.isZoneCut() || (nnode.getChildren() != null)) ? "javax.naming.directory.DirContext"
0954:                        : "java.lang.Object";
0955:
0956:                String label = nnode.getLabel();
0957:                Name compName = (new DnsName()).add(label);
0958:                Name cname = (new CompositeName()).add(compName.toString());
0959:
0960:                NameClassPair ncp = new NameClassPair(cname.toString(),
0961:                        className);
0962:                ncp.setNameInNamespace(ctx.fullyQualify(cname).toString());
0963:                return ncp;
0964:            }
0965:
0966:            public boolean hasMoreElements() {
0967:                return hasMore();
0968:            }
0969:
0970:            public Object nextElement() {
0971:                try {
0972:                    return next();
0973:                } catch (NamingException e) {
0974:                    throw (new java.util.NoSuchElementException(
0975:                            "javax.naming.NamingException was thrown: "
0976:                                    + e.getMessage()));
0977:                }
0978:            }
0979:        }
0980:
0981:        /*
0982:         * An enumeration of Bindings.
0983:         */
0984:        class BindingEnumeration extends NameClassPairEnumeration {
0985:
0986:            BindingEnumeration(DnsContext ctx, Hashtable nodes) {
0987:                super (ctx, nodes);
0988:            }
0989:
0990:            // Finalizer not needed since it's safe to leave ctx unclosed.
0991:            //  protected void finalize() {
0992:            //	close();
0993:            //  }
0994:
0995:            public Object next() throws NamingException {
0996:                if (!hasMore()) {
0997:                    throw (new java.util.NoSuchElementException());
0998:                }
0999:                NameNode nnode = (NameNode) nodes.nextElement();
1000:
1001:                String label = nnode.getLabel();
1002:                Name compName = (new DnsName()).add(label);
1003:                String compNameStr = compName.toString();
1004:                Name cname = (new CompositeName()).add(compNameStr);
1005:                String cnameStr = cname.toString();
1006:
1007:                DnsName fqdn = ctx.fullyQualify(compName);
1008:
1009:                // Clone ctx to create the child context.
1010:                DnsContext child = new DnsContext(ctx, fqdn);
1011:
1012:                try {
1013:                    Object obj = DirectoryManager.getObjectInstance(child,
1014:                            cname, ctx, child.environment, null);
1015:                    Binding binding = new Binding(cnameStr, obj);
1016:                    binding.setNameInNamespace(ctx.fullyQualify(cname)
1017:                            .toString());
1018:                    return binding;
1019:                } catch (Exception e) {
1020:                    NamingException ne = new NamingException(
1021:                            "Problem generating object using object factory");
1022:                    ne.setRootCause(e);
1023:                    throw ne;
1024:                }
1025:            }
1026:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.