You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@directory.apache.org by er...@apache.org on 2005/10/28 23:37:43 UTC

svn commit: r329308 - in /directory/protocol-providers/dns/trunk/src/java/org/apache/dns: ./ messages/ service/ store/ store/operations/

Author: erodriguez
Date: Fri Oct 28 14:37:33 2005
New Revision: 329308

URL: http://svn.apache.org/viewcvs?rev=329308&view=rev
Log:
Added multi-zone support to dns-protocol:
o  Updates to the record store to support switching strategies based on configuration.
o  Catalog for resolving zones to domain components.
o  Multi-base search strategy.
o  Single-base search strategy.

Added:
    directory/protocol-providers/dns/trunk/src/java/org/apache/dns/DnsServer.java   (with props)
    directory/protocol-providers/dns/trunk/src/java/org/apache/dns/store/DnsCatalog.java   (with props)
    directory/protocol-providers/dns/trunk/src/java/org/apache/dns/store/MultiBaseSearch.java   (with props)
    directory/protocol-providers/dns/trunk/src/java/org/apache/dns/store/SearchStrategy.java   (with props)
    directory/protocol-providers/dns/trunk/src/java/org/apache/dns/store/SingleBaseSearch.java   (with props)
    directory/protocol-providers/dns/trunk/src/java/org/apache/dns/store/operations/GetFlatRecord.java
      - copied, changed from r328198, directory/protocol-providers/dns/trunk/src/java/org/apache/dns/store/operations/GetRecord.java
    directory/protocol-providers/dns/trunk/src/java/org/apache/dns/store/operations/GetRecords.java   (with props)
Removed:
    directory/protocol-providers/dns/trunk/src/java/org/apache/dns/store/operations/GetRecord.java
Modified:
    directory/protocol-providers/dns/trunk/src/java/org/apache/dns/DnsConfiguration.java
    directory/protocol-providers/dns/trunk/src/java/org/apache/dns/messages/ResourceRecords.java
    directory/protocol-providers/dns/trunk/src/java/org/apache/dns/service/DnsContext.java
    directory/protocol-providers/dns/trunk/src/java/org/apache/dns/service/GetResourceRecords.java
    directory/protocol-providers/dns/trunk/src/java/org/apache/dns/store/JndiRecordStoreImpl.java
    directory/protocol-providers/dns/trunk/src/java/org/apache/dns/store/RecordStore.java

Modified: directory/protocol-providers/dns/trunk/src/java/org/apache/dns/DnsConfiguration.java
URL: http://svn.apache.org/viewcvs/directory/protocol-providers/dns/trunk/src/java/org/apache/dns/DnsConfiguration.java?rev=329308&r1=329307&r2=329308&view=diff
==============================================================================
--- directory/protocol-providers/dns/trunk/src/java/org/apache/dns/DnsConfiguration.java (original)
+++ directory/protocol-providers/dns/trunk/src/java/org/apache/dns/DnsConfiguration.java Fri Oct 28 14:37:33 2005
@@ -21,35 +21,30 @@
 import java.util.Map;
 
 import org.apache.ldap.server.DirectoryService;
-import org.apache.ldap.server.configuration.Configuration;
 import org.apache.ldap.server.configuration.ConfigurationException;
+import org.apache.protocol.common.LoadStrategy;
+import org.apache.protocol.common.ServiceConfiguration;
 
