[dna-commits] DNA SVN: r324 - in trunk/dna-repository/src: main/java/org/jboss/dna/repository/federation and 2 other directories.

dna-commits at lists.jboss.org dna-commits at lists.jboss.org
Tue Jul 1 16:17:40 EDT 2008


Author: rhauch
Date: 2008-07-01 16:17:39 -0400 (Tue, 01 Jul 2008)
New Revision: 324

Added:
   trunk/dna-repository/src/main/java/org/jboss/dna/repository/federation/FederatedRepositoryConfig.java
   trunk/dna-repository/src/test/java/org/jboss/dna/repository/federation/SimpleRepository.java
   trunk/dna-repository/src/test/java/org/jboss/dna/repository/federation/SimpleRepositorySource.java
Modified:
   trunk/dna-repository/src/main/java/org/jboss/dna/repository/RepositoryI18n.java
   trunk/dna-repository/src/main/java/org/jboss/dna/repository/federation/FederatedRegion.java
   trunk/dna-repository/src/main/java/org/jboss/dna/repository/federation/FederatedRepository.java
   trunk/dna-repository/src/main/java/org/jboss/dna/repository/federation/FederatedRepositoryConnection.java
   trunk/dna-repository/src/main/java/org/jboss/dna/repository/federation/FederationService.java
   trunk/dna-repository/src/main/java/org/jboss/dna/repository/federation/RepositorySourceManager.java
   trunk/dna-repository/src/main/resources/org/jboss/dna/repository/RepositoryI18n.properties
   trunk/dna-repository/src/test/java/org/jboss/dna/repository/federation/FederatedRepositoryConnectionTest.java
   trunk/dna-repository/src/test/java/org/jboss/dna/repository/federation/FederatedRepositoryTest.java
   trunk/dna-repository/src/test/java/org/jboss/dna/repository/federation/FederationServiceTest.java
Log:
DNA-115 - Create federation service 
http://jira.jboss.com/jira/browse/DNA-115

Added more tests for FederationService, including tests for those methods that read the configuration repository.  To allow the configuration of a FederatedRepository to be updated in a concurrent environment, the configuration-related information (regions, default cache policy) was pulled into a separate FederatedRepositoryConfig object.  A FederatedRepository's configuration can therefore be replaced wholesale.

Modified: trunk/dna-repository/src/main/java/org/jboss/dna/repository/RepositoryI18n.java
===================================================================
--- trunk/dna-repository/src/main/java/org/jboss/dna/repository/RepositoryI18n.java	2008-07-01 20:14:52 UTC (rev 323)
+++ trunk/dna-repository/src/main/java/org/jboss/dna/repository/RepositoryI18n.java	2008-07-01 20:17:39 UTC (rev 324)
@@ -124,6 +124,8 @@
     public static I18n interruptedWhileConnectingToFederationConfigurationRepository;
     public static I18n interruptedWhileUsingFederationConfigurationRepository;
     public static I18n interruptedWhileClosingConnectionToFederationConfigurationRepository;
+    public static I18n federatedRepositoryCannotBeFound;
+    public static I18n unableToConnectToFederationConfigurationRepository;
     public static I18n unableToFindRepositorySourceByName;
     public static I18n unableToCreateConnectionToFederatedRepository;
     public static I18n unableToAuthenticateConnectionToFederatedRepository;

Modified: trunk/dna-repository/src/main/java/org/jboss/dna/repository/federation/FederatedRegion.java
===================================================================
--- trunk/dna-repository/src/main/java/org/jboss/dna/repository/federation/FederatedRegion.java	2008-07-01 20:14:52 UTC (rev 323)
+++ trunk/dna-repository/src/main/java/org/jboss/dna/repository/federation/FederatedRegion.java	2008-07-01 20:17:39 UTC (rev 324)
@@ -44,19 +44,22 @@
     private final Path pathInRepository;
     private final Path pathInSource;
     private final String sourceName;
+    private final String regionName;
 
     /**
      * Create a binding given a location in the repository below which the content from the named source appears.
      * 
+     * @param regionName the name of the region
      * @param pathInRepository the absolute path in the repository at which the content appears
      * @param pathInSource the path in the source defining the content
      * @param sourceName the name of the source
      * @throws IllegalArgumentException if any of the parameters is null, or if the source name is empty/blank, or if the
      *         <code>pathInRepository</code> is not {@link Path#isAbsolute() absolute}.
      */
-    public FederatedRegion( Path pathInRepository,
-                             Path pathInSource,
-                             String sourceName ) {
+    public FederatedRegion( String regionName,
+                            Path pathInRepository,
+                            Path pathInSource,
+                            String sourceName ) {
         ArgCheck.isNotNull(pathInRepository, "pathInRepository");
         ArgCheck.isNotNull(pathInSource, "pathInSource");
         ArgCheck.isNotEmpty(sourceName, "sourceName");
@@ -64,12 +67,22 @@
             String msg = RepositoryI18n.repositoryPathInFederationBindingIsNotAbsolute.text(pathInRepository.getString());
             throw new IllegalArgumentException(msg);
         }
+        this.regionName = regionName;
         this.pathInRepository = pathInRepository;
         this.pathInSource = pathInSource;
         this.sourceName = sourceName;
     }
 
     /**
+     * Get the name of this region.
+     * 
+     * @return regionName
+     */
+    public String getRegionName() {
+        return regionName;
+    }
+
+    /**
      * Get the location in the repository at which the source's content appears.
      * 
      * @return the repository-based path for the top of the source's content
@@ -154,6 +167,7 @@
         if (obj == this) return true;
         if (obj instanceof FederatedRegion) {
             FederatedRegion that = (FederatedRegion)obj;
+            if (!this.getRegionName().equals(that.getRegionName())) return false;
             if (!this.getPathInRepository().equals(that.getPathInRepository())) return false;
             if (!this.getPathInSource().equals(that.getPathInSource())) return false;
             if (!this.getSourceName().equals(that.getSourceName())) return false;
@@ -169,8 +183,10 @@
      */
     public int compareTo( FederatedRegion that ) {
         if (this == that) return 0;
-        int diff = this.getPathInRepository().compareTo(that.getPathInRepository());
+        int diff = this.getRegionName().compareTo(that.getRegionName());
         if (diff != 0) return diff;
+        diff = this.getPathInRepository().compareTo(that.getPathInRepository());
+        if (diff != 0) return diff;
         diff = this.getPathInSource().compareTo(that.getPathInSource());
         if (diff != 0) return diff;
         return this.getSourceName().compareTo(that.getSourceName());
@@ -183,6 +199,15 @@
      */
     @Override
     public String toString() {
-        return this.getPathInRepository().toString() + " -> \"" + this.getSourceName() + "\":" + this.getPathInSource();
+        StringBuilder sb = new StringBuilder();
+        if (this.getRegionName() != null) {
+            sb.append(this.getRegionName());
+        }
+        sb.append(this.getPathInRepository());
+        sb.append(" -> \"");
+        sb.append(this.getSourceName());
+        sb.append("\":");
+        sb.append(this.getPathInSource());
+        return sb.toString();
     }
 }

Modified: trunk/dna-repository/src/main/java/org/jboss/dna/repository/federation/FederatedRepository.java
===================================================================
--- trunk/dna-repository/src/main/java/org/jboss/dna/repository/federation/FederatedRepository.java	2008-07-01 20:14:52 UTC (rev 323)
+++ trunk/dna-repository/src/main/java/org/jboss/dna/repository/federation/FederatedRepository.java	2008-07-01 20:17:39 UTC (rev 324)
@@ -21,7 +21,6 @@
  */
 package org.jboss.dna.repository.federation;
 
-import java.util.Collections;
 import java.util.List;
 import java.util.concurrent.CopyOnWriteArrayList;
 import java.util.concurrent.TimeUnit;
@@ -30,16 +29,15 @@
 import org.jboss.dna.repository.RepositoryI18n;
 import org.jboss.dna.repository.services.AbstractServiceAdministrator;
 import org.jboss.dna.repository.services.ServiceAdministrator;
-import org.jboss.dna.spi.cache.CachePolicy;
 import org.jboss.dna.spi.graph.connection.ExecutionEnvironment;
 import org.jboss.dna.spi.graph.connection.RepositoryConnection;
 import org.jboss.dna.spi.graph.connection.RepositorySource;
 import org.jboss.dna.spi.graph.connection.RepositorySourceListener;
 
 /**
- * The component in the {@link FederationService} that represents a single federated repository. The federated repository manages
- * a set of {@link RepositorySource federated sources}, and provides the logic of interacting with those sources and presenting a
- * single unified graph.
+ * The component in the {@link FederationService} that represents a single federated repository. The federated repository uses a
+ * set of {@link RepositorySource federated sources} as designated by name through the {@link #getConfiguration() configuration},
+ * and provides the logic of interacting with those sources and presenting a single unified graph.
  * 
  * @author Randall Hauch
  */
@@ -97,9 +95,8 @@
     private final String name;
     private final ExecutionEnvironment env;
     private final RepositoryConnectionFactories connectionFactories;