-public class DnsConfiguration extends Configuration
+public class DnsConfiguration extends ServiceConfiguration
 {
-    /** the prop key const for the port */
-    public static final String DNS_PORT_KEY = "dns.port";
-
-    /** the prop key const for dns.buffer.size */
-    public static final String DNS_BUFFER_SIZE_KEY = "dns.buffer.size";
-
     /** the default port */
-    private static final String DNS_DEFAULT_PORT = "53";
+    private static final String DEFAULT_IP_PORT = "53";
 
-    private static final String SERVICE_PID = "service.pid";
-    private static final String PID = "org.apache.dns";
-    private static final String name = "Apache DNS Service";
+    /** the default pid */
+    private static final String DEFAULT_PID = "org.apache.dns";
 
-    /** the default dns buffer size */
-    private static final int DNS_DEFAULT_BUFFER_SIZE = 1024;
+    /** the default name */
+    private static final String DEFAULT_NAME = "Apache DNS Service";
 
-    private Map configuration = new HashMap();
+    /** the default prefix */
+    private static final String DEFAULT_PREFIX = "dns.";
 
     /**
      * Creates a new instance with default settings.
      */
     public DnsConfiguration()
     {
-        this( getDefaultConfig() );
+        this( getDefaultConfig(), LoadStrategy.LDAP );
     }
 
     /**
@@ -58,26 +53,31 @@
      */
     public DnsConfiguration( String instanceId )
     {
-        this( getDefaultConfig() );
+        this( getDefaultConfig(), LoadStrategy.LDAP );
         setInstanceId( instanceId );
     }
 
     public DnsConfiguration( Map properties )
     {
+        this( properties, LoadStrategy.LDAP );
+    }
+
+    public DnsConfiguration( Map properties, int strategy )
+    {
         if ( properties == null )
         {
             configuration = getDefaultConfig();
         }
         else
         {
-            configuration.putAll( properties );
+            loadProperties( DEFAULT_PREFIX, properties, strategy );
         }
 
         int port = getPort();
 
         if ( port < 1 || port > 0xFFFF )
         {
-            throw new ConfigurationException( "Invalid value:  " + DNS_PORT_KEY + "=" + port );
+            throw new ConfigurationException( "Invalid value:  " + IP_PORT_KEY + "=" + port );
         }
     }
 
@@ -85,8 +85,8 @@
     {
         Map defaults = new HashMap();
 
-        defaults.put( SERVICE_PID, PID );
-        defaults.put( DNS_PORT_KEY, DNS_DEFAULT_PORT );
+        defaults.put( SERVICE_PID, DEFAULT_PID );
+        defaults.put( IP_PORT_KEY, DEFAULT_IP_PORT );
 
         return defaults;
     }
@@ -95,7 +95,7 @@
     {
         int port = getPort();
 
-        if ( port == Integer.parseInt( (String) config.get( DNS_PORT_KEY ) ) )
+        if ( port == Integer.parseInt( (String) config.get( IP_PORT_KEY ) ) )
         {
             return false;
         }
@@ -105,35 +105,30 @@
 
     public String getName()
     {
-        return name;
+        return DEFAULT_NAME;
     }
 
     public int getPort()
     {
-        String key = DNS_PORT_KEY;
+        String key = IP_PORT_KEY;
 
         if ( configuration.containsKey( key ) )
         {
             return Integer.parseInt( get( key ) );
         }
 
-        return Integer.parseInt( DNS_DEFAULT_PORT );
+        return Integer.parseInt( DEFAULT_IP_PORT );
     }
 
     public int getBufferSize()
     {
-        String key = DNS_BUFFER_SIZE_KEY;
+        String key = BUFFER_SIZE_KEY;
 
         if ( configuration.containsKey( key ) )
         {
             return Integer.parseInt( get( key ) );
         }
 
-        return DNS_DEFAULT_BUFFER_SIZE;
-    }
-
-    private String get( String key )
-    {
-        return (String) configuration.get( key );
+        return DEFAULT_BUFFER_SIZE;
     }
 }

Added: directory/protocol-providers/dns/trunk/src/java/org/apache/dns/DnsServer.java
URL: http://svn.apache.org/viewcvs/directory/protocol-providers/dns/trunk/src/java/org/apache/dns/DnsServer.java?rev=329308&view=auto
==============================================================================
--- directory/protocol-providers/dns/trunk/src/java/org/apache/dns/DnsServer.java (added)
+++ directory/protocol-providers/dns/trunk/src/java/org/apache/dns/DnsServer.java Fri Oct 28 14:37:33 2005
@@ -0,0 +1,89 @@
+/*
+ *   Copyright 2005 The Apache Software Foundation
+ *
+ *   Licensed under the Apache License, Version 2.0 (the "License");
+ *   you may not use this file except in compliance with the License.
+ *   You may obtain a copy of the License at
+ *
+ *       http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *   Unless required by applicable law or agreed to in writing, software
+ *   distributed under the License is distributed on an "AS IS" BASIS,
+ *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *   See the License for the specific language governing permissions and
+ *   limitations under the License.
+ *
+ */
+
+package org.apache.dns;
+
+import java.io.IOException;
+import java.util.Dictionary;
+
+import org.apache.dns.protocol.DnsProtocolProvider;
+import org.apache.dns.store.RecordStore;
+import org.apache.mina.common.TransportType;
+import org.apache.mina.protocol.ProtocolProvider;
+import org.apache.mina.registry.Service;
+import org.apache.mina.registry.ServiceRegistry;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class DnsServer
+{
+    /** the log for this class */
+    private static final Logger log = LoggerFactory.getLogger( DnsServer.class );
+
+    private DnsConfiguration config;
+    private ServiceRegistry registry;
+    private RecordStore store;
+
+    private ProtocolProvider provider;
+    private Service tcpService;
+    private Service udpService;
+
+    public DnsServer( DnsConfiguration config, ServiceRegistry registry, RecordStore store )
+    {
+        this.config = config;
+        this.registry = registry;
+        this.store = store;
+
+        String name = config.getName();
+        int port = config.getPort();
+
+        try
+        {
+            provider = new DnsProtocolProvider( config, this.store );
+
+            udpService = new Service( name, TransportType.DATAGRAM, port );
+            tcpService = new Service( name, TransportType.SOCKET, port );
+
+            registry.bind( udpService, provider );
+            registry.bind( tcpService, provider );
+
+            log.debug( name + " listening on port " + port );
+        }
+        catch ( IOException ioe )
+        {
+            log.error( ioe.getMessage(), ioe );
+        }
+    }
+
+    public boolean isDifferent( Dictionary newConfig )
+    {
+        return config.isDifferent( newConfig );
+    }
+
+    public void destroy()
+    {
+        registry.unbind( udpService );
+        registry.unbind( tcpService );
+
+        registry = null;
+        provider = null;
+        udpService = null;
+        tcpService = null;
+
+        log.debug( config.getName() + " has stopped listening on port " + config.getPort() );
+    }
+}

Propchange: directory/protocol-providers/dns/trunk/src/java/org/apache/dns/DnsServer.java
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: directory/protocol-providers/dns/trunk/src/java/org/apache/dns/messages/ResourceRecords.java
URL: http://svn.apache.org/viewcvs/directory/protocol-providers/dns/trunk/src/java/org/apache/dns/messages/ResourceRecords.java?rev=329308&r1=329307&r2=329308&view=diff
==============================================================================
--- directory/protocol-providers/dns/trunk/src/java/org/apache/dns/messages/ResourceRecords.java (original)
+++ directory/protocol-providers/dns/trunk/src/java/org/apache/dns/messages/ResourceRecords.java Fri Oct 28 14:37:33 2005
@@ -18,6 +18,7 @@
 package org.apache.dns.messages;
 
 import java.util.ArrayList;
+import java.util.Collection;
 import java.util.Iterator;
 import java.util.List;
 
@@ -38,6 +39,11 @@
     public void add( ResourceRecord record )
     {
         resourceRecords.add( record );
+    }
+
+    public void addAll( Collection records )
+    {
+        resourceRecords.addAll( records );
     }
 
     public int size()

Modified: directory/protocol-providers/dns/trunk/src/java/org/apache/dns/service/DnsContext.java
URL: http://svn.apache.org/viewcvs/directory/protocol-providers/dns/trunk/src/java/org/apache/dns/service/DnsContext.java?rev=329308&r1=329307&r2=329308&view=diff
==============================================================================
--- directory/protocol-providers/dns/trunk/src/java/org/apache/dns/service/DnsContext.java (original)
+++ directory/protocol-providers/dns/trunk/src/java/org/apache/dns/service/DnsContext.java Fri Oct 28 14:37:33 2005
@@ -16,6 +16,9 @@
  */
 package org.apache.dns.service;
 
+import java.util.Collection;
+
+import org.apache.dns.DnsConfiguration;
 import org.apache.dns.messages.DnsMessage;
 import org.apache.dns.messages.ResourceRecord;
 import org.apache.dns.messages.ResourceRecords;
@@ -44,6 +47,14 @@
     public void addResourceRecord( ResourceRecord resourceRecord )
     {
         this.records.add( resourceRecord );
+    }
+
+    /**
+     * @param resourceRecords The resourceRecords to add.
+     */
+    public void addResourceRecords( Collection resourceRecords )
+    {
+        this.records.addAll( resourceRecords );
     }
 
     /**

Modified: directory/protocol-providers/dns/trunk/src/java/org/apache/dns/service/GetResourceRecords.java
URL: http://svn.apache.org/viewcvs/directory/protocol-providers/dns/trunk/src/java/org/apache/dns/service/GetResourceRecords.java?rev=329308&r1=329307&r2=329308&view=diff
==============================================================================
--- directory/protocol-providers/dns/trunk/src/java/org/apache/dns/service/GetResourceRecords.java (original)
+++ directory/protocol-providers/dns/trunk/src/java/org/apache/dns/service/GetResourceRecords.java Fri Oct 28 14:37:33 2005
@@ -17,11 +17,11 @@
 package org.apache.dns.service;
 
 import java.util.Iterator;
+import java.util.Set;
 
 import org.apache.dns.DnsException;
 import org.apache.dns.messages.QuestionRecord;
 import org.apache.dns.messages.QuestionRecords;
-import org.apache.dns.messages.ResourceRecord;
 import org.apache.dns.messages.ResponseCode;
 import org.apache.dns.store.RecordStore;
 import org.apache.protocol.common.chain.Context;
@@ -40,30 +40,30 @@
 
         while ( it.hasNext() )
         {
-            dnsContext.addResourceRecord( getEntry( store, (QuestionRecord) it.next() ) );
+            dnsContext.addResourceRecords( getEntry( store, (QuestionRecord) it.next() ) );
         }
 
         return CONTINUE_CHAIN;
     }
 
-    public ResourceRecord getEntry( RecordStore store, QuestionRecord question ) throws Exception
+    public Set getEntry( RecordStore store, QuestionRecord question ) throws Exception
     {
-        ResourceRecord record = null;
+        Set records = null;
 
         try
         {
-            record = store.getRecord( question );
+            records = store.getRecords( question );
         }
         catch ( Exception e )
         {
             throw new DnsException( ResponseCode.SERVER_FAILURE );
         }
 
-        if ( record == null )
+        if ( records == null || records.isEmpty() )
         {
             throw new DnsException( ResponseCode.NAME_ERROR );
         }
 
-        return record;
+        return records;
     }
 }

Added: directory/protocol-providers/dns/trunk/src/java/org/apache/dns/store/DnsCatalog.java
URL: http://svn.apache.org/viewcvs/directory/protocol-providers/dns/trunk/src/java/org/apache/dns/store/DnsCatalog.java?rev=329308&view=auto
==============================================================================
--- directory/protocol-providers/dns/trunk/src/java/org/apache/dns/store/DnsCatalog.java (added)
+++ directory/protocol-providers/dns/trunk/src/java/org/apache/dns/store/DnsCatalog.java Fri Oct 28 14:37:33 2005
@@ -0,0 +1,69 @@
+/*
+ *   Copyright 2005 The Apache Software Foundation
+ *
+ *   Licensed under the Apache License, Version 2.0 (the "License");
+ *   you may not use this file except in compliance with the License.
+ *   You may obtain a copy of the License at
+ *
+ *       http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *   Unless required by applicable law or agreed to in writing, software
+ *   distributed under the License is distributed on an "AS IS" BASIS,
+ *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *   See the License for the specific language governing permissions and
+ *   limitations under the License.
+ *
+ */
+
+package org.apache.dns.store;
+
+import java.util.Map;
+
+import org.apache.protocol.common.catalog.Catalog;
+
+/**
+ * A catalog for mapping DNS zones to search base DN's. 
+ * 
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$
+ */
+class DnsCatalog implements Catalog
+{
+    private Map map;
+
+    public DnsCatalog( Map map )
+    {
+        this.map = map;
+    }
+
+    public String getBaseDn( String name )
+    {
+        if ( name.endsWith( "." ) )
+        {
+            int last = name.lastIndexOf( "." );
+            name = name.substring( 0, last );
+        }
+
+        while ( !name.equals( "" ) && name != null )
+        {
+            String candidate = (String) map.get( name );
+            if ( candidate != null )
+            {
+                return candidate;
+            }
+
+            int period = name.indexOf( "." );
+
+            if ( period > -1 )
+            {
+                name = name.substring( period + 1 );
+            }
+            else
+            {
+                return "";
+            }
+        }
+
+        return "";
+    }
+}

Propchange: directory/protocol-providers/dns/trunk/src/java/org/apache/dns/store/DnsCatalog.java
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: directory/protocol-providers/dns/trunk/src/java/org/apache/dns/store/JndiRecordStoreImpl.java
URL: http://svn.apache.org/viewcvs/directory/protocol-providers/dns/trunk/src/java/org/apache/dns/store/JndiRecordStoreImpl.java?rev=329308&r1=329307&r2=329308&view=diff
==============================================================================
--- directory/protocol-providers/dns/trunk/src/java/org/apache/dns/store/JndiRecordStoreImpl.java (original)
+++ directory/protocol-providers/dns/trunk/src/java/org/apache/dns/store/JndiRecordStoreImpl.java Fri Oct 28 14:37:33 2005
@@ -16,49 +16,52 @@
  */
 package org.apache.dns.store;
 
-import javax.naming.Name;
-import javax.naming.ldap.LdapContext;
+import java.util.Set;
 
+import javax.naming.spi.InitialContextFactory;
+
+import org.apache.dns.DnsConfiguration;
 import org.apache.dns.messages.QuestionRecord;
-import org.apache.dns.messages.ResourceRecord;
-import org.apache.dns.store.operations.GetRecord;
-import org.apache.protocol.common.store.ContextOperation;
 
 /**
- * A simple implementation of the RecordStore interface using a JNDI-based store.
+ * A JNDI-backed implementation of the RecordStore interface.  This RecordStore uses
+ * the Strategy pattern to either serve records based on a single base DN or to lookup
+ * catalog mappings from directory configuration.
  * 
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  * @version $Rev$, $Date$
  */
 public class JndiRecordStoreImpl implements RecordStore
 {
-    /** a handle on the provider context */
-    private LdapContext ctx;
-
-    /** the search searchBase relative to the DN of the context supplied */
-    private Name searchBase;
+    /** a handle on the configuration */
+    private DnsConfiguration config;
+    /** a handle on the provider factory */
+    private InitialContextFactory factory;
+    /** a handle on the searchh strategy */
+    private SearchStrategy strategy;
 
-    /**
-     * Creates the action to be used against the embedded ApacheDS DIT.  Note
-     * the searchBase is a relative name to the context and not a DN.
-     *
-     * @param ctx the JNDI context to the store
-     * @param searchBase the name relative to the context to use as the search base
-     */
-    public JndiRecordStoreImpl( LdapContext ctx, Name searchBase )
+    public JndiRecordStoreImpl( DnsConfiguration config, InitialContextFactory factory )
     {
-        this.ctx = ctx;
+        this.config = config;
+        this.factory = factory;
 
-        this.searchBase = searchBase;
+        strategy = getSearchStrategy();
     }
 
-    public ResourceRecord getRecord( QuestionRecord question ) throws Exception
+    public Set getRecords( QuestionRecord question ) throws Exception
     {
-        return (ResourceRecord) execute( new GetRecord( question ) );
+        return strategy.getRecords( question );
     }
 
-    private Object execute( ContextOperation operation ) throws Exception
+    private SearchStrategy getSearchStrategy()
     {
-        return operation.execute( ctx, searchBase );
+        if ( config.getCatalogBaseDn() != null )
+        {
+            // build catalog from factory
+            return new MultiBaseSearch( config, factory );
+        }
+
+        // use config for catalog baseDN
+        return new SingleBaseSearch( config, factory );
     }
 }

Added: directory/protocol-providers/dns/trunk/src/java/org/apache/dns/store/MultiBaseSearch.java
URL: http://svn.apache.org/viewcvs/directory/protocol-providers/dns/trunk/src/java/org/apache/dns/store/MultiBaseSearch.java?rev=329308&view=auto
==============================================================================
--- directory/protocol-providers/dns/trunk/src/java/org/apache/dns/store/MultiBaseSearch.java (added)
+++ directory/protocol-providers/dns/trunk/src/java/org/apache/dns/store/MultiBaseSearch.java Fri Oct 28 14:37:33 2005
@@ -0,0 +1,99 @@
+/*
+ *   Copyright 2005 The Apache Software Foundation
+ *
+ *   Licensed under the Apache License, Version 2.0 (the "License");
+ *   you may not use this file except in compliance with the License.
+ *   You may obtain a copy of the License at
+ *
+ *       http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *   Unless required by applicable law or agreed to in writing, software
+ *   distributed under the License is distributed on an "AS IS" BASIS,
+ *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *   See the License for the specific language governing permissions and
+ *   limitations under the License.
+ *
+ */
+
+package org.apache.dns.store;
+
+import java.util.Hashtable;
+import java.util.Map;
+import java.util.Set;
+
+import javax.naming.Context;
+import javax.naming.NamingException;
+import javax.naming.directory.DirContext;
+import javax.naming.spi.InitialContextFactory;
+
+import org.apache.dns.DnsConfiguration;
+import org.apache.dns.messages.QuestionRecord;
+import org.apache.dns.store.operations.GetRecords;
+import org.apache.ldap.server.configuration.ConfigurationException;
+import org.apache.protocol.common.catalog.Catalog;
+import org.apache.protocol.common.catalog.GetCatalog;
+import org.apache.protocol.common.store.ContextOperation;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * A JNDI-backed search strategy implementation.  This search strategy builds a catalog
+ * from directory configuration to determine where zones are to search for
+ * resource records.
+ * 
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$
+ */
+public class MultiBaseSearch implements SearchStrategy
+{
+    /** the log for this class */
+    private static final Logger log = LoggerFactory.getLogger( MultiBaseSearch.class );
+
+    private InitialContextFactory factory;
+    private Hashtable env;
+
+    private Catalog catalog;
+
+    MultiBaseSearch( DnsConfiguration config, InitialContextFactory factory )
+    {
+        this.factory = factory;
+
+        env = new Hashtable( config.toJndiEnvironment() );
+        env.put( Context.INITIAL_CONTEXT_FACTORY, config.getInitialContextFactory() );
+        env.put( Context.PROVIDER_URL, config.getCatalogBaseDn() );
+
+        try
+        {
+            DirContext ctx = (DirContext) factory.getInitialContext( env );
+            catalog = new DnsCatalog( (Map) execute( ctx, new GetCatalog() ) );
+        }
+        catch ( Exception e )
+        {
+            log.error( e.getMessage(), e );
+            String message = "Failed to get catalog context " + (String) env.get( Context.PROVIDER_URL );
+            throw new ConfigurationException( message );
+        }
+    }
+
+    public Set getRecords( QuestionRecord question ) throws Exception
+    {
+        env.put( Context.PROVIDER_URL, catalog.getBaseDn( question.getDomainName() ) );
+
+        try
+        {
+            DirContext ctx = (DirContext) factory.getInitialContext( env );
+            return (Set) execute( ctx, new GetRecords( question ) );
+        }
+        catch ( NamingException ne )
+        {
+            log.error( ne.getMessage(), ne );
+            String message = "Failed to get initial context " + (String) env.get( Context.PROVIDER_URL );
+            throw new ConfigurationException( message );
+        }
+    }
+
+    private Object execute( DirContext ctx, ContextOperation operation ) throws Exception
+    {
+        return operation.execute( ctx, null );
+    }
+}

Propchange: directory/protocol-providers/dns/trunk/src/java/org/apache/dns/store/MultiBaseSearch.java
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: directory/protocol-providers/dns/trunk/src/java/org/apache/dns/store/RecordStore.java
URL: http://svn.apache.org/viewcvs/directory/protocol-providers/dns/trunk/src/java/org/apache/dns/store/RecordStore.java?rev=329308&r1=329307&r2=329308&view=diff
==============================================================================
--- directory/protocol-providers/dns/trunk/src/java/org/apache/dns/store/RecordStore.java (original)
+++ directory/protocol-providers/dns/trunk/src/java/org/apache/dns/store/RecordStore.java Fri Oct 28 14:37:33 2005
@@ -16,14 +16,17 @@
  */
 package org.apache.dns.store;
 
+import java.util.Set;
+
 import org.apache.dns.messages.QuestionRecord;
-import org.apache.dns.messages.ResourceRecord;
 
 /**
+ * The store interface used by the DNS protocol to lookup resource records.
+ * 
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
- * @version $Rev$, $Date$
+ * @version $Rev: 329063 $, $Date$
  */
 public interface RecordStore
 {
-    public ResourceRecord getRecord( QuestionRecord question ) throws Exception;
+    public Set getRecords( QuestionRecord question ) throws Exception;
 }

Added: directory/protocol-providers/dns/trunk/src/java/org/apache/dns/store/SearchStrategy.java
URL: http://svn.apache.org/viewcvs/directory/protocol-providers/dns/trunk/src/java/org/apache/dns/store/SearchStrategy.java?rev=329308&view=auto
==============================================================================
--- directory/protocol-providers/dns/trunk/src/java/org/apache/dns/store/SearchStrategy.java (added)
+++ directory/protocol-providers/dns/trunk/src/java/org/apache/dns/store/SearchStrategy.java Fri Oct 28 14:37:33 2005
@@ -0,0 +1,35 @@
+/*
+ *   Copyright 2005 The Apache Software Foundation
+ *
+ *   Licensed under the Apache License, Version 2.0 (the "License");
+ *   you may not use this file except in compliance with the License.
+ *   You may obtain a copy of the License at
+ *
+ *       http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *   Unless required by applicable law or agreed to in writing, software
+ *   distributed under the License is distributed on an "AS IS" BASIS,
+ *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *   See the License for the specific language governing permissions and
+ *   limitations under the License.
+ *
+ */
+
+package org.apache.dns.store;
+
+import java.util.Set;
+
+import org.apache.dns.messages.QuestionRecord;
+
+/**
+ * Interface for search strategies.  The DNS protocol may search a single
+ * base DN for resource records or use a catalog to lookup resource records
+ * in multiple zones.
+ * 
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$
+ */
+interface SearchStrategy
+{
+    Set getRecords( QuestionRecord question ) throws Exception;
+}

Propchange: directory/protocol-providers/dns/trunk/src/java/org/apache/dns/store/SearchStrategy.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: directory/protocol-providers/dns/trunk/src/java/org/apache/dns/store/SingleBaseSearch.java
URL: http://svn.apache.org/viewcvs/directory/protocol-providers/dns/trunk/src/java/org/apache/dns/store/SingleBaseSearch.java?rev=329308&view=auto
==============================================================================
--- directory/protocol-providers/dns/trunk/src/java/org/apache/dns/store/SingleBaseSearch.java (added)
+++ directory/protocol-providers/dns/trunk/src/java/org/apache/dns/store/SingleBaseSearch.java Fri Oct 28 14:37:33 2005
@@ -0,0 +1,77 @@
+/*
+ *   Copyright 2005 The Apache Software Foundation
+ *
+ *   Licensed under the Apache License, Version 2.0 (the "License");
+ *   you may not use this file except in compliance with the License.
+ *   You may obtain a copy of the License at
+ *
+ *       http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *   Unless required by applicable law or agreed to in writing, software
+ *   distributed under the License is distributed on an "AS IS" BASIS,
+ *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *   See the License for the specific language governing permissions and
+ *   limitations under the License.
+ *
+ */
+
+package org.apache.dns.store;
+
+import java.util.Hashtable;
+import java.util.Set;
+
+import javax.naming.Context;
+import javax.naming.NamingException;
+import javax.naming.directory.DirContext;
+import javax.naming.spi.InitialContextFactory;
+
+import org.apache.dns.DnsConfiguration;
+import org.apache.dns.messages.QuestionRecord;
+import org.apache.dns.store.operations.GetRecords;
+import org.apache.ldap.server.configuration.ConfigurationException;
+import org.apache.protocol.common.store.ContextOperation;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * A JNDI-backed search strategy implementation.  This search strategy searches a
+ * single base DN for resource records.
+ * 
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$
+ */
+public class SingleBaseSearch implements SearchStrategy
+{
+    /** the log for this class */
+    private static final Logger log = LoggerFactory.getLogger( SingleBaseSearch.class );
+
+    private DirContext ctx;
+
+    SingleBaseSearch( DnsConfiguration config, InitialContextFactory factory )
+    {
+        Hashtable env = new Hashtable( config.toJndiEnvironment() );
+        env.put( Context.INITIAL_CONTEXT_FACTORY, config.getInitialContextFactory() );
+        env.put( Context.PROVIDER_URL, config.getEntryBaseDn() );
+
+        try
+        {
+            ctx = (DirContext) factory.getInitialContext( env );
+        }
+        catch ( NamingException ne )
+        {
+            log.error( ne.getMessage(), ne );
+            String message = "Failed to get initial context " + (String) env.get( Context.PROVIDER_URL );
+            throw new ConfigurationException( message );
+        }
+    }
+
+    public Set getRecords( QuestionRecord question ) throws Exception
+    {
+        return (Set) execute( new GetRecords( question ) );
+    }
+
+    private Object execute( ContextOperation operation ) throws Exception
+    {
+        return operation.execute( ctx, null );
+    }
+}

Propchange: directory/protocol-providers/dns/trunk/src/java/org/apache/dns/store/SingleBaseSearch.java
------------------------------------------------------------------------------
    svn:eol-style = native

Copied: directory/protocol-providers/dns/trunk/src/java/org/apache/dns/store/operations/GetFlatRecord.java (from r328198, directory/protocol-providers/dns/trunk/src/java/org/apache/dns/store/operations/GetRecord.java)
URL: http://svn.apache.org/viewcvs/directory/protocol-providers/dns/trunk/src/java/org/apache/dns/store/operations/GetFlatRecord.java?p2=directory/protocol-providers/dns/trunk/src/java/org/apache/dns/store/operations/GetFlatRecord.java&p1=directory/protocol-providers/dns/trunk/src/java/org/apache/dns/store/operations/GetRecord.java&r1=328198&r2=329308&rev=329308&view=diff
==============================================================================
--- directory/protocol-providers/dns/trunk/src/java/org/apache/dns/store/operations/GetRecord.java (original)
+++ directory/protocol-providers/dns/trunk/src/java/org/apache/dns/store/operations/GetFlatRecord.java Fri Oct 28 14:37:33 2005
@@ -35,12 +35,12 @@
 import org.apache.protocol.common.store.ContextOperation;
 
 /**
- * Encapsulates the action of looking up a Resource Record from an embedded JNDI provider.
+ * A JNDI context operation for looking up a Resource Record with flat attributes.
  *
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  * @version $Rev$, $Date$
  */
-public class GetRecord implements ContextOperation
+public class GetFlatRecord implements ContextOperation
 {
     /** The name of the question to get. */
     private final QuestionRecord question;
@@ -48,7 +48,7 @@
     /**
      * Creates the action to be used against the embedded JNDI provider.
      */
-    public GetRecord( QuestionRecord question )
+    public GetFlatRecord( QuestionRecord question )
     {
         this.question = question;
     }
@@ -64,7 +64,7 @@
             return null;
         }
 
-        Attributes matchAttrs = new BasicAttributes( false ); // case-sensitive
+        Attributes matchAttrs = new BasicAttributes( true );
 
         matchAttrs.put( new BasicAttribute( DnsAttribute.NAME, question.getDomainName() ) );
         matchAttrs.put( new BasicAttribute( DnsAttribute.TYPE, question.getRecordType().getCode() ) );

Added: directory/protocol-providers/dns/trunk/src/java/org/apache/dns/store/operations/GetRecords.java
URL: http://svn.apache.org/viewcvs/directory/protocol-providers/dns/trunk/src/java/org/apache/dns/store/operations/GetRecords.java?rev=329308&view=auto
==============================================================================
--- directory/protocol-providers/dns/trunk/src/java/org/apache/dns/store/operations/GetRecords.java (added)
+++ directory/protocol-providers/dns/trunk/src/java/org/apache/dns/store/operations/GetRecords.java Fri Oct 28 14:37:33 2005
@@ -0,0 +1,307 @@
+/*
+ *   Copyright 2005 The Apache Software Foundation
+ *
+ *   Licensed under the Apache License, Version 2.0 (the "License");
+ *   you may not use this file except in compliance with the License.
+ *   You may obtain a copy of the License at
+ *
+ *       http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *   Unless required by applicable law or agreed to in writing, software
+ *   distributed under the License is distributed on an "AS IS" BASIS,
+ *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *   See the License for the specific language governing permissions and
+ *   limitations under the License.
+ *
+ */
+
+package org.apache.dns.store.operations;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Properties;
+import java.util.Set;
+
+import javax.naming.CompoundName;
+import javax.naming.Name;
+import javax.naming.NamingEnumeration;
+import javax.naming.NamingException;
+import javax.naming.directory.Attribute;
+import javax.naming.directory.Attributes;
+import javax.naming.directory.DirContext;
+import javax.naming.directory.SearchControls;
+import javax.naming.directory.SearchResult;
+
+import org.apache.dns.messages.QuestionRecord;
+import org.apache.dns.messages.RecordClass;
+import org.apache.dns.messages.RecordType;
+import org.apache.dns.messages.ResourceRecord;
+import org.apache.dns.messages.ResourceRecordModifier;
+import org.apache.dns.store.DnsAttribute;
+import org.apache.protocol.common.store.ContextOperation;
+
+/**
+ * A JNDI context operation for looking up Resource Records from an embedded JNDI provider.
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$
+ */
+public class GetRecords implements ContextOperation
+{
+    /** The name of the question to get. */
+    private final QuestionRecord question;
+
+    /**
+     * Creates the action to be used against the embedded JNDI provider.
+     */
+    public GetRecords( QuestionRecord question )
+    {
+        this.question = question;
+    }
+
+    /**
+     * Mappings of type to objectClass.
+     */
+    private static final Map TYPE_TO_OBJECTCLASS;
+
+    static
+    {
+        Map typeToObjectClass = new HashMap();
+        typeToObjectClass.put( RecordType.SOA, "apacheDnsStartOfAuthorityRecord" );
+        typeToObjectClass.put( RecordType.A, "apacheDnsAddressRecord" );
+        typeToObjectClass.put( RecordType.NS, "apacheDnsNameServerRecord" );
+        typeToObjectClass.put( RecordType.CNAME, "apacheDnsCanonicalNameRecord" );
+        typeToObjectClass.put( RecordType.PTR, "apacheDnsPointerRecord" );
+        typeToObjectClass.put( RecordType.MX, "apacheDnsMailExchangeRecord" );
+        typeToObjectClass.put( RecordType.SRV, "apacheDnsServiceRecord" );
+        typeToObjectClass.put( RecordType.TXT, "apacheDnsTextRecord" );
+
+        TYPE_TO_OBJECTCLASS = Collections.unmodifiableMap( typeToObjectClass );
+    }
+
+    /**
+     * Mappings of type to objectClass.
+     */
+    private static final Map OBJECTCLASS_TO_TYPE;
+
+    static
+    {
+        Map objectClassToType = new HashMap();
+        objectClassToType.put( "apacheDnsStartOfAuthorityRecord", RecordType.SOA );
+        objectClassToType.put( "apacheDnsAddressRecord", RecordType.A );
+        objectClassToType.put( "apacheDnsNameServerRecord", RecordType.NS );
+        objectClassToType.put( "apacheDnsCanonicalNameRecord", RecordType.CNAME );
+        objectClassToType.put( "apacheDnsPointerRecord", RecordType.PTR );
+        objectClassToType.put( "apacheDnsMailExchangeRecord", RecordType.MX );
+        objectClassToType.put( "apacheDnsServiceRecord", RecordType.SRV );
+        objectClassToType.put( "apacheDnsTextRecord", RecordType.TXT );
+        objectClassToType.put( "apacheDnsReferralNameServer", RecordType.NS );
+        objectClassToType.put( "apacheDnsReferralAddress", RecordType.A );
+
+        OBJECTCLASS_TO_TYPE = Collections.unmodifiableMap( objectClassToType );
+    }
+
+    /**
+     * Note that the base is a relative path from the exiting context.
+     * It is not a DN.
+     */
+    public Object execute( DirContext ctx, Name base ) throws Exception
+    {
+        if ( question == null )
+        {
+            return null;
+        }
+
+        String name = question.getDomainName();
+        RecordType type = question.getRecordType();
+
+        SearchControls controls = new SearchControls();
+        controls.setSearchScope( SearchControls.SUBTREE_SCOPE );
+
+        String filter = "(objectClass=" + (String) TYPE_TO_OBJECTCLASS.get( type ) + ")";
+
+        NamingEnumeration list = ctx.search( transformDomainName( name ), filter, controls );
+
+        Set set = new HashSet();
+
+        while ( list.hasMore() )
+        {
+            SearchResult result = (SearchResult) list.next();
+            Name relative = getRelativeName( ctx.getNameInNamespace(), result.getName() );
+
+            set.add( getRecord( result.getAttributes(), relative ) );
+        }
+
+        return set;
+    }
+
+    /**
+     * Marshals a RecordStoreEntry from an Attributes object.
+     *
+     * @param attrs the attributes of the DNS question
+     * @return the entry for the question
+     * @throws NamingException if there are any access problems
+     */
+    private ResourceRecord getRecord( Attributes attrs, Name relative ) throws NamingException
+    {
+        String SOA_MINIMUM = "86400";
+        String SOA_CLASS = "IN";
+
+        ResourceRecordModifier modifier = new ResourceRecordModifier();
+
+        Attribute attr;
+
+        // if no name, transform rdn
+        attr = attrs.get( DnsAttribute.NAME );
+
+        if ( attr != null )
+        {
+            modifier.setDnsName( (String) attr.get() );
+        }
+        else
+        {
+            relative = getDomainComponents( relative );
+
+            String dnsName;
+            dnsName = transformDistinguishedName( relative.toString() );
+            modifier.setDnsName( dnsName );
+        }
+
+        // type is implicit in objectclass
+        attr = attrs.get( DnsAttribute.TYPE );
+
+        if ( attr != null )
+        {
+            modifier.setDnsType( RecordType.getTypeByName( (String) attr.get() ) );
+        }
+        else
+        {
+            modifier.setDnsType( getType( attrs.get( "objectclass" ) ) );
+        }
+
+        // class defaults to SOA CLASS
+        String dnsClass = ( attr = attrs.get( DnsAttribute.CLASS ) ) != null ? (String) attr.get() : SOA_CLASS;
+        modifier.setDnsClass( RecordClass.getTypeByName( dnsClass ) );
+
+        // ttl defaults to SOA MINIMUM
+        String dnsTtl = ( attr = attrs.get( DnsAttribute.TTL ) ) != null ? (String) attr.get() : SOA_MINIMUM;
+        modifier.setDnsTtl( Integer.parseInt( dnsTtl ) );
+
+        NamingEnumeration ids = attrs.getIDs();
+
+        while ( ids.hasMore() )
+        {
+            String id = (String) ids.next();
+            modifier.put( id, (String) attrs.get( id ).get() );
+        }
+
+        return modifier.getEntry();
+    }
+
+    /**
+     * Uses the algorithm in <a href="http://www.faqs.org/rfcs/rfc2247.html">RFC 2247</a>
+     * to transform any Internet domain name into a distinguished name.
+     *
+     * @param domainName the domain name
+     * @return the distinguished name
+     */
+    String transformDomainName( String domainName )
+    {
+        if ( domainName == null || domainName.length() == 0 )
+        {
+            return "";
+        }
+
+        StringBuffer buf = new StringBuffer( domainName.length() + 16 );
+
+        buf.append( "dc=" );
+        buf.append( domainName.replaceAll( "\\.", ",dc=" ) );
+
+        return buf.toString();
+    }
+
+    /**
+     * Uses the algorithm in <a href="http://www.faqs.org/rfcs/rfc2247.html">RFC 2247</a>
+     * to transform a distinguished name into an Internet domain name.
+     *
+     * @param distinguishedName the distinguished name
+     * @return the domain name
+     */
+    String transformDistinguishedName( String distinguishedName )
+    {
+        if ( distinguishedName == null || distinguishedName.length() == 0 )
+        {
+            return "";
+        }
+
+        String domainName = distinguishedName.replaceFirst( "dc=", "" );
+        domainName = domainName.replaceAll( ",dc=", "." );
+
+        return domainName;
+    }
+
+    private RecordType getType( Attribute objectClass ) throws NamingException
+    {
+        NamingEnumeration list = objectClass.getAll();
+
+        while ( list.hasMore() )
+        {
+            String value = (String) list.next();
+
+            if ( !value.equals( "apacheDnsAbstractRecord" ) )
+            {
+                RecordType type = (RecordType) OBJECTCLASS_TO_TYPE.get( value );
+
+                if ( type == null )
+                {
+                    throw new RuntimeException( "Record type to objectClass mapping has not been set." );
+                }
+
+                return type;
+            }
+        }
+
+        throw new NamingException( "ResourceRecord requires STRUCTURAL objectClass" );
+    }
+
+    private Name getRelativeName( String nameInNamespace, String baseDn ) throws NamingException
+    {
+        Properties props = new Properties();
+        props.setProperty( "jndi.syntax.direction", "right_to_left" );
+        props.setProperty( "jndi.syntax.separator", "," );
+        props.setProperty( "jndi.syntax.ignorecase", "true" );
+        props.setProperty( "jndi.syntax.trimblanks", "true" );
+
+        Name searchBaseDn = null;
+
+        Name ctxRoot = new CompoundName( nameInNamespace, props );
+        searchBaseDn = new CompoundName( baseDn, props );
+
+        if ( !searchBaseDn.startsWith( ctxRoot ) )
+        {
+            throw new NamingException( "Invalid search base " + baseDn );
+        }
+
+        for ( int ii = 0; ii < ctxRoot.size(); ii++ )
+        {
+            searchBaseDn.remove( 0 );
+        }
+
+        return searchBaseDn;
+    }
+
+    private Name getDomainComponents( Name name ) throws NamingException
+    {
+        for ( int ii = 0; ii < name.size(); ii++ )
+        {
+            if ( !name.get( ii ).startsWith( "dc=" ) )
+            {
+                name.remove( ii );
+            }
+        }
+
+        return name;
+    }
+}

Propchange: directory/protocol-providers/dns/trunk/src/java/org/apache/dns/store/operations/GetRecords.java
------------------------------------------------------------------------------
    svn:eol-style = native