-    private final CopyOnWriteArrayList<FederatedRegion> regions = new CopyOnWriteArrayList<FederatedRegion>();
+    private FederatedRepositoryConfig config;
     private final CopyOnWriteArrayList<RepositorySourceListener> listeners = new CopyOnWriteArrayList<RepositorySourceListener>();
-    private CachePolicy defaultCachePolicy;
 
     /**
      * Create a federated repository instance, as managed by the supplied {@link FederationService}.
@@ -107,17 +104,21 @@
      * @param repositoryName the name of the repository
      * @param env the execution environment
      * @param connectionFactories the set of connection factories that should be used
+     * @param config the configuration for this repository
      * @throws IllegalArgumentException if any of the parameters are null, or if the name is blank
      */
     public FederatedRepository( String repositoryName,
                                 ExecutionEnvironment env,
-                                RepositoryConnectionFactories connectionFactories ) {
+                                RepositoryConnectionFactories connectionFactories,
+                                FederatedRepositoryConfig config ) {
         ArgCheck.isNotNull(connectionFactories, "connectionFactories");
         ArgCheck.isNotNull(env, "env");
+        ArgCheck.isNotNull(config, "config");
         ArgCheck.isNotEmpty(repositoryName, "repositoryName");
         this.name = repositoryName;
         this.env = env;
         this.connectionFactories = connectionFactories;
+        this.config = config;
     }
 
     /**
@@ -206,32 +207,6 @@
     }
 
     /**
-     * Return the unmodifiable list of bindings.
-     * 
-     * @return the bindings
-     */
-    public List<FederatedRegion> getRegions() {
-        return Collections.unmodifiableList(regions);
-    }
-
-    /**
-     * Add the supplied federation region to this repository, if it is not already in the repository. . This method does not
-     * attempt to check whether this region would result in a duplicate region.
-     * 
-     * @param region the region to be added
-     * @return true if the region was added, or false if there was already a duplicate region
-     * @throws IllegalArgumentException if the binding reference is null
-     */
-    protected boolean addRegionIfAbsent( FederatedRegion region ) {
-        ArgCheck.isNotNull(region, "region");
-        return this.regions.addIfAbsent(region);
-    }
-
-    protected boolean removeBinding( FederatedRegion region ) {
-        return this.regions.remove(region);
-    }
-
-    /**
      * Add a listener that is to receive notifications to changes to content within this repository. This method does nothing if
      * the supplied listener is null.
      * 
@@ -280,25 +255,28 @@
     }
 
     /**
-     * Get the default cache policy for the repository with the supplied name
+     * Get the configuration of this repository. This configuration is immutable and may be
+     * {@link #setConfiguration(FederatedRepositoryConfig) changed} as needed. Therefore, when using a configuration and needing a
+     * consistent configuration, maintain a reference to the configuration during that time (as the actual configuration may be
+     * replaced at any time).
      * 
-     * @return the default cache policy
+     * @return the repository's configuration at the time this method is called.
      */
-    public CachePolicy getDefaultCachePolicy() {
-        return defaultCachePolicy;
+    public FederatedRepositoryConfig getConfiguration() {
+        return config;
     }
 
     /**
-     * Set the default cache policy for the federated repository.
-     * <p>
-     * This method can safely be called while the federation repository is in use.
-     * </p>
+     * Set the configuration for this repository. The configuration is immutable and therefore may be replaced using this method.
+     * All interaction with the configuration is done in a thread-safe and concurrent manner, and as such only valid
+     * configurations should be used.
      * 
-     * @param defaultCachePolicy Sets defaultCachePolicy to the specified value.
+     * @param config the new configuration
+     * @throws IllegalArgumentException if the configuration is null
      */
-    public void setDefaultCachePolicy( CachePolicy defaultCachePolicy ) {
-        ArgCheck.isNotNull(defaultCachePolicy, "defaultCachePolicy");
-        this.defaultCachePolicy = defaultCachePolicy;
+    public void setConfiguration( FederatedRepositoryConfig config ) {
+        ArgCheck.isNotNull(config, "config");
+        this.config = config;
     }
 
 }

Added: trunk/dna-repository/src/main/java/org/jboss/dna/repository/federation/FederatedRepositoryConfig.java
===================================================================
--- trunk/dna-repository/src/main/java/org/jboss/dna/repository/federation/FederatedRepositoryConfig.java	                        (rev 0)
+++ trunk/dna-repository/src/main/java/org/jboss/dna/repository/federation/FederatedRepositoryConfig.java	2008-07-01 20:17:39 UTC (rev 324)
@@ -0,0 +1,108 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors. 
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.dna.repository.federation;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import net.jcip.annotations.Immutable;
+import org.jboss.dna.common.collection.Problems;
+import org.jboss.dna.common.collection.ThreadSafeProblems;
+import org.jboss.dna.common.util.ArgCheck;
+import org.jboss.dna.spi.cache.CachePolicy;
+import org.jboss.dna.spi.graph.connection.RepositorySource;
+
+/**
+ * The configuration of a {@link FederatedRepository}. The configuration defines, among other things, the set of
+ * {@link #getRegions() regions} in the federated repository that each specify how and where content from a
+ * {@link RepositorySource source} is federated into the unified repository.
+ * 
+ * @author Randall Hauch
+ */
+ at Immutable
+public class FederatedRepositoryConfig {
+
+    private final List<FederatedRegion> regions;
+    private final Problems problems;
+    private final String name;
+    private final CachePolicy defaultCachePolicy;
+
+    /**
+     * Create a federated repository instance, as managed by the supplied {@link FederationService}.
+     * 
+     * @param repositoryName the name of the repository
+     * @param regions the federated regions; may not be null
+     * @param defaultCachePolicy the default cache policy for this repository; may be null
+     * @throws IllegalArgumentException if the name is null or is blank
+     */
+    public FederatedRepositoryConfig( String repositoryName,
+                                      Iterable<FederatedRegion> regions,
+                                      CachePolicy defaultCachePolicy ) {
+        ArgCheck.isNotEmpty(repositoryName, "repositoryName");
+        this.name = repositoryName;
+        this.problems = new ThreadSafeProblems();
+        this.defaultCachePolicy = defaultCachePolicy;
+        List<FederatedRegion> regionList = new ArrayList<FederatedRegion>();
+        for (FederatedRegion region : regions) {
+            if (region != null && !regionList.contains(region)) regionList.add(region);
+        }
+        this.regions = Collections.unmodifiableList(regionList);
+        ArgCheck.isNotEmpty(this.regions, "regions");
+    }
+
+    /**
+     * Get the name of this repository
+     * 
+     * @return name
+     */
+    public String getName() {
+        return this.name;
+    }
+
+    /**
+     * Return the problem associated with this configuration. These problems may change at any time, although the returned
+     * {@link Problems} object is thread-safe.
+     * 
+     * @return the thread-safe problems for this configuration
+     */
+    public Problems getProblems() {
+        return problems;
+    }
+
+    /**
+     * Return the unmodifiable list of bindings.
+     * 
+     * @return the bindings
+     */
+    public List<FederatedRegion> getRegions() {
+        return regions;
+    }
+
+    /**
+     * Get the default cache policy for the repository with the supplied name
+     * 
+     * @return the default cache policy
+     */
+    public CachePolicy getDefaultCachePolicy() {
+        return defaultCachePolicy;
+    }
+}


Property changes on: trunk/dna-repository/src/main/java/org/jboss/dna/repository/federation/FederatedRepositoryConfig.java
___________________________________________________________________
Name: svn:mime-type
   + text/plain

Modified: trunk/dna-repository/src/main/java/org/jboss/dna/repository/federation/FederatedRepositoryConnection.java
===================================================================
--- trunk/dna-repository/src/main/java/org/jboss/dna/repository/federation/FederatedRepositoryConnection.java	2008-07-01 20:14:52 UTC (rev 323)
+++ trunk/dna-repository/src/main/java/org/jboss/dna/repository/federation/FederatedRepositoryConnection.java	2008-07-01 20:17:39 UTC (rev 324)
@@ -83,7 +83,7 @@
      * {@inheritDoc}
      */
     public CachePolicy getDefaultCachePolicy() {
-        return this.repository.getDefaultCachePolicy();
+        return this.repository.getConfiguration().getDefaultCachePolicy();
     }
 
     /**

Modified: trunk/dna-repository/src/main/java/org/jboss/dna/repository/federation/FederationService.java
===================================================================
--- trunk/dna-repository/src/main/java/org/jboss/dna/repository/federation/FederationService.java	2008-07-01 20:14:52 UTC (rev 323)
+++ trunk/dna-repository/src/main/java/org/jboss/dna/repository/federation/FederationService.java	2008-07-01 20:17:39 UTC (rev 324)
@@ -23,6 +23,7 @@
 
 import java.lang.reflect.InvocationTargetException;
 import java.util.Collections;
+import java.util.LinkedList;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
@@ -41,6 +42,9 @@
 import org.jboss.dna.repository.services.AbstractServiceAdministrator;
 import org.jboss.dna.repository.services.AdministeredService;
 import org.jboss.dna.repository.services.ServiceAdministrator;
+import org.jboss.dna.spi.cache.BasicCachePolicy;
+import org.jboss.dna.spi.cache.CachePolicy;
+import org.jboss.dna.spi.graph.InvalidPathException;
 import org.jboss.dna.spi.graph.Name;
 import org.jboss.dna.spi.graph.NameFactory;
 import org.jboss.dna.spi.graph.Path;
@@ -65,6 +69,11 @@
 
     protected static final String CLASSNAME_PROPERTY_NAME = "dna:classname";
     protected static final String CLASSPATH_PROPERTY_NAME = "dna:classpath";
+    protected static final String REGION_PATH_IN_REPOSITORY_PROPERTY_NAME = "dna:pathInRepository";
+    protected static final String REGION_PATH_IN_SOURCE_PROPERTY_NAME = "dna:pathInSource";
+    protected static final String REGION_SOURCE_NAME = "dna:sourceName";
+    protected static final String CACHE_POLICY_TIME_TO_EXPIRE = "dna:timeToExpire";
+    protected static final String CACHE_POLICY_TIME_TO_CACHE = "dna:timeToCache";
 
     /**
      * The administrative component for this service.
@@ -74,7 +83,7 @@
     protected class Administrator extends AbstractServiceAdministrator {
 
         protected Administrator() {
-            super(RepositoryI18n.federationServiceName, State.STARTED);
+            super(RepositoryI18n.federationServiceName, State.PAUSED);
         }
 
         /**
@@ -204,6 +213,9 @@
             } catch (InterruptedException err) {
                 I18n msg = RepositoryI18n.interruptedWhileConnectingToFederationConfigurationRepository;
                 throw new FederationException(msg.text(configurationSourceName));
+            } catch (Throwable err) {
+                I18n msg = RepositoryI18n.unableToConnectToFederationConfigurationRepository;
+                throw new FederationException(msg.text(configurationSourceName));
             }
 
             // ------------------------------------------------------------------------------------
@@ -211,31 +223,41 @@
             // ------------------------------------------------------------------------------------
             ValueFactories valueFactories = env.getValueFactories();
             PathFactory pathFactory = valueFactories.getPathFactory();
+            NameFactory nameFactory = valueFactories.getNameFactory();
 
+            // The root of the configuration repository should be converted using the configuration region
+            // to the path in the source (since we're talking directly to the source) ...
+            Path configurationRoot = pathFactory.create("/");
+            configurationRoot = configurationRegion.convertPathInRepositoryToPathInSource(configurationRoot, pathFactory);
+
             // Read the configuration and the repository sources, located as child nodes/branches under "/dna:sources",
             // and then instantiate and register each in the "sources" manager
             try {
-                Path sourcesNode = pathFactory.create("/dna:sources");
+                Path sourcesNode = pathFactory.create(configurationRoot, nameFactory.create("dna:sources"));
                 BasicGetChildrenCommand getSources = new BasicGetChildrenCommand(sourcesNode);
                 configurationConnection.execute(env, getSources);
+                if (getSources.hasNoError()) {
 
-                // Build the commands to get each of the children ...
-                List<Path.Segment> children = getSources.getChildren();
-                if (children.isEmpty()) {
-                    BasicCompositeCommand commands = new BasicCompositeCommand();
-                    for (Path.Segment child : getSources.getChildren()) {
-                        final Path pathToSource = pathFactory.create(sourcesNode, child);
-                        commands.add(new BasicGetNodeCommand(pathToSource));
-                    }
-                    configurationConnection.execute(env, commands);
+                    // Build the commands to get each of the children ...
+                    List<Path.Segment> children = getSources.getChildren();
+                    if (!children.isEmpty()) {
+                        BasicCompositeCommand commands = new BasicCompositeCommand();
+                        for (Path.Segment child : getSources.getChildren()) {
+                            final Path pathToSource = pathFactory.create(sourcesNode, child);
+                            commands.add(new BasicGetNodeCommand(pathToSource));
+                        }
+                        configurationConnection.execute(env, commands);
 
-                    // Iterate over each source node obtained ...
-                    for (GraphCommand command : commands) {
-                        BasicGetNodeCommand getSourceCommand = (BasicGetNodeCommand)command;
-                        RepositorySource source = createRepositorySource(getSourceCommand.getPath(),
-                                                                         getSourceCommand.getProperties(),
-                                                                         problems);
-                        if (source != null) sources.addSource(source);
+                        // Iterate over each source node obtained ...
+                        for (GraphCommand command : commands) {
+                            BasicGetNodeCommand getSourceCommand = (BasicGetNodeCommand)command;
+                            if (getSourceCommand.hasNoError()) {
+                                RepositorySource source = createRepositorySource(getSourceCommand.getPath(),
+                                                                                 getSourceCommand.getProperties(),
+                                                                                 problems);
+                                if (source != null) sources.addSource(source, false);
+                            }
+                        }
                     }
                 }
             } catch (InterruptedException err) {
@@ -268,14 +290,12 @@
         if (classnameProperty == null) {
             problems.addError(RepositoryI18n.requiredPropertyIsMissingFromNode, CLASSNAME_PROPERTY_NAME, path);
         }
-        if (classpathProperty == null) {
-            problems.addError(RepositoryI18n.requiredPropertyIsMissingFromNode, CLASSPATH_PROPERTY_NAME, path);
-        }
+        // If the classpath property is null or empty, the default classpath will be used
         if (problems.hasErrors()) return null;
 
         // Create the instance ...
         String classname = stringFactory.create(classnameProperty.getValues().next());
-        String[] classpath = stringFactory.create(classpathProperty.getValuesAsArray());
+        String[] classpath = classpathProperty == null ? new String[] {} : stringFactory.create(classpathProperty.getValuesAsArray());
         ClassLoader classLoader = this.classLoaderFactory.getClassLoader(classpath);
         RepositorySource source = null;
         try {
@@ -289,8 +309,23 @@
             problems.addError(err, RepositoryI18n.unableToInstantiateClassUsingClasspath, classname, classpath);
         }
 
+        // Try to set the name property to the local name of the node...
+        Reflection reflection = new Reflection(source.getClass());
+        try {
+            reflection.invokeSetterMethodOnTarget("name", source, path.getLastSegment().getName().getLocalName());
+        } catch (SecurityException err) {
+            // Do nothing ... assume not a JavaBean property
+        } catch (NoSuchMethodException err) {
+            // Do nothing ... assume not a JavaBean property
+        } catch (IllegalArgumentException err) {
+            // Do nothing ... assume not a JavaBean property
+        } catch (IllegalAccessException err) {
+            // Do nothing ... assume not a JavaBean property
+        } catch (InvocationTargetException err) {
+            // Do nothing ... assume not a JavaBean property
+        }
+
         // Now set all the properties that we can, ignoring any property that doesn't fit pattern ...
-        Reflection reflection = new Reflection(source.getClass());
         for (Map.Entry<Name, Property> entry : properties.entrySet()) {
             Name propertyName = entry.getKey();
             Property property = entry.getValue();
@@ -332,10 +367,12 @@
         FederatedRepository repository = this.repositories.get(name);
         if (repository == null) {
             // Look up the node representing the repository in the configuration ...
+            FederatedRepositoryConfig config = loadConfiguration(name);
+            assert config != null;
 
-            // // New up a repository and configure it ...
-            // Repository
-            repository = new FederatedRepository(name, env, sources);
+            // New up a repository and configure it ...
+            repository = new FederatedRepository(name, env, sources, config);
+
             // Now register it, being careful to not overwrite any added since "get" call above ..
             FederatedRepository existingRepository = this.repositories.putIfAbsent(name, repository);
             if (existingRepository != null) repository = existingRepository;
@@ -345,6 +382,117 @@
         return repository;
     }
 
+    protected FederatedRepositoryConfig loadConfiguration( String repositoryName ) {
+        Problems problems = new SimpleProblems();
+        ValueFactories valueFactories = env.getValueFactories();
+        PathFactory pathFactory = valueFactories.getPathFactory();
+        NameFactory nameFactory = valueFactories.getNameFactory();
+        ValueFactory<Long> longFactory = valueFactories.getLongFactory();
+
+        // The root of the configuration repository should be converted using the configuration region
+        // to the path in the source (since we're talking directly to the source) ...
+        Path configurationRoot = pathFactory.create("/dna:repositories");
+        configurationRoot = configurationRegion.convertPathInRepositoryToPathInSource(configurationRoot, pathFactory);
+        Path repositoryNode = pathFactory.create(configurationRoot, nameFactory.create(repositoryName));
+
+        try {
+            // Get the repository node ...
+            BasicGetNodeCommand getRepository = new BasicGetNodeCommand(repositoryNode);
+
+            // Get the regions for the repository ...
+            Path regionsNode = pathFactory.create(repositoryNode, nameFactory.create("dna:regions"));
+            BasicGetChildrenCommand getRegions = new BasicGetChildrenCommand(regionsNode);
+
+            configurationConnection.execute(env, getRepository, getRegions);
+            if (getRepository.hasError()) {
+                throw new FederationException(RepositoryI18n.federatedRepositoryCannotBeFound.text(repositoryName));
+            }
+
+            // Build the commands to get each of the region branches ...
+            List<FederatedRegion> regions = new LinkedList<FederatedRegion>();
+            if (getRegions.hasNoError() && !getRegions.getChildren().isEmpty()) {
+                BasicCompositeCommand commands = new BasicCompositeCommand();
+                for (Path.Segment child : getRegions.getChildren()) {
+                    final Path pathToSource = pathFactory.create(regionsNode, child);
+                    commands.add(new BasicGetNodeCommand(pathToSource));
+                }
+                configurationConnection.execute(env, commands);
+
+                // Iterate over each region node obtained ...
+                for (GraphCommand command : commands) {
+                    BasicGetNodeCommand getRegionCommand = (BasicGetNodeCommand)command;
+                    if (getRegionCommand.hasNoError()) {
+                        FederatedRegion region = createRegion(getRegionCommand.getPath(),
+                                                              getRegionCommand.getProperties(),
+                                                              problems);
+                        if (region != null) regions.add(region);
+                    }
+                }
+            }
+
+            // Look for the default cache policy ...
+            BasicCachePolicy cachePolicy = new BasicCachePolicy();
+            Property timeToExpireProperty = getRepository.getProperties().get(nameFactory.create(CACHE_POLICY_TIME_TO_EXPIRE));
+            Property timeToCacheProperty = getRepository.getProperties().get(nameFactory.create(CACHE_POLICY_TIME_TO_CACHE));
+            if (timeToCacheProperty != null && !timeToCacheProperty.isEmpty()) {
+                cachePolicy.setTimeToCache(longFactory.create(timeToCacheProperty.getValues().next()));
+            }
+            if (timeToExpireProperty != null && !timeToExpireProperty.isEmpty()) {
+                cachePolicy.setTimeToExpire(longFactory.create(timeToExpireProperty.getValues().next()));
+            }
+            CachePolicy defaultCachePolicy = cachePolicy.isEmpty() ? null : cachePolicy.getUnmodifiable();
+            return new FederatedRepositoryConfig(repositoryName, regions, defaultCachePolicy);
+        } catch (InvalidPathException err) {
+            I18n msg = RepositoryI18n.federatedRepositoryCannotBeFound;
+            throw new FederationException(msg.text(repositoryName));
+        } catch (InterruptedException err) {
+            I18n msg = RepositoryI18n.interruptedWhileUsingFederationConfigurationRepository;
+            throw new FederationException(msg.text(repositoryName));
+        }
+
+    }
+
+    /**
+     * Instantiate the {@link FederatedRegion} described by the supplied properties.
+     * 
+     * @param path the path to the node where these properties were found; never null
+     * @param properties the properties; never null
+     * @param problems the problems container in which any problems should be reported; never null
+     * @return the region instance, or null if it could not be created
+     */
+    @SuppressWarnings( "null" )
+    protected FederatedRegion createRegion( Path path,
+                                            Map<Name, Property> properties,
+                                            Problems problems ) {
+        ValueFactories valueFactories = env.getValueFactories();
+        PathFactory pathFactory = valueFactories.getPathFactory();
+        NameFactory nameFactory = valueFactories.getNameFactory();
+        ValueFactory<String> stringFactory = valueFactories.getStringFactory();
+
+        String regionName = path.getLastSegment().getName().getLocalName();
+        Path pathInRepository = pathFactory.createRootPath();
+        Path pathInSource = pathInRepository;
+
+        // Get the classname and classpath ...
+        Property pathInRepositoryProperty = properties.get(nameFactory.create(REGION_PATH_IN_REPOSITORY_PROPERTY_NAME));
+        Property pathInSourceProperty = properties.get(nameFactory.create(REGION_PATH_IN_SOURCE_PROPERTY_NAME));
+        Property sourceNameProperty = properties.get(nameFactory.create(REGION_SOURCE_NAME));
+        if (pathInRepositoryProperty != null && !pathInRepositoryProperty.isEmpty()) {
+            pathInRepository = pathFactory.create(pathInRepositoryProperty.iterator().next());
+        }
+        if (pathInSourceProperty != null && !pathInSourceProperty.isEmpty()) {
+            pathInSource = pathFactory.create(pathInSourceProperty.iterator().next());
+        }
+        if (sourceNameProperty == null || sourceNameProperty.isEmpty()) {
+            problems.addError(RepositoryI18n.requiredPropertyIsMissingFromNode, CLASSNAME_PROPERTY_NAME, path);
+        }
+        if (problems.hasErrors()) return null;
+
+        String sourceName = stringFactory.create(sourceNameProperty.iterator().next());
+        FederatedRegion region = new FederatedRegion(regionName, pathInRepository, pathInSource, sourceName);
+        return region;
+    }
+
     protected synchronized void shutdownService() {
         if (this.configurationConnection != null) {
             try {

Modified: trunk/dna-repository/src/main/java/org/jboss/dna/repository/federation/RepositorySourceManager.java
===================================================================
--- trunk/dna-repository/src/main/java/org/jboss/dna/repository/federation/RepositorySourceManager.java	2008-07-01 20:14:52 UTC (rev 323)
+++ trunk/dna-repository/src/main/java/org/jboss/dna/repository/federation/RepositorySourceManager.java	2008-07-01 20:17:39 UTC (rev 324)
@@ -247,17 +247,23 @@
      * </p>
      * 
      * @param source the source to add
+     * @param force true if the valid source should be added even if there is an existing source with the supplied name
      * @return true if the source is added, or false if the reference is null or if there is already an existing source with the
      *         supplied name.
      */
-    public boolean addSource( RepositorySource source ) {
+    public boolean addSource( RepositorySource source,
+                              boolean force ) {
         if (source == null) return false;
         try {
             this.sourcesWriteLock.lock();
             for (RepositorySource existingSource : this.sources.values()) {
                 if (existingSource.getName().equals(source.getName())) return false;
             }
-            this.sources.put(source.getName(), source);
+            if (force) {
+                this.sources.put(source.getName(), source);
+            } else {
+                this.sources.putIfAbsent(source.getName(), source);
+            }
         } finally {
             this.sourcesWriteLock.unlock();
         }

Modified: trunk/dna-repository/src/main/resources/org/jboss/dna/repository/RepositoryI18n.properties
===================================================================
--- trunk/dna-repository/src/main/resources/org/jboss/dna/repository/RepositoryI18n.properties	2008-07-01 20:14:52 UTC (rev 323)
+++ trunk/dna-repository/src/main/resources/org/jboss/dna/repository/RepositoryI18n.properties	2008-07-01 20:17:39 UTC (rev 324)
@@ -104,8 +104,10 @@
 interruptedWhileConnectingToFederationConfigurationRepository = Interrupted while connecting to federation configuration repository "{0}"
 interruptedWhileUsingFederationConfigurationRepository = Interrupted while using federation configuration repository "{0}"
 interruptedWhileClosingConnectionToFederationConfigurationRepository = Interrupted while closing connection to federation configuration repository "{0}"
+federatedRepositoryCannotBeFound = The federated repository "{0}" cannot be found
+unableToConnectToFederationConfigurationRepository = Unable to connect to federation configuration repository "{0}"
 unableToFindRepositorySourceByName = Unable to find the repository source "{0}"
-unableToCreateConnectionToFederatedRepository = Unable to create a connection to the repository "{0}". Check the Federation Service configuration.
+unableToCreateConnectionToFederatedRepository = Unable to connect to the repository "{0}". Check the Federation Service configuration.
 unableToAuthenticateConnectionToFederatedRepository = Unable to authenticate "{1}" for repository "{0}"
 repositoryHasBeenShutDown = The "{0}" repository has been shut down and may no longer be used.
 repositoryPathInFederationBindingIsNotAbsolute = The repository path in a federation binding must be absolute, but was "{0}"

Modified: trunk/dna-repository/src/test/java/org/jboss/dna/repository/federation/FederatedRepositoryConnectionTest.java
===================================================================
--- trunk/dna-repository/src/test/java/org/jboss/dna/repository/federation/FederatedRepositoryConnectionTest.java	2008-07-01 20:14:52 UTC (rev 323)
+++ trunk/dna-repository/src/test/java/org/jboss/dna/repository/federation/FederatedRepositoryConnectionTest.java	2008-07-01 20:17:39 UTC (rev 324)
@@ -23,7 +23,6 @@
 
 import static org.hamcrest.core.Is.is;
 import static org.hamcrest.core.IsNull.nullValue;
-import static org.hamcrest.core.IsSame.sameInstance;
 import static org.junit.Assert.assertThat;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.stub;
@@ -31,7 +30,6 @@
 import static org.mockito.Mockito.verify;
 import java.util.concurrent.TimeUnit;
 import org.jboss.dna.repository.services.ServiceAdministrator;
-import org.jboss.dna.spi.cache.CachePolicy;
 import org.jboss.dna.spi.graph.commands.GraphCommand;
 import org.jboss.dna.spi.graph.connection.ExecutionEnvironment;
 import org.jboss.dna.spi.graph.connection.RepositorySourceException;
@@ -53,8 +51,6 @@
     @Mock
     private FederatedRepository repository;
     @Mock
-    private CachePolicy defaultCachePolicy;
-    @Mock
     private ServiceAdministrator repositoryAdmin;
 
     @Before
@@ -62,7 +58,6 @@
         MockitoAnnotations.initMocks(this);
         sourceName = "Source X";
         stub(source.getName()).toReturn(sourceName);
-        stub(repository.getDefaultCachePolicy()).toReturn(defaultCachePolicy);
         stub(repository.getAdministrator()).toReturn(repositoryAdmin);
         connection = new FederatedRepositoryConnection(repository, source);
     }
@@ -82,12 +77,6 @@
     }
 
     @Test
-    public void shouldGetDefaultCachePolicyFromRepository() {
-        assertThat(connection.getDefaultCachePolicy(), is(sameInstance(defaultCachePolicy)));
-        verify(repository, times(1)).getDefaultCachePolicy();
-    }
-
-    @Test
     public void shouldHaveNoXaResource() {
         assertThat(connection.getXAResource(), is(nullValue()));
     }

Modified: trunk/dna-repository/src/test/java/org/jboss/dna/repository/federation/FederatedRepositoryTest.java
===================================================================
--- trunk/dna-repository/src/test/java/org/jboss/dna/repository/federation/FederatedRepositoryTest.java	2008-07-01 20:14:52 UTC (rev 323)
+++ trunk/dna-repository/src/test/java/org/jboss/dna/repository/federation/FederatedRepositoryTest.java	2008-07-01 20:17:39 UTC (rev 324)
@@ -26,7 +26,6 @@
 import static org.hamcrest.core.IsSame.sameInstance;
 import static org.junit.Assert.assertThat;
 import static org.junit.matchers.JUnitMatchers.hasItems;
-import static org.mockito.Mockito.mock;
 import org.jboss.dna.spi.graph.connection.BasicExecutionEnvironment;
 import org.jboss.dna.spi.graph.connection.ExecutionEnvironment;
 import org.jboss.dna.spi.graph.connection.RepositorySourceListener;
@@ -44,6 +43,8 @@
     private FederatedRepository repository;
     private String name;
     @Mock
+    private FederatedRepositoryConfig config;
+    @Mock
     private RepositorySourceListener listener1;
     @Mock
     private RepositorySourceListener listener2;
@@ -57,7 +58,7 @@
         MockitoAnnotations.initMocks(this);
         env = new BasicExecutionEnvironment();
         name = "Test repository";
-        repository = new FederatedRepository(name, env, connectionFactories);
+        repository = new FederatedRepository(name, env, connectionFactories, config);
     }
 
     @Test
@@ -137,32 +138,9 @@
     }
 
     @Test
-    public void shouldHaveNoFederationRegionsAfterInitialization() {
-        assertThat(repository.getRegions(), is(notNullValue()));
-        assertThat(repository.getRegions().isEmpty(), is(true));
+    public void shouldHaveConfigurationAfterInitialization() {
+        assertThat(repository.getConfiguration(), is(notNullValue()));
+        assertThat(repository.getConfiguration(), is(sameInstance(config)));
     }
 
-    @Test
-    public void shouldAddFederationRegionThatIsNotAlreadyRegistered() {
-        FederatedRegion region1 = mock(FederatedRegion.class);
-        FederatedRegion region2 = mock(FederatedRegion.class);
-
-        assertThat(repository.getRegions().isEmpty(), is(true));
-        assertThat(repository.addRegionIfAbsent(region1), is(true));
-        assertThat(repository.getRegions(), hasItems(region1));
-        assertThat(repository.addRegionIfAbsent(region2), is(true));
-        assertThat(repository.getRegions(), hasItems(region1, region2));
-    }
-
-    @Test
-    public void shouldNotAddSourceThatIsAlreadyRegistered() {
-        FederatedRegion region1 = mock(FederatedRegion.class);
-
-        assertThat(repository.getRegions().isEmpty(), is(true));
-        assertThat(repository.addRegionIfAbsent(region1), is(true));
-        assertThat(repository.getRegions(), hasItems(region1));
-        assertThat(repository.addRegionIfAbsent(region1), is(false));
-        assertThat(repository.getRegions(), hasItems(region1));
-    }
-
 }

Modified: trunk/dna-repository/src/test/java/org/jboss/dna/repository/federation/FederationServiceTest.java
===================================================================
--- trunk/dna-repository/src/test/java/org/jboss/dna/repository/federation/FederationServiceTest.java	2008-07-01 20:14:52 UTC (rev 323)
+++ trunk/dna-repository/src/test/java/org/jboss/dna/repository/federation/FederationServiceTest.java	2008-07-01 20:17:39 UTC (rev 324)
@@ -22,17 +22,31 @@
 package org.jboss.dna.repository.federation;
 
 import static org.hamcrest.core.Is.is;
+import static org.hamcrest.core.IsInstanceOf.instanceOf;
 import static org.hamcrest.core.IsNull.notNullValue;
+import static org.hamcrest.core.IsNull.nullValue;
 import static org.hamcrest.core.IsSame.sameInstance;
 import static org.junit.Assert.assertThat;
+import static org.junit.matchers.JUnitMatchers.hasItems;
+import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.stub;
-import org.jboss.dna.repository.util.ExecutionContext;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyNoMoreInteractions;
+import java.util.concurrent.TimeUnit;
+import org.jboss.dna.common.component.ClassLoaderFactory;
+import org.jboss.dna.repository.services.ServiceAdministrator;
+import org.jboss.dna.spi.graph.NamespaceRegistry;
 import org.jboss.dna.spi.graph.Path;
 import org.jboss.dna.spi.graph.PathFactory;
+import org.jboss.dna.spi.graph.PropertyFactory;
+import org.jboss.dna.spi.graph.connection.ExecutionEnvironment;
+import org.jboss.dna.spi.graph.connection.RepositorySource;
 import org.jboss.dna.spi.graph.impl.BasicNamespaceRegistry;
+import org.jboss.dna.spi.graph.impl.BasicPropertyFactory;
 import org.jboss.dna.spi.graph.impl.StandardValueFactories;
+import org.junit.After;
 import org.junit.Before;
-import org.junit.Ignore;
 import org.junit.Test;
 import org.mockito.MockitoAnnotations;
 import org.mockito.MockitoAnnotations.Mock;
@@ -42,46 +56,250 @@
  */
 public class FederationServiceTest {
 
+    public static final String CLASSNAME = FederationService.CLASSNAME_PROPERTY_NAME;
+    public static final String CLASSPATH = FederationService.CLASSPATH_PROPERTY_NAME;
+    public static final String PATH_IN_REPOSITORY = FederationService.REGION_PATH_IN_REPOSITORY_PROPERTY_NAME;
+    public static final String PATH_IN_SOURCE = FederationService.REGION_PATH_IN_SOURCE_PROPERTY_NAME;
+    public static final String SOURCE_NAME = FederationService.REGION_SOURCE_NAME;
+    public static final String TIME_TO_EXPIRE = FederationService.CACHE_POLICY_TIME_TO_EXPIRE;
+    public static final String TIME_TO_CACHE = FederationService.CACHE_POLICY_TIME_TO_CACHE;
+
     private FederationService service;
     private FederatedRegion configRegion;
     private StandardValueFactories valueFactories;
+    private PropertyFactory propertyFactory;
     private PathFactory pathFactory;
     private String configSourceName;
+    private SimpleRepository configRepository;
+    private SimpleRepositorySource configRepositorySource;
     @Mock
-    private ExecutionContext env;
+    private ExecutionEnvironment env;
     @Mock
     private RepositorySourceManager sources;
 
     @Before
     public void beforeEach() throws Exception {
         MockitoAnnotations.initMocks(this);
+        NamespaceRegistry registry = new BasicNamespaceRegistry();
+        registry.register("dna", "http://www.jboss.org/dna");
+        valueFactories = new StandardValueFactories(registry);
+        pathFactory = valueFactories.getPathFactory();
+        propertyFactory = new BasicPropertyFactory(valueFactories);
+        Path pathInRepository = pathFactory.create("/");
+        Path pathInSource = pathFactory.create("/reposX");
         configSourceName = "configSource";
-        valueFactories = new StandardValueFactories(new BasicNamespaceRegistry());
-        pathFactory = valueFactories.getPathFactory();
-        Path pathInRepository = pathFactory.create("/dna:system");
-        Path pathInSource = pathFactory.create("/some/root");
-        configRegion = new FederatedRegion(pathInRepository, pathInSource, configSourceName);
+        configRegion = new FederatedRegion("config region", pathInRepository, pathInSource, configSourceName);
+        configRepository = new SimpleRepository("Configuration Repository");
+        configRepositorySource = new SimpleRepositorySource();
+        configRepositorySource.setRepositoryName(configRepository.getRepositoryName());
+        configRepositorySource.setName(configSourceName);
+        stub(sources.getConnectionFactory(configSourceName)).toReturn(configRepositorySource);
         stub(env.getValueFactories()).toReturn(valueFactories);
+        stub(env.getPropertyFactory()).toReturn(propertyFactory);
+        stub(env.getNamespaceRegistry()).toReturn(registry);
         service = new FederationService(sources, configRegion, env, null);
     }
 
-    @Ignore
+    @After
+    public void afterEach() throws Exception {
+        service.getAdministrator().shutdown();
+        service.getAdministrator().awaitTermination(2, TimeUnit.SECONDS);
+        SimpleRepository.shutdownAll();
+    }
+
     @Test
     public void shouldHaveServiceAdministratorAfterInstantiation() {
         assertThat(service.getAdministrator(), is(notNullValue()));
     }
 
-    @Ignore
     @Test
     public void shouldHaveConfigurationRegionAfterInstantiation() {
         assertThat(service.getConfigurationRegion(), is(notNullValue()));
         assertThat(service.getConfigurationRegion(), is(sameInstance(configRegion)));
     }
 
-    @Ignore
     @Test
+    public void shouldHaveAnExecutionEnvironmentAfterInstantiation() {
+        assertThat(service.getExecutionEnvironment(), is(notNullValue()));
+        assertThat(service.getExecutionEnvironment(), is(sameInstance(env)));
+    }
+
+    @Test
     public void shouldHaveNonNullClassLoaderFactoryAfterInstantiatingWithNullClassLoaderFactoryReference() {
         assertThat(service.getClassLoaderFactory(), is(notNullValue()));
     }
 
+    @Test
+    public void shouldHaveNonNullClassLoaderFactoryAfterInstantiatingWithClassLoaderFactoryReference() {
+        ClassLoaderFactory classLoaderFactory = mock(ClassLoaderFactory.class);
+        service = new FederationService(sources, configRegion, env, classLoaderFactory);
+        assertThat(service.getClassLoaderFactory(), is(notNullValue()));
+        assertThat(service.getClassLoaderFactory(), is(sameInstance(classLoaderFactory)));
+    }
+
+    @Test
+    public void shouldHaveNullJndiNameAfterInstantiation() {
+        assertThat(service.getJndiName(), is(nullValue()));
+    }
+
+    @Test
+    public void shouldAllowShuttingDownBeforeStartingUp() throws Exception {
+        assertThat(service.getAdministrator().getState(), is(ServiceAdministrator.State.PAUSED));
+        service.getAdministrator().shutdown();
+        service.getAdministrator().awaitTermination(1, TimeUnit.SECONDS);
+        assertThat(service.getAdministrator().getState(), is(ServiceAdministrator.State.TERMINATED));
+    }
+
+    @Test( expected = FederationException.class )
+    public void shouldFailToStartUpIfConfigurationRepositorySourceIsNotFound() {
+        stub(sources.getConnectionFactory(configSourceName)).toReturn(null);
+        service.getAdministrator().start();
+    }
+
+    @Test( expected = FederationException.class )
+    public void shouldFailToStartUpIfUnableToConnectToConfigurationRepository() throws Exception {
+        RepositorySource mockSource = mock(RepositorySource.class);
+        stub(sources.getConnectionFactory(configSourceName)).toReturn(mockSource);
+        stub(mockSource.getConnection()).toThrow(new UnsupportedOperationException());
+        service.getAdministrator().start();
+    }
+
+    @Test( expected = FederationException.class )
+    public void shouldFailToStartUpIfInterruptedWhileConnectingToConfigurationRepository() throws Exception {
+        RepositorySource mockSource = mock(RepositorySource.class);
+        stub(sources.getConnectionFactory(configSourceName)).toReturn(mockSource);
+        stub(mockSource.getConnection()).toThrow(new InterruptedException());
+        service.getAdministrator().start();
+    }
+
+    @Test
+    public void shouldStartUpUsingConfigurationRepositoryThatContainsSomeSources() {
+        // Use a real source manager for this test ...
+        sources = new RepositorySourceManager(sources);
+        sources.addSource(configRepositorySource, true);
+        assertThat(sources.getSources(), hasItems((RepositorySource)configRepositorySource));
+        assertThat(sources.getSources().size(), is(1));
+        service = new FederationService(sources, configRegion, env, null);
+
+        // Set up the configuration repository to contain 3 sources ...
+        configRepository.create(env, "/reposX/dna:sources");
+        configRepository.setProperty(env, "/reposX/dna:sources/source A", CLASSNAME, SimpleRepositorySource.class.getName());
+        configRepository.setProperty(env, "/reposX/dna:sources/source A", CLASSPATH, "");
+        configRepository.setProperty(env, "/reposX/dna:sources/source A", "repositoryName", "sourceReposA");
+        configRepository.setProperty(env, "/reposX/dna:sources/source A", "retryLimit", 3);
+
+        configRepository.setProperty(env, "/reposX/dna:sources/source B", CLASSNAME, SimpleRepositorySource.class.getName());
+        configRepository.setProperty(env, "/reposX/dna:sources/source B", CLASSPATH, "");
+        configRepository.setProperty(env, "/reposX/dna:sources/source B", "repositoryName", "sourceReposB");
+
+        configRepository.setProperty(env, "/reposX/dna:sources/source C", CLASSNAME, SimpleRepositorySource.class.getName());
+        configRepository.setProperty(env, "/reposX/dna:sources/source C", CLASSPATH, "");
+        configRepository.setProperty(env, "/reposX/dna:sources/source C", "repositoryName", "sourceReposC");
+
+        // Now, start up the service ...
+        service.getAdministrator().start();
+
+        // and verify that the sources were added to the manager...
+        assertThat(sources.getSources().size(), is(4));
+        assertThat(sources.getConnectionFactory("source A"), is(instanceOf(SimpleRepositorySource.class)));
+        assertThat(sources.getConnectionFactory("source B"), is(instanceOf(SimpleRepositorySource.class)));
+        assertThat(sources.getConnectionFactory("source C"), is(instanceOf(SimpleRepositorySource.class)));
+
+        SimpleRepositorySource sourceA = (SimpleRepositorySource)sources.getConnectionFactory("source A");
+        assertThat(sourceA.getName(), is("source A"));
+        assertThat(sourceA.getRepositoryName(), is("sourceReposA"));
+        assertThat(sourceA.getRetryLimit(), is(3));
+
+        SimpleRepositorySource sourceB = (SimpleRepositorySource)sources.getConnectionFactory("source B");
+        assertThat(sourceB.getName(), is("source B"));
+        assertThat(sourceB.getRepositoryName(), is("sourceReposB"));
+        assertThat(sourceB.getRetryLimit(), is(SimpleRepositorySource.DEFAULT_RETRY_LIMIT));
+
+        SimpleRepositorySource sourceC = (SimpleRepositorySource)sources.getConnectionFactory("source C");
+        assertThat(sourceC.getName(), is("source C"));
+        assertThat(sourceC.getRepositoryName(), is("sourceReposC"));
+        assertThat(sourceC.getRetryLimit(), is(SimpleRepositorySource.DEFAULT_RETRY_LIMIT));
+    }
+
+    @Test
+    public void shouldStartUpUsingConfigurationRepositoryThatContainsNoSources() {
+        // Set up the configuration repository to contain NO sources ...
+        configRepository.create(env, "/reposX/dna:sources");
+
+        // Now, start up the service ...
+        service.getAdministrator().start();
+
+        // and verify that the configuration source was obtained from the manager ...
+        verify(sources, times(1)).getConnectionFactory(configSourceName);
+
+        // and verify that the sources were never added to the manager...
+        verifyNoMoreInteractions(sources);
+    }
+
+    @Test
+    public void shouldStartUpAndCreateRepositoryUsingConfigurationRepositoryThatContainsNoSources() {
+        // Set up the configuration repository ...
+        configRepository.create(env, "/reposX/dna:sources");
+        configRepository.setProperty(env, "/reposX/dna:sources/source A", CLASSNAME, SimpleRepositorySource.class.getName());
+        configRepository.setProperty(env, "/reposX/dna:sources/source A", CLASSPATH, "");
+        configRepository.setProperty(env, "/reposX/dna:sources/source A", "repositoryName", "sourceReposA");
+        configRepository.setProperty(env, "/reposX/dna:sources/source A", "retryLimit", 3);
+
+        String fedReposPath = "/reposX/dna:repositories/fed repos/";
+        configRepository.setProperty(env, fedReposPath, TIME_TO_CACHE, "10000");
+        configRepository.setProperty(env, fedReposPath, TIME_TO_EXPIRE, "20000");
+        configRepository.setProperty(env, fedReposPath + "dna:regions/region1", PATH_IN_REPOSITORY, "/a/b/c");
+        configRepository.setProperty(env, fedReposPath + "dna:regions/region1", PATH_IN_SOURCE, "/sx/sy");
+        configRepository.setProperty(env, fedReposPath + "dna:regions/region1", SOURCE_NAME, "source A");
+        configRepository.setProperty(env, fedReposPath + "dna:regions/region2", PATH_IN_REPOSITORY, "/");
+        configRepository.setProperty(env, fedReposPath + "dna:regions/region2", PATH_IN_SOURCE, "/");
+        configRepository.setProperty(env, fedReposPath + "dna:regions/region2", SOURCE_NAME, "source B");
+        configRepository.setProperty(env, fedReposPath + "dna:regions/region3", PATH_IN_REPOSITORY, "/d/e/f");
+        configRepository.setProperty(env, fedReposPath + "dna:regions/region3", PATH_IN_SOURCE, "/");
+        configRepository.setProperty(env, fedReposPath + "dna:regions/region3", SOURCE_NAME, "source C");
+        configRepository.setProperty(env, fedReposPath + "dna:regions/region4", PATH_IN_REPOSITORY, "/");
+        configRepository.setProperty(env, fedReposPath + "dna:regions/region4", PATH_IN_SOURCE, "/x/y/z");
+        configRepository.setProperty(env, fedReposPath + "dna:regions/region4", SOURCE_NAME, "source A");
+
+        // Now, start up the service ...
+        service.getAdministrator().start();
+
+        // Create the repository ...
+        FederatedRepository repository = service.getRepository("fed repos");
+        assertThat(repository, is(notNullValue()));
+        assertThat(repository.getName(), is("fed repos"));
+        assertThat(repository.getConfiguration().getDefaultCachePolicy().getTimeToCache(), is(10000l));
+        assertThat(repository.getConfiguration().getDefaultCachePolicy().getTimeToExpire(), is(20000l));
+        assertThat(repository.getConfiguration().getRegions().get(0).getRegionName(), is("region1"));
+        assertThat(repository.getConfiguration().getRegions().get(0).getPathInRepository(), is(pathFactory.create("/a/b/c")));
+        assertThat(repository.getConfiguration().getRegions().get(0).getPathInSource(), is(pathFactory.create("/sx/sy")));
+        assertThat(repository.getConfiguration().getRegions().get(0).getSourceName(), is("source A"));
+        assertThat(repository.getConfiguration().getRegions().get(1).getRegionName(), is("region2"));
+        assertThat(repository.getConfiguration().getRegions().get(1).getPathInRepository(), is(pathFactory.create("/")));
+        assertThat(repository.getConfiguration().getRegions().get(1).getPathInSource(), is(pathFactory.create("/")));
+        assertThat(repository.getConfiguration().getRegions().get(1).getSourceName(), is("source B"));
+        assertThat(repository.getConfiguration().getRegions().get(2).getRegionName(), is("region3"));
+        assertThat(repository.getConfiguration().getRegions().get(2).getPathInRepository(), is(pathFactory.create("/d/e/f")));
+        assertThat(repository.getConfiguration().getRegions().get(2).getPathInSource(), is(pathFactory.create("/")));
+        assertThat(repository.getConfiguration().getRegions().get(2).getSourceName(), is("source C"));
+        assertThat(repository.getConfiguration().getRegions().get(3).getRegionName(), is("region4"));
+        assertThat(repository.getConfiguration().getRegions().get(3).getPathInRepository(), is(pathFactory.create("/")));
+        assertThat(repository.getConfiguration().getRegions().get(3).getPathInSource(), is(pathFactory.create("/x/y/z")));
+        assertThat(repository.getConfiguration().getRegions().get(3).getSourceName(), is("source A"));
+
+        for (int i = 0; i != 10; ++i) {
+            assertThat(service.getRepository("fed repos"), is(sameInstance(repository)));
+        }
+    }
+
+    @Test( expected = FederationException.class )
+    public void shouldThrowExceptionWhenGettingRepositoryThatDoesNotExistInConfigurationRepository() {
+        // No sources, no repositories in configuration repository ...
+
+        // Now, start up the service ...
+        service.getAdministrator().start();
+
+        // Get the non-existant repository ...
+        service.getRepository("non-existant repos");
+    }
 }

Added: trunk/dna-repository/src/test/java/org/jboss/dna/repository/federation/SimpleRepository.java
===================================================================
--- trunk/dna-repository/src/test/java/org/jboss/dna/repository/federation/SimpleRepository.java	                        (rev 0)
+++ trunk/dna-repository/src/test/java/org/jboss/dna/repository/federation/SimpleRepository.java	2008-07-01 20:17:39 UTC (rev 324)
@@ -0,0 +1,178 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors. 
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.dna.repository.federation;
+
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+import net.jcip.annotations.ThreadSafe;
+import org.jboss.dna.spi.graph.Name;
+import org.jboss.dna.spi.graph.NameFactory;
+import org.jboss.dna.spi.graph.Path;
+import org.jboss.dna.spi.graph.PathFactory;
+import org.jboss.dna.spi.graph.Property;
+import org.jboss.dna.spi.graph.PropertyFactory;
+import org.jboss.dna.spi.graph.connection.ExecutionEnvironment;
+
+/**
+ * A very simple repository that maintains properties for nodes identified by a path, and computes the children based upon the set
+ * of paths registered in the {@link #getData() data}.
+ * <p>
+ * Note that the repository does not automatically rename same-name siblings when nodes are
+ * {@link #delete(ExecutionEnvironment, String) deleted} or {@link #create(ExecutionEnvironment, String) explicitly} or
+ * {@link #setProperty(ExecutionEnvironment, String, String, Object...) implicitly} created.
+ * </p>
+ * 
+ * @author Randall Hauch
+ */
+ at ThreadSafe
+public class SimpleRepository {
+
+    private static final ConcurrentMap<String, SimpleRepository> repositoriesByName = new ConcurrentHashMap<String, SimpleRepository>();
+
+    public static SimpleRepository get( String name ) {
+        return repositoriesByName.get(name);
+    }
+
+    public static void shutdownAll() {
+        for (SimpleRepository repository : repositoriesByName.values()) {
+            repository.shutdown();
+        }
+    }
+
+    private ConcurrentMap<Path, Map<Name, Property>> data = new ConcurrentHashMap<Path, Map<Name, Property>>();
+    private final String repositoryName;
+    private boolean shutdown = false;
+
+    public SimpleRepository( String repositoryName ) {
+        this.repositoryName = repositoryName;
+        if (repositoriesByName.putIfAbsent(repositoryName, this) != null) {
+            throw new IllegalArgumentException("Repository \"" + repositoryName + "\" already exists and may not be recreated");
+        }
+    }
+
+    /**
+     * @return repositoryName
+     */
+    public String getRepositoryName() {
+        return repositoryName;
+    }
+
+    /**
+     * Get the current modifiable map of property data
+     * 
+     * @return data
+     */
+    public ConcurrentMap<Path, Map<Name, Property>> getData() {
+        return data;
+    }
+
+    /**
+     * Utility method to help set the property on the node given by the supplied path. If the node does not exist, it will be
+     * created.
+     * 
+     * @param env the environment; may not be null
+     * @param path the path to the node; may not be null
+     * @param propertyName the property name; may not be null
+     * @param values the values of the property
+     * @return this repository, for method chaining
+     */
+    public SimpleRepository setProperty( ExecutionEnvironment env,
+                                         String path,
+                                         String propertyName,
+                                         Object... values ) {
+        PathFactory pathFactory = env.getValueFactories().getPathFactory();
+        NameFactory nameFactory = env.getValueFactories().getNameFactory();
+        PropertyFactory propertyFactory = env.getPropertyFactory();
+        Path pathObj = pathFactory.create(path);
+        create(env, pathObj.getAncestor().getString(env.getNamespaceRegistry()));
+        Property property = propertyFactory.create(nameFactory.create(propertyName), values);
+        Map<Name, Property> properties = new HashMap<Name, Property>();
+        Map<Name, Property> existingProperties = data.putIfAbsent(pathObj, properties);
+        if (existingProperties == null) existingProperties = properties;
+        existingProperties.put(property.getName(), property);
+        return this;
+    }
+
+    /**
+     * Create the node if it does not exist.
+     * 
+     * @param env the environment; may not be null
+     * @param path the path to the node; may not be null
+     * @return this repository, for method chaining
+     */
+    public SimpleRepository create( ExecutionEnvironment env,
+                                    String path ) {
+        PathFactory pathFactory = env.getValueFactories().getPathFactory();
+        Path pathObj = pathFactory.create(path);
+        Path ancestorPath = pathObj.getAncestor();
+        while (!ancestorPath.isRoot()) {
+            data.putIfAbsent(ancestorPath, new HashMap<Name, Property>());
+            ancestorPath = ancestorPath.getAncestor();
+        }
+        data.putIfAbsent(pathObj, new HashMap<Name, Property>());
+        return this;
+    }
+
+    /**
+     * Delete the branch rooted at the supplied path, if it exists.
+     * 
+     * @param env the environment; may not be null
+     * @param path the path to the branch's top node; may not be null
+     * @return this repository, for method chaining
+     */
+    public SimpleRepository delete( ExecutionEnvironment env,
+                                    String path ) {
+        PathFactory pathFactory = env.getValueFactories().getPathFactory();
+        Path pathObj = pathFactory.create(path);
+        List<Path> pathsToRemove = new LinkedList<Path>();
+        for (Path nodePath : data.keySet()) {
+            if (nodePath.equals(pathObj) || nodePath.isDecendantOf(pathObj)) {
+                pathsToRemove.add(nodePath);
+            }
+        }
+        for (Path pathToRemove : pathsToRemove) {
+            data.remove(pathToRemove);
+        }
+        return this;
+    }
+
+    /**
+     * @param data new new map of property data
+     */
+    public void setData( ConcurrentMap<Path, Map<Name, Property>> data ) {
+        this.data = data;
+    }
+
+    public boolean isShutdown() {
+        return shutdown;
+    }
+
+    public void shutdown() {
+        shutdown = true;
+        repositoriesByName.remove(this.repositoryName);
+    }
+
+}


Property changes on: trunk/dna-repository/src/test/java/org/jboss/dna/repository/federation/SimpleRepository.java
___________________________________________________________________
Name: svn:mime-type
   + text/plain

Added: trunk/dna-repository/src/test/java/org/jboss/dna/repository/federation/SimpleRepositorySource.java
===================================================================
--- trunk/dna-repository/src/test/java/org/jboss/dna/repository/federation/SimpleRepositorySource.java	                        (rev 0)
+++ trunk/dna-repository/src/test/java/org/jboss/dna/repository/federation/SimpleRepositorySource.java	2008-07-01 20:17:39 UTC (rev 324)
@@ -0,0 +1,294 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors. 
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.dna.repository.federation;
+
+import java.util.Collections;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.TimeUnit;
+import javax.naming.Reference;
+import javax.transaction.xa.XAResource;
+import org.jboss.dna.spi.cache.CachePolicy;
+import org.jboss.dna.spi.graph.InvalidPathException;
+import org.jboss.dna.spi.graph.Name;
+import org.jboss.dna.spi.graph.Path;
+import org.jboss.dna.spi.graph.Property;
+import org.jboss.dna.spi.graph.commands.CompositeCommand;
+import org.jboss.dna.spi.graph.commands.GetChildrenCommand;
+import org.jboss.dna.spi.graph.commands.GetPropertiesCommand;
+import org.jboss.dna.spi.graph.commands.GraphCommand;
+import org.jboss.dna.spi.graph.connection.ExecutionEnvironment;
+import org.jboss.dna.spi.graph.connection.RepositoryConnection;
+import org.jboss.dna.spi.graph.connection.RepositorySource;
+import org.jboss.dna.spi.graph.connection.RepositorySourceException;
+import org.jboss.dna.spi.graph.connection.RepositorySourceListener;
+
+/**
+ * A {@link RepositorySource} for a {@link SimpleRepository simple repository}.
+ * 
+ * @author Randall Hauch
+ */
+public class SimpleRepositorySource implements RepositorySource {
+
+    private static final long serialVersionUID = 1L;
+
+    public static final int DEFAULT_RETRY_LIMIT = 5;
+
+    private String repositoryName;
+    private String name;
+    private int retryLimit = DEFAULT_RETRY_LIMIT;
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.spi.graph.connection.RepositorySource#getRetryLimit()
+     */
+    public int getRetryLimit() {
+        return retryLimit;
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.spi.graph.connection.RepositorySource#setRetryLimit(int)
+     */
+    public void setRetryLimit( int limit ) {
+        retryLimit = limit;
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.spi.graph.connection.RepositoryConnectionFactory#getName()
+     */
+    public String getName() {
+        return name;
+    }
+
+    /**
+     * @param name Sets name to the specified value.
+     */
+    public void setName( String name ) {
+        this.name = name;
+    }
+
+    /**
+     * @return repositoryName
+     */
+    public String getRepositoryName() {
+        return repositoryName;
+    }
+
+    /**
+     * @param repositoryName Sets repositoryName to the specified value.
+     */
+    public void setRepositoryName( String repositoryName ) {
+        this.repositoryName = repositoryName;
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see javax.naming.Referenceable#getReference()
+     */
+    public Reference getReference() {
+        throw new UnsupportedOperationException();
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.spi.graph.connection.RepositoryConnectionFactory#getConnection()
+     */
+    public RepositoryConnection getConnection() throws RepositorySourceException {
+        String reposName = this.repositoryName;
+        SimpleRepository repository = SimpleRepository.get(reposName);
+        if (repository == null) {
+            throw new RepositorySourceException(this.getName(), "Unable to find repository \"" + reposName + "\"");
+        }
+        return new Connection(repository);
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see java.lang.Object#hashCode()
+     */
+    @Override
+    public int hashCode() {
+        return name.hashCode();
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see java.lang.Object#equals(java.lang.Object)
+     */
+    @Override
+    public boolean equals( Object obj ) {
+        if (obj == this) return true;
+        if (obj instanceof SimpleRepositorySource) {
+            SimpleRepositorySource that = (SimpleRepositorySource)obj;
+            if (!this.getName().equals(that.getName())) return false;
+            if (!this.getRepositoryName().equals(that.getRepositoryName())) return false;
+            return true;
+        }
+        return false;
+    }
+
+    protected class Connection implements RepositoryConnection {
+
+        private RepositorySourceListener listener;
+        private final SimpleRepository repository;
+
+        protected Connection( SimpleRepository repository ) {
+            assert repository != null;
+            this.repository = repository;
+        }
+
+        /**
+         * {@inheritDoc}
+         * 
+         * @see org.jboss.dna.spi.graph.connection.RepositoryConnection#close()
+         */
+        public void close() {
+        }
+
+        /**
+         * {@inheritDoc}
+         * 
+         * @see org.jboss.dna.spi.graph.connection.RepositoryConnection#execute(org.jboss.dna.spi.graph.connection.ExecutionEnvironment,
+         *      org.jboss.dna.spi.graph.commands.GraphCommand[])
+         */
+        public void execute( ExecutionEnvironment env,
+                             GraphCommand... commands ) throws RepositorySourceException {
+            assert env != null;
+            if (repository.isShutdown()) {
+                throw new RepositorySourceException(getName(), "The repository \"" + repository.getRepositoryName()
+                                                               + "\" is no longer available");
+            }
+            for (GraphCommand command : commands) {
+                executeCommand(env, command);
+            }
+        }
+
+        protected void executeCommand( ExecutionEnvironment env,
+                                       GraphCommand command ) {
+            if (command == null) return;
+            if (command instanceof CompositeCommand) {
+                CompositeCommand composite = (CompositeCommand)command;
+                for (GraphCommand nestedCommand : composite) {
+                    executeCommand(env, nestedCommand);
+                }
+            }
+            Map<Path, Map<Name, Property>> data = repository.getData();
+            // Only commands we recognize are the following; everything else is ignored ...
+            if (command instanceof GetPropertiesCommand) { // super of GetNodeCommand
+                GetPropertiesCommand getProperties = (GetPropertiesCommand)command;
+                Path targetPath = getProperties.getPath();
+                Map<Name, Property> properties = data.get(targetPath);
+                if (properties == null) {
+                    getProperties.setError(new InvalidPathException("Non-existant node: " + targetPath));
+                    return;
+                }
+                for (Property property : properties.values()) {
+                    getProperties.setProperty(property);
+                }
+            }
+            if (command instanceof GetChildrenCommand) { // super of GetNodeCommand
+                GetChildrenCommand getChildren = (GetChildrenCommand)command;
+                Path targetPath = getChildren.getPath();
+                if (data.get(targetPath) == null) {
+                    getChildren.setError(new InvalidPathException("Non-existant node: " + targetPath));
+                    return;
+                }
+                // Iterate through all of the properties, looking for any paths that are children of the path ...
+                List<Path.Segment> childSegments = new LinkedList<Path.Segment>();
+                for (Path path : data.keySet()) {
+                    if (path.getAncestor().equals(targetPath)) {
+                        childSegments.add(path.getLastSegment());
+                    }
+                }
+                // This does not store children order, so sort ...
+                Collections.sort(childSegments);
+                getChildren.setChildren(childSegments);
+            }
+
+        }
+
+        /**
+         * {@inheritDoc}
+         * 
+         * @see org.jboss.dna.spi.graph.connection.RepositoryConnection#getDefaultCachePolicy()
+         */
+        public CachePolicy getDefaultCachePolicy() {
+            return null;
+        }
+
+        /**
+         * {@inheritDoc}
+         * 
+         * @see org.jboss.dna.spi.graph.connection.RepositoryConnection#getSourceName()
+         */
+        public String getSourceName() {
+            return SimpleRepositorySource.this.getName();
+        }
+
+        /**
+         * {@inheritDoc}
+         * 
+         * @see org.jboss.dna.spi.graph.connection.RepositoryConnection#getXAResource()
+         */
+        public XAResource getXAResource() {
+            return null;
+        }
+
+        /**
+         * {@inheritDoc}
+         * 
+         * @see org.jboss.dna.spi.graph.connection.RepositoryConnection#ping(long, java.util.concurrent.TimeUnit)
+         */
+        public boolean ping( long time,
+                             TimeUnit unit ) {
+            return true;
+        }
+
+        /**
+         * {@inheritDoc}
+         * 
+         * @see org.jboss.dna.spi.graph.connection.RepositoryConnection#setListener(org.jboss.dna.spi.graph.connection.RepositorySourceListener)
+         */
+        public void setListener( RepositorySourceListener listener ) {
+            this.listener = listener;
+        }
+
+        /**
+         * @return listener
+         */
+        public RepositorySourceListener getListener() {
+            return listener;
+        }
+
+    }
+
+}


Property changes on: trunk/dna-repository/src/test/java/org/jboss/dna/repository/federation/SimpleRepositorySource.java
___________________________________________________________________
Name: svn:mime-type
   + text/plain




More information about the dna-commits mailing list