[dna-commits] DNA SVN: r321 - in trunk: dna-repository/src/test/java/org/jboss/dna/repository/federation and 3 other directories.

dna-commits at lists.jboss.org dna-commits at lists.jboss.org
Mon Jun 30 17:45:21 EDT 2008


Author: rhauch
Date: 2008-06-30 17:45:21 -0400 (Mon, 30 Jun 2008)
New Revision: 321

Added:
   trunk/dna-repository/src/main/java/org/jboss/dna/repository/federation/FederatedNode.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/RepositoryConnectionFactories.java
   trunk/dna-repository/src/main/java/org/jboss/dna/repository/federation/RepositorySourceManager.java
   trunk/dna-repository/src/test/java/org/jboss/dna/repository/federation/FederationServiceTest.java
   trunk/dna-spi/src/main/java/org/jboss/dna/spi/graph/commands/impl/BasicCompositeCommand.java
   trunk/dna-spi/src/main/java/org/jboss/dna/spi/graph/connection/BasicExecutionEnvironment.java
   trunk/dna-spi/src/main/java/org/jboss/dna/spi/graph/connection/ExecutionEnvironments.java
   trunk/dna-spi/src/main/java/org/jboss/dna/spi/graph/connection/RepositoryConnectionPool.java
   trunk/dna-spi/src/main/java/org/jboss/dna/spi/graph/impl/AbstractValueFactories.java
   trunk/dna-spi/src/main/java/org/jboss/dna/spi/graph/impl/DelegatingValueFactories.java
Log:
DNA-115: Create federation service - Completed another round of refactoring to simplify configuration that also allows distribution/clustering

Added: trunk/dna-repository/src/main/java/org/jboss/dna/repository/federation/FederatedNode.java
===================================================================
--- trunk/dna-repository/src/main/java/org/jboss/dna/repository/federation/FederatedNode.java	                        (rev 0)
+++ trunk/dna-repository/src/main/java/org/jboss/dna/repository/federation/FederatedNode.java	2008-06-30 21:45:21 UTC (rev 321)
@@ -0,0 +1,140 @@
+/*
+ * 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.Iterator;
+import java.util.Set;
+import java.util.UUID;
+import net.jcip.annotations.ThreadSafe;
+import org.jboss.dna.spi.graph.Name;
+import org.jboss.dna.spi.graph.Property;
+
+/**
+ * @author Randall Hauch
+ */
+ at ThreadSafe
+public interface FederatedNode {
+    /**
+     * Get the unique identifier for this federated node.
+     * 
+     * @return the UUID; never null
+     */
+    UUID getUuid();
+
+    /**
+     * Get the name of this node.
+     * 
+     * @return the node name; never null
+     */
+    Name getName();
+
+    /**
+     * Get the property with the given name.
+     * 
+     * @param propertyName the property name
+     * @return the property, or null if the property does not exist
+     * @throws IllegalArgumentException if the name is null
+     */
+    Property getProperty( Name propertyName );
+
+    /**
+     * Get the number of properties on this node. This value is technically an estimate, as it may not exactly match the number of
+     * properties returned by {@link #getProperties()} or {@link #getPropertyNames()}.
+     * 
+     * @return the approximate number of properties.
+     */
+    int getPropertyCount();
+
+    /**
+     * Get the properties. This method returns a consistent set of properties at the moment this method is called, and is not
+     * affected by additions or change to the properties. In other words, it is safe for concurrent operations and is not a
+     * fail-fast iterator.
+     * 
+     * @return the properties on this node via an immutable iterator
+     */
+    Iterator<Property> getProperties();
+
+    /**
+     * Get the names of the properties for this node. This method returns a consistent set of names at the moment this method is
+     * called, and is not affected by additions or change to the properties. In other words, it is safe for concurrent operations
+     * and is not a fail-fast iterator.
+     * 
+     * @return the property names via an immutable iterator
+     */
+    Iterator<Name> getPropertyNames();
+
+    /**
+     * Set the property if it is not already set.
+     * 
+     * @param property the property
+     * @return the existing property, or null if there was no property and the supplied property was set
+     * @throws IllegalArgumentException if the property is null
+     */
+    Property setPropertyIfAbsent( Property property );
+
+    /**
+     * Set the supplied properties. This method will overwrite any existing properties with the new properties if they have the
+     * same {@link Property#getName() property name}. This method ignores any null property references, and does nothing if there
+     * are no properties supplied.
+     * 
+     * @param properties the properties that should be set
+     */
+    void setProperties( Property... properties );
+
+    /**
+     * Set the supplied properties. This method will overwrite any existing properties with the new properties if they have the
+     * same {@link Property#getName() property name}. This method ignores any null property references, and does nothing if there
+     * are no properties supplied.
+     * 
+     * @param properties the properties that should be set
+     */
+    void setProperties( Iterable<Property> properties );
+
+    /**
+     * Replace all existing properties with the supplied properties. This method ignores any null property references, and does
+     * nothing if there are no properties supplied.
+     * 
+     * @param properties the properties that should be set
+     */
+    void setAllProperties( Property... properties );
+
+    /**
+     * Replace all existing properties with the supplied properties. This method ignores any null property references, and does
+     * nothing if there are no properties supplied.
+     * 
+     * @param properties the properties that should replace the existing properties
+     */
+    void setAllProperties( Iterable<Property> properties );
+
+    /**
+     * Remove all properties, except for the {@link #getName() name} and {@link #getUuid() identifier}.
+     */
+    void removeAllProperties();
+
+    /**
+     * Get the sources that have contributed information to this node.
+     * 
+     * @return the names of the sources that have contributed content to this node.
+     */
+    Set<String> getContributingSources();
+
+}

Added: 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	                        (rev 0)
+++ trunk/dna-repository/src/main/java/org/jboss/dna/repository/federation/FederatedRegion.java	2008-06-30 21:45:21 UTC (rev 321)
@@ -0,0 +1,188 @@
+/*
+ * 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 net.jcip.annotations.Immutable;
+import org.jboss.dna.common.util.ArgCheck;
+import org.jboss.dna.repository.RepositoryI18n;
+import org.jboss.dna.spi.graph.Path;
+import org.jboss.dna.spi.graph.PathFactory;
+
+/**
+ * A binding of content from a source into a particular location within a repository. The content in the source is defined by the
+ * name of the source and the {@link #getPathInSource() path within the source}. The {@link #getPathInRepository() path in the
+ * repository} defines the location at which the content appears.
+ * <p>
+ * Note that it is possible for a federated repository to have a single source may be bound to multiple locations, and multiple
+ * sources bound to the same location.
+ * </p>
+ * 
+ * @author Randall Hauch
+ */
+ at Immutable
+public class FederatedRegion implements Comparable<FederatedRegion> {
+
+    private final Path pathInRepository;
+    private final Path pathInSource;
+    private final String sourceName;
+
+    /**
+     * Create a binding given a location in the repository below which the content from the named source appears.
+     * 
+     * @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 ) {
+        ArgCheck.isNotNull(pathInRepository, "pathInRepository");
+        ArgCheck.isNotNull(pathInSource, "pathInSource");
+        ArgCheck.isNotEmpty(sourceName, "sourceName");
+        if (!pathInRepository.isAbsolute()) {
+            String msg = RepositoryI18n.repositoryPathInFederationBindingIsNotAbsolute.text(pathInRepository.getString());
+            throw new IllegalArgumentException(msg);
+        }
+        this.pathInRepository = pathInRepository;
+        this.pathInSource = pathInSource;
+        this.sourceName = sourceName;
+    }
+
+    /**
+     * 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
+     */
+    public Path getPathInRepository() {
+        return pathInRepository;
+    }
+
+    /**
+     * Get the path to the source content that is bound to the {@link #getPathInRepository() repository location}. This path is
+     * source-specific, and may be either absolute or relative.
+     * 
+     * @return pathInSource
+     */
+    public Path getPathInSource() {
+        return pathInSource;
+    }
+
+    /**
+     * @return sourceName
+     */
+    public String getSourceName() {
+        return sourceName;
+    }
+
+    /**
+     * Convert a path defined in the source system into an equivalent path in the repository system.
+     * 
+     * @param pathInSource the path in the source system, which may include the {@link #getPathInSource()}
+     * @param factory the path factory; may not be null
+     * @return the path in the repository system, which will be normalized and absolute (including the
+     *         {@link #getPathInRepository()})
+     */
+    public Path convertPathInSourceToPathInRepository( Path pathInSource,
+                                                       PathFactory factory ) {
+        Path relativeSourcePath = pathInSource;
+        if (this.pathInSource.isAncestorOf(pathInSource)) {
+            // Remove the leading source path ...
+            relativeSourcePath = pathInSource.relativeTo(this.pathInSource);
+        }
+        // Prepend the region's root path ...
+        Path result = factory.create(this.pathInRepository, relativeSourcePath);
+        return result.getNormalizedPath();
+    }
+
+    /**
+     * Convert a path defined in the repository system into an equivalent path in the source system.
+     * 
+     * @param pathInRepository the path in the repository system, which may include the {@link #getPathInRepository()}
+     * @param factory the path factory; may not be null
+     * @return the path in the source system, which will be normalized and absolute (including the {@link #getPathInSource()})
+     */
+    public Path convertPathInRepositoryToPathInSource( Path pathInRepository,
+                                                       PathFactory factory ) {
+        Path pathInRegion = pathInRepository;
+        if (this.pathInRepository.isAncestorOf(pathInRepository)) {
+            // Find the relative path from the root of this region ...
+            pathInRegion = pathInRepository.relativeTo(this.pathInRepository);
+        }
+        // Prepend the path in source ...
+        Path result = factory.create(this.pathInSource, pathInRegion);
+        return result.getNormalizedPath();
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see java.lang.Object#hashCode()
+     */
+    @Override
+    public int hashCode() {
+        return pathInRepository.hashCode();
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see java.lang.Object#equals(java.lang.Object)
+     */
+    @Override
+    public boolean equals( Object obj ) {
+        if (obj == this) return true;
+        if (obj instanceof FederatedRegion) {
+            FederatedRegion that = (FederatedRegion)obj;
+            if (!this.getPathInRepository().equals(that.getPathInRepository())) return false;
+            if (!this.getPathInSource().equals(that.getPathInSource())) return false;
+            if (!this.getSourceName().equals(that.getSourceName())) return false;
+            return true;
+        }
+        return false;
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see java.lang.Comparable#compareTo(java.lang.Object)
+     */
+    public int compareTo( FederatedRegion that ) {
+        if (this == that) return 0;
+        int 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());
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see java.lang.Object#toString()
+     */
+    @Override
+    public String toString() {
+        return this.getPathInRepository().toString() + " -> \"" + this.getSourceName() + "\":" + this.getPathInSource();
+    }
+}

Added: trunk/dna-repository/src/main/java/org/jboss/dna/repository/federation/RepositoryConnectionFactories.java
===================================================================
--- trunk/dna-repository/src/main/java/org/jboss/dna/repository/federation/RepositoryConnectionFactories.java	                        (rev 0)
+++ trunk/dna-repository/src/main/java/org/jboss/dna/repository/federation/RepositoryConnectionFactories.java	2008-06-30 21:45:21 UTC (rev 321)
@@ -0,0 +1,33 @@
+/*
+ * 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 org.jboss.dna.spi.graph.connection.RepositoryConnectionFactory;
+
+/**
+ * @author Randall Hauch
+ */
+public interface RepositoryConnectionFactories {
+
+    RepositoryConnectionFactory getConnectionFactory( String sourceName );
+
+}

Added: 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	                        (rev 0)
+++ trunk/dna-repository/src/main/java/org/jboss/dna/repository/federation/RepositorySourceManager.java	2008-06-30 21:45:21 UTC (rev 321)
@@ -0,0 +1,341 @@
+/*
+ * 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.Collection;
+import java.util.Collections;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.ReentrantLock;
+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.graph.connection.RepositoryConnection;
+import org.jboss.dna.spi.graph.connection.RepositoryConnectionFactory;
+import org.jboss.dna.spi.graph.connection.RepositoryConnectionPool;
+import org.jboss.dna.spi.graph.connection.RepositorySource;
+
+/**
+ * @author Randall Hauch
+ */
+public class RepositorySourceManager implements RepositoryConnectionFactories {
+
+    /**
+     * The administrative component for this service.
+     * 
+     * @author Randall Hauch
+     */
+    protected class Administrator extends AbstractServiceAdministrator {
+
+        protected Administrator() {
+            super(RepositoryI18n.federationServiceName, State.STARTED);
+        }
+
+        /**
+         * {@inheritDoc}
+         */
+        @Override
+        protected void doStart( State fromState ) {
+            super.doStart(fromState);
+            RepositorySourceManager.this.start();
+        }
+
+        /**
+         * {@inheritDoc}
+         */
+        @Override
+        protected void doShutdown( State fromState ) {
+            super.doShutdown(fromState);
+            RepositorySourceManager.this.shutdown();
+        }
+
+        /**
+         * {@inheritDoc}
+         */
+        public boolean awaitTermination( long timeout,
+                                         TimeUnit unit ) throws InterruptedException {
+            return RepositorySourceManager.this.awaitTermination(timeout, unit);
+        }
+
+        /**
+         * {@inheritDoc}
+         */
+        @Override
+        protected boolean doCheckIsTerminated() {
+            return RepositorySourceManager.this.isTerminated();
+        }
+
+    }
+
+    private final ServiceAdministrator administrator = new Administrator();
+    private final Lock sourcesWriteLock = new ReentrantLock();
+    private final ConcurrentMap<String, RepositorySource> sources = new ConcurrentHashMap<String, RepositorySource>();
+    private RepositoryConnectionFactories delegate;
+
+    /**
+     * Create a new manager instance.
+     * 
+     * @param delegate the factories object that this instance should delegate to in the event that a source is not found in this
+     *        manager; may be null if there is no delegate
+     */
+    public RepositorySourceManager( RepositoryConnectionFactories delegate ) {
+        this.delegate = delegate;
+    }
+
+    /**
+     * @return delegate
+     */
+    public RepositoryConnectionFactories getDelegate() {
+        return delegate;
+    }
+
+    /**
+     * @param delegate Sets delegate to the specified value.
+     */
+    public void setDelegate( RepositoryConnectionFactories delegate ) {
+        this.delegate = delegate;
+    }
+
+    /**
+     * @return administrator
+     */
+    public ServiceAdministrator getAdministrator() {
+        return this.administrator;
+    }
+
+    /**
+     * Utility method called by the administrator.
+     */
+    protected void start() {
+        // Do not establish connections to the sources; these will be established as needed
+
+    }
+
+    /**
+     * Utility method called by the administrator.
+     */
+    protected void shutdown() {
+        // Close all connections to the sources. This is done inside the sources write lock.
+        try {
+            this.sourcesWriteLock.lock();
+            for (RepositorySource source : this.sources.values()) {
+                if (source instanceof RepositoryConnectionPool) {
+                    RepositoryConnectionPool pool = (RepositoryConnectionPool)source;
+                    pool.shutdown();
+                }
+            }
+        } finally {
+            this.sourcesWriteLock.unlock();
+        }
+    }
+
+    /**
+     * Utility method called by the administrator.
+     * 
+     * @param timeout
+     * @param unit
+     * @return true if all pools were terminated in the supplied time (or were already terminated), or false if the timeout
+     *         occurred before all the connections were closed
+     * @throws InterruptedException
+     */
+    protected boolean awaitTermination( long timeout,
+                                        TimeUnit unit ) throws InterruptedException {
+        // Check whether all source pools are shut down. This is done inside the sources write lock.
+        try {
+            this.sourcesWriteLock.lock();
+            for (RepositorySource source : this.sources.values()) {
+                if (source instanceof RepositoryConnectionPool) {
+                    RepositoryConnectionPool pool = (RepositoryConnectionPool)source;
+                    if (!pool.awaitTermination(timeout, unit)) {
+                        return false;
+                    }
+                }
+            }
+            return true;
+        } finally {
+            this.sourcesWriteLock.unlock();
+        }
+    }
+
+    /**
+     * Returns true if this federated repository is in the process of terminating after {@link ServiceAdministrator#shutdown()}
+     * has been called on the {@link #getAdministrator() administrator}, but the federated repository has connections that have
+     * not yet normally been {@link RepositoryConnection#close() closed}. This method may be useful for debugging. A return of
+     * <tt>true</tt> reported a sufficient period after shutdown may indicate that connection users have ignored or suppressed
+     * interruption, causing this repository not to properly terminate.
+     * 
+     * @return true if terminating but not yet terminated, or false otherwise
+     * @see #isTerminated()
+     */
+    public boolean isTerminating() {
+        try {
+            this.sourcesWriteLock.lock();
+            for (RepositorySource source : this.sources.values()) {
+                if (source instanceof RepositoryConnectionPool) {
+                    RepositoryConnectionPool pool = (RepositoryConnectionPool)source;
+                    if (pool.isTerminating()) {
+                        return true;
+                    }
+                }
+            }
+            return false;
+        } finally {
+            this.sourcesWriteLock.unlock();
+        }
+    }
+
+    /**
+     * Return true if this federated repository has completed its termination and no longer has any open connections.
+     * 
+     * @return true if terminated, or false otherwise
+     * @see #isTerminating()
+     */
+    public boolean isTerminated() {
+        try {
+            this.sourcesWriteLock.lock();
+            for (RepositorySource source : this.sources.values()) {
+                if (source instanceof RepositoryConnectionPool) {
+                    RepositoryConnectionPool pool = (RepositoryConnectionPool)source;
+                    if (!pool.isTerminated()) {
+                        return false;
+                    }
+                }
+            }
+            return true;
+        } finally {
+            this.sourcesWriteLock.unlock();
+        }
+    }
+
+    /**
+     * Get an unmodifiable collection of {@link RepositorySource federated sources}.
+     * <p>
+     * This method can safely be called while the federation repository is in use.
+     * </p>
+     * 
+     * @return the sources
+     */
+    public Collection<RepositorySource> getSources() {
+        return Collections.unmodifiableCollection(this.sources.values());
+    }
+
+    /**
+     * Add the supplied federated source. This method returns false if the source is null.
+     * <p>
+     * This method can safely be called while the federation repository is in use.
+     * </p>
+     * 
+     * @param source the source to add
+     * @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 ) {
+        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);
+        } finally {
+            this.sourcesWriteLock.unlock();
+        }
+        return true;
+    }
+
+    /**
+     * Remove from this federated repository the supplied source (or a source with the same name as that supplied). This call
+     * shuts down the connections in the source in an orderly fashion, allowing those connection currently in use to be used and
+     * closed normally, but preventing further connections from being used.
+     * <p>
+     * This method can safely be called while the federation repository is in use.
+     * </p>
+     * 
+     * @param source the source to be removed
+     * @param timeToAwait the amount of time to wait while all of the source's connections are closed, or non-positive if the call
+     *        should not wait at all
+     * @param unit the time unit to be used for <code>timeToAwait</code>
+     * @return true if the source was removed, or false if the source was not a source for this repository.
+     * @throws InterruptedException if the thread is interrupted while awaiting closing of the connections
+     */
+    public boolean removeSource( RepositorySource source,
+                                 long timeToAwait,
+                                 TimeUnit unit ) throws InterruptedException {
+        // Use the name; don't use the object equality ...
+        return removeSource(source.getName(), timeToAwait, unit) != null;
+    }
+
+    /**
+     * Remove from this federated repository the source with the supplied name. This call shuts down the connections in the source
+     * in an orderly fashion, allowing those connection currently in use to be used and closed normally, but preventing further
+     * connections from being used.
+     * <p>
+     * This method can safely be called while the federation repository is in use.
+     * </p>
+     * 
+     * @param name the name of the source to be removed
+     * @param timeToAwait the amount of time to wait while all of the source's connections are closed, or non-positive if the call
+     *        should not wait at all
+     * @param unit the time unit to be used for <code>timeToAwait</code>
+     * @return the source with the supplied name that was removed, or null if no existing source matching the supplied name could
+     *         be found
+     * @throws InterruptedException if the thread is interrupted while awaiting closing of the connections
+     */
+    public RepositorySource removeSource( String name,
+                                          long timeToAwait,
+                                          TimeUnit unit ) throws InterruptedException {
+        try {
+            this.sourcesWriteLock.lock();
+            RepositorySource existingSource = this.sources.remove(name);
+            if (existingSource != null) {
+                // Shut down the connection pool if it is one ...
+                if (existingSource instanceof RepositoryConnectionPool) {
+                    RepositoryConnectionPool pool = (RepositoryConnectionPool)existingSource;
+                    pool.shutdown();
+                    if (timeToAwait > 0l) pool.awaitTermination(timeToAwait, unit);
+                }
+            }
+            return existingSource;
+        } finally {
+            this.sourcesWriteLock.unlock();
+        }
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.jboss.dna.repository.federation.RepositoryConnectionFactories#getConnectionFactory(java.lang.String)
+     */
+    public RepositoryConnectionFactory getConnectionFactory( String sourceName ) {
+        RepositoryConnectionFactory result = this.sources.get(sourceName);
+        if (result == null) {
+            RepositoryConnectionFactories delegate = this.delegate;
+            if (delegate != null) {
+                result = delegate.getConnectionFactory(sourceName);
+            }
+        }
+        return result;
+    }
+
+}

Added: 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	                        (rev 0)
+++ trunk/dna-repository/src/test/java/org/jboss/dna/repository/federation/FederationServiceTest.java	2008-06-30 21:45:21 UTC (rev 321)
@@ -0,0 +1,87 @@
+/*
+ * 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 static org.hamcrest.core.Is.is;
+import static org.hamcrest.core.IsNull.notNullValue;
+import static org.hamcrest.core.IsSame.sameInstance;
+import static org.junit.Assert.assertThat;
+import static org.mockito.Mockito.stub;
+import org.jboss.dna.repository.util.ExecutionContext;
+import org.jboss.dna.spi.graph.Path;
+import org.jboss.dna.spi.graph.PathFactory;
+import org.jboss.dna.spi.graph.impl.BasicNamespaceRegistry;
+import org.jboss.dna.spi.graph.impl.StandardValueFactories;
+import org.junit.Before;
+import org.junit.Ignore;
+import org.junit.Test;
+import org.mockito.MockitoAnnotations;
+import org.mockito.MockitoAnnotations.Mock;
+
+/**
+ * @author Randall Hauch
+ */
+public class FederationServiceTest {
+
+    private FederationService service;
+    private FederatedRegion configRegion;
+    private StandardValueFactories valueFactories;
+    private PathFactory pathFactory;
+    private String configSourceName;
+    @Mock
+    private ExecutionContext env;
+    @Mock
+    private RepositorySourceManager sources;
+
+    @Before
+    public void beforeEach() throws Exception {
+        MockitoAnnotations.initMocks(this);
+        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);
+        stub(env.getValueFactories()).toReturn(valueFactories);
+        service = new FederationService(sources, configRegion, env, null);
+    }
+
+    @Ignore
+    @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 shouldHaveNonNullClassLoaderFactoryAfterInstantiatingWithNullClassLoaderFactoryReference() {
+        assertThat(service.getClassLoaderFactory(), is(notNullValue()));
+    }
+
+}

Added: trunk/dna-spi/src/main/java/org/jboss/dna/spi/graph/commands/impl/BasicCompositeCommand.java
===================================================================
--- trunk/dna-spi/src/main/java/org/jboss/dna/spi/graph/commands/impl/BasicCompositeCommand.java	                        (rev 0)
+++ trunk/dna-spi/src/main/java/org/jboss/dna/spi/graph/commands/impl/BasicCompositeCommand.java	2008-06-30 21:45:21 UTC (rev 321)
@@ -0,0 +1,71 @@
+/*
+ * 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.spi.graph.commands.impl;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import org.jboss.dna.spi.graph.commands.CompositeCommand;
+import org.jboss.dna.spi.graph.commands.GraphCommand;
+
+/**
+ * @author Randall Hauch
+ */
+public class BasicCompositeCommand extends BasicGraphCommand implements CompositeCommand {
+
+    private final List<GraphCommand> commands = new ArrayList<GraphCommand>();
+
+    public BasicCompositeCommand() {
+        super();
+    }
+
+    public boolean isEmpty() {
+        return commands.isEmpty();
+    }
+
+    public int size() {
+        return commands.size();
+    }
+
+    public void add( GraphCommand command ) {
+        if (command != null) commands.add(command);
+    }
+
+    public GraphCommand getCommand( int index ) {
+        return commands.get(index);
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see java.lang.Iterable#iterator()
+     */
+    public Iterator<GraphCommand> iterator() {
+        return commands.iterator();
+    }
+
+    public BasicCompositeCommand clearCommands() {
+        this.commands.clear();
+        return this;
+    }
+
+}

Added: trunk/dna-spi/src/main/java/org/jboss/dna/spi/graph/connection/BasicExecutionEnvironment.java
===================================================================
--- trunk/dna-spi/src/main/java/org/jboss/dna/spi/graph/connection/BasicExecutionEnvironment.java	                        (rev 0)
+++ trunk/dna-spi/src/main/java/org/jboss/dna/spi/graph/connection/BasicExecutionEnvironment.java	2008-06-30 21:45:21 UTC (rev 321)
@@ -0,0 +1,78 @@
+/*
+ * 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.spi.graph.connection;
+
+import org.jboss.dna.common.util.ArgCheck;
+import org.jboss.dna.spi.graph.NamespaceRegistry;
+import org.jboss.dna.spi.graph.PropertyFactory;
+import org.jboss.dna.spi.graph.ValueFactories;
+import org.jboss.dna.spi.graph.impl.BasicNamespaceRegistry;
+import org.jboss.dna.spi.graph.impl.BasicPropertyFactory;
+import org.jboss.dna.spi.graph.impl.StandardValueFactories;
+
+/**
+ * @author Randall Hauch
+ */
+public class BasicExecutionEnvironment implements ExecutionEnvironment {
+
+    private final PropertyFactory propertyFactory;
+    private final ValueFactories valueFactories;
+    private final NamespaceRegistry namespaceRegistry;
+
+    public BasicExecutionEnvironment() {
+        this(new BasicNamespaceRegistry());
+    }
+
+    public BasicExecutionEnvironment( NamespaceRegistry namespaceRegistry ) {
+        this(namespaceRegistry, null, null);
+    }
+
+    public BasicExecutionEnvironment( NamespaceRegistry namespaceRegistry,
+                                      ValueFactories valueFactories,
+                                      PropertyFactory propertyFactory ) {
+        ArgCheck.isNotNull(namespaceRegistry, "namespace registry");
+        this.namespaceRegistry = namespaceRegistry;
+        this.valueFactories = valueFactories != null ? valueFactories : new StandardValueFactories(this.namespaceRegistry);
+        this.propertyFactory = propertyFactory != null ? propertyFactory : new BasicPropertyFactory(this.valueFactories);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public NamespaceRegistry getNamespaceRegistry() {
+        return this.namespaceRegistry;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public ValueFactories getValueFactories() {
+        return this.valueFactories;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public PropertyFactory getPropertyFactory() {
+        return this.propertyFactory;
+    }
+}

Added: trunk/dna-spi/src/main/java/org/jboss/dna/spi/graph/connection/ExecutionEnvironments.java
===================================================================
--- trunk/dna-spi/src/main/java/org/jboss/dna/spi/graph/connection/ExecutionEnvironments.java	                        (rev 0)
+++ trunk/dna-spi/src/main/java/org/jboss/dna/spi/graph/connection/ExecutionEnvironments.java	2008-06-30 21:45:21 UTC (rev 321)
@@ -0,0 +1,184 @@
+/*
+ * 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.spi.graph.connection;
+
+import org.jboss.dna.common.util.ArgCheck;
+import org.jboss.dna.spi.graph.NameFactory;
+import org.jboss.dna.spi.graph.NamespaceRegistry;
+import org.jboss.dna.spi.graph.PathFactory;
+import org.jboss.dna.spi.graph.PropertyFactory;
+import org.jboss.dna.spi.graph.ValueFactories;
+import org.jboss.dna.spi.graph.impl.DelegatingValueFactories;
+
+/**
+ * Utility methods for creating various execution environments with replacement factories or components.
+ * 
+ * @author Randall Hauch
+ */
+public class ExecutionEnvironments {
+
+    /**
+     * Create an environment that can be used to replace the supplied environment but that uses the supplied path factory.
+     * 
+     * @param env the base environment
+     * @param pathFactory the new path factory
+     * @return the new execution environment
+     * @throws IllegalArgumentException if the environment or factory references are null
+     */
+    public static ExecutionEnvironment replace( ExecutionEnvironment env,
+                                                PathFactory pathFactory ) {
+        ArgCheck.isNotNull(env, "env");
+        ArgCheck.isNotNull(pathFactory, "pathFactory");
+        return new DelegatingExecutionEnvironment(env, null, null, null, pathFactory);
+    }
+
+    /**
+     * Create an environment that can be used to replace the supplied environment but that uses the supplied name factory.
+     * 
+     * @param env the base environment
+     * @param nameFactory the new name factory
+     * @return the new execution environment
+     * @throws IllegalArgumentException if the environment or factory references are null
+     */
+    public static ExecutionEnvironment replace( ExecutionEnvironment env,
+                                                NameFactory nameFactory ) {
+        ArgCheck.isNotNull(env, "env");
+        ArgCheck.isNotNull(nameFactory, "nameFactory");
+        return new DelegatingExecutionEnvironment(env, null, null, nameFactory, null);
+    }
+
+    /**
+     * Create an environment that can be used to replace the supplied environment but that uses the supplied name and path
+     * factories.
+     * 
+     * @param env the base environment
+     * @param nameFactory the new name factory
+     * @param pathFactory the new path factory
+     * @return the new execution environment
+     * @throws IllegalArgumentException if the environment or factory references are null
+     */
+    public static ExecutionEnvironment replace( ExecutionEnvironment env,
+                                                NameFactory nameFactory,
+                                                PathFactory pathFactory ) {
+        ArgCheck.isNotNull(env, "env");
+        ArgCheck.isNotNull(nameFactory, "nameFactory");
+        ArgCheck.isNotNull(pathFactory, "pathFactory");
+        return new DelegatingExecutionEnvironment(env, null, null, nameFactory, pathFactory);
+    }
+
+    /**
+     * Create an environment that can be used to replace the supplied environment but that uses the supplied namespace registry.
+     * 
+     * @param env the base environment
+     * @param namespaceRegistry the new namespace registry
+     * @return the new execution environment
+     * @throws IllegalArgumentException if the environment or registry references are null
+     */
+    public static ExecutionEnvironment replace( ExecutionEnvironment env,
+                                                NamespaceRegistry namespaceRegistry ) {
+        ArgCheck.isNotNull(env, "env");
+        ArgCheck.isNotNull(namespaceRegistry, "namespaceRegistry");
+        return new DelegatingExecutionEnvironment(env, namespaceRegistry, null, null, null);
+    }
+
+    protected static class DelegatingExecutionEnvironment implements ExecutionEnvironment {
+
+        private final ExecutionEnvironment delegate;
+        private final NamespaceRegistry newNamespaceRegistry;
+        private final PropertyFactory newPropertyFactory;
+        private final ValueFactories newValueFactories;
+
+        public DelegatingExecutionEnvironment( ExecutionEnvironment delegate,
+                                               NamespaceRegistry newRegistry,
+                                               PropertyFactory newPropertyFactory,
+                                               ValueFactories newValueFactories ) {
+            assert delegate != null;
+            this.delegate = delegate;
+            this.newNamespaceRegistry = newRegistry;
+            this.newPropertyFactory = newPropertyFactory;
+            this.newValueFactories = newValueFactories;
+        }
+
+        public DelegatingExecutionEnvironment( ExecutionEnvironment delegate,
+                                               NamespaceRegistry newRegistry,
+                                               PropertyFactory newPropertyFactory,
+                                               final NameFactory newNameFactory,
+                                               final PathFactory newPathFactory ) {
+            assert delegate != null;
+            this.delegate = delegate;
+            this.newNamespaceRegistry = newRegistry;
+            this.newPropertyFactory = newPropertyFactory;
+            final PathFactory pathFactory = newPathFactory != null ? newPathFactory : delegate.getValueFactories().getPathFactory();
+            final NameFactory nameFactory = newNameFactory != null ? newNameFactory : delegate.getValueFactories().getNameFactory();
+            this.newValueFactories = newPathFactory == null ? null : new DelegatingValueFactories(delegate.getValueFactories()) {
+
+                @Override
+                public PathFactory getPathFactory() {
+                    return pathFactory;
+                }
+
+                @Override
+                public NameFactory getNameFactory() {
+                    return nameFactory;
+                }
+            };
+        }
+
+        /**
+         * {@inheritDoc}
+         * 
+         * @see org.jboss.dna.spi.graph.connection.ExecutionEnvironment#getNamespaceRegistry()
+         */
+        public NamespaceRegistry getNamespaceRegistry() {
+            if (newNamespaceRegistry != null) return newNamespaceRegistry;
+            return delegate.getNamespaceRegistry();
+        }
+
+        /**
+         * {@inheritDoc}
+         * 
+         * @see org.jboss.dna.spi.graph.connection.ExecutionEnvironment#getPropertyFactory()
+         */
+        public PropertyFactory getPropertyFactory() {
+            if (newPropertyFactory != null) return newPropertyFactory;
+            return delegate.getPropertyFactory();
+        }
+
+        /**
+         * {@inheritDoc}
+         * 
+         * @see org.jboss.dna.spi.graph.connection.ExecutionEnvironment#getValueFactories()
+         */
+        public ValueFactories getValueFactories() {
+            if (newValueFactories != null) return newValueFactories;
+            return delegate.getValueFactories();
+        }
+
+        /**
+         * @return delegate
+         */
+        protected ExecutionEnvironment getDelegate() {
+            return delegate;
+        }
+
+    }
+}

Added: trunk/dna-spi/src/main/java/org/jboss/dna/spi/graph/connection/RepositoryConnectionPool.java
===================================================================
--- trunk/dna-spi/src/main/java/org/jboss/dna/spi/graph/connection/RepositoryConnectionPool.java	                        (rev 0)
+++ trunk/dna-spi/src/main/java/org/jboss/dna/spi/graph/connection/RepositoryConnectionPool.java	2008-06-30 21:45:21 UTC (rev 321)
@@ -0,0 +1,111 @@
+/*
+ * 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.spi.graph.connection;
+
+import java.util.concurrent.TimeUnit;
+
+/**
+ * @author Randall Hauch
+ */
+public interface RepositoryConnectionPool extends RepositoryConnectionFactory {
+
+    /**
+     * Initiates an orderly shutdown in which connections that are currently in use are allowed to be used and closed as normal,
+     * but no new connections will be created. Invocation has no additional effect if already shut down.
+     * <p>
+     * Once the pool has been shutdown, it may not be used to {@link #getConnection() get connections}.
+     * </p>
+     * 
+     * @throws SecurityException if a security manager exists and shutting down this pool may manipulate threads that the caller
+     *         is not permitted to modify because it does not hold {@link java.lang.RuntimePermission}<tt>("modifyThread")</tt>,
+     *         or the security manager's <tt>checkAccess</tt> method denies access.
+     * @see #shutdownNow()
+     */
+    void shutdown();
+
+    /**
+     * Attempts to close all connections, including those connections currently in use, and prevent the use of other connections.
+     * 
+     * @throws SecurityException if a security manager exists and shutting down this pool may manipulate threads that the caller
+     *         is not permitted to modify because it does not hold {@link java.lang.RuntimePermission}<tt>("modifyThread")</tt>,
+     *         or the security manager's <tt>checkAccess</tt> method denies access.
+     * @see #shutdown()
+     */
+    void shutdownNow();
+
+    /**
+     * Return whether this connection pool is running and is able to {@link #getConnection() provide connections}. Note that this
+     * method is effectively <code>!isShutdown()</code>.
+     * 
+     * @return true if this pool is running, or false otherwise
+     * @see #isShutdown()
+     * @see #isTerminated()
+     * @see #isTerminating()
+     */
+    boolean isRunning();
+
+    /**
+     * Return whether this connection pool is in the process of shutting down or has already been shut down. A result of
+     * <code>true</code> signals that the pool may no longer be used. Note that this method is effectively
+     * <code>!isRunning()</code>.
+     * 
+     * @return true if this pool has been shut down, or false otherwise
+     * @see #isShutdown()
+     * @see #isTerminated()
+     * @see #isTerminating()
+     */
+    boolean isShutdown();
+
+    /**
+     * Returns true if this pool is in the process of terminating after {@link #shutdown()} or {@link #shutdownNow()} has been
+     * called but has not completely terminated. This method may be useful for debugging. A return of <tt>true</tt> reported a
+     * sufficient period after shutdown may indicate that submitted tasks have ignored or suppressed interruption, causing this
+     * executor not to properly terminate.
+     * 
+     * @return true if terminating but not yet terminated, or false otherwise
+     * @see #isTerminated()
+     */
+    boolean isTerminating();
+
+    /**
+     * Return true if this pool has completed its termination and no longer has any open connections.
+     * 
+     * @return true if terminated, or false otherwise
+     * @see #isTerminating()
+     */
+    boolean isTerminated();
+
+    /**
+     * Method that can be called after {@link #shutdown()} or {@link #shutdownNow()} to wait until all connections in use at the
+     * time those methods were called have been closed normally. This method accepts a maximum time duration, after which it will
+     * return even if all connections have not been closed.
+     * 
+     * @param timeout the maximum time to wait for all connections to be closed and returned to the pool
+     * @param unit the time unit for <code>timeout</code>
+     * @return true if the pool was terminated in the supplied time (or was already terminated), or false if the timeout occurred
+     *         before all the connections were closed
+     * @throws InterruptedException if the thread was interrupted
+     */
+    boolean awaitTermination( long timeout,
+                              TimeUnit unit ) throws InterruptedException;
+
+}

Added: trunk/dna-spi/src/main/java/org/jboss/dna/spi/graph/impl/AbstractValueFactories.java
===================================================================
--- trunk/dna-spi/src/main/java/org/jboss/dna/spi/graph/impl/AbstractValueFactories.java	                        (rev 0)
+++ trunk/dna-spi/src/main/java/org/jboss/dna/spi/graph/impl/AbstractValueFactories.java	2008-06-30 21:45:21 UTC (rev 321)
@@ -0,0 +1,130 @@
+/*
+ * 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.spi.graph.impl;
+
+import java.util.Iterator;
+import org.jboss.dna.common.util.ArgCheck;
+import org.jboss.dna.spi.graph.PropertyType;
+import org.jboss.dna.spi.graph.ValueFactories;
+import org.jboss.dna.spi.graph.ValueFactory;
+
+/**
+ * Abstract implementation of {@link ValueFactories} that implements all the methods other than the <code>get*Factory()</code>
+ * methods. Subclasses can simply implement these methods and inherit the {@link #iterator()}, {@link #getValueFactory(Object)}
+ * and {@link #getValueFactory(PropertyType)} method implementations.
+ * 
+ * @author Randall Hauch
+ */
+public abstract class AbstractValueFactories implements ValueFactories {
+
+    /**
+     * <p>
+     * {@inheritDoc}
+     * </p>
+     * <p>
+     * This implementation always iterates over the instances return by the <code>get*Factory()</code> methods.
+     * </p>
+     */
+    public Iterator<ValueFactory<?>> iterator() {
+        return new ValueFactoryIterator();
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public ValueFactory<?> getValueFactory( PropertyType type ) {
+        ArgCheck.isNotNull(type, "type");
+        switch (type) {
+            case BINARY:
+                return getBinaryFactory();
+            case BOOLEAN:
+                return getBooleanFactory();
+            case DATE:
+                return getDateFactory();
+            case DECIMAL:
+                return getDecimalFactory();
+            case DOUBLE:
+                return getDoubleFactory();
+            case LONG:
+                return getLongFactory();
+            case NAME:
+                return getNameFactory();
+            case OBJECT:
+                return getObjectFactory();
+            case PATH:
+                return getPathFactory();
+            case REFERENCE:
+                return getReferenceFactory();
+            case STRING:
+                return getStringFactory();
+            case URI:
+                return getUriFactory();
+        }
+        return getObjectFactory();
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public ValueFactory<?> getValueFactory( Object prototype ) {
+        ArgCheck.isNotNull(prototype, "prototype");
+        PropertyType inferredType = PropertyType.discoverType(prototype);
+        assert inferredType != null;
+        return getValueFactory(inferredType);
+    }
+
+    protected class ValueFactoryIterator implements Iterator<ValueFactory<?>> {
+        private final Iterator<PropertyType> propertyTypeIter = PropertyType.iterator();
+
+        protected ValueFactoryIterator() {
+        }
+
+        /**
+         * {@inheritDoc}
+         * 
+         * @see java.util.Iterator#hasNext()
+         */
+        public boolean hasNext() {
+            return propertyTypeIter.hasNext();
+        }
+
+        /**
+         * {@inheritDoc}
+         * 
+         * @see java.util.Iterator#next()
+         */
+        public ValueFactory<?> next() {
+            PropertyType nextType = propertyTypeIter.next();
+            return getValueFactory(nextType);
+        }
+
+        /**
+         * {@inheritDoc}
+         * 
+         * @see java.util.Iterator#remove()
+         */
+        public void remove() {
+            throw new UnsupportedOperationException();
+        }
+    }
+
+}

Added: trunk/dna-spi/src/main/java/org/jboss/dna/spi/graph/impl/DelegatingValueFactories.java
===================================================================
--- trunk/dna-spi/src/main/java/org/jboss/dna/spi/graph/impl/DelegatingValueFactories.java	                        (rev 0)
+++ trunk/dna-spi/src/main/java/org/jboss/dna/spi/graph/impl/DelegatingValueFactories.java	2008-06-30 21:45:21 UTC (rev 321)
@@ -0,0 +1,94 @@
+/*
+ * 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.spi.graph.impl;
+
+import java.math.BigDecimal;
+import java.net.URI;
+import org.jboss.dna.spi.graph.Binary;
+import org.jboss.dna.spi.graph.DateTimeFactory;
+import org.jboss.dna.spi.graph.NameFactory;
+import org.jboss.dna.spi.graph.PathFactory;
+import org.jboss.dna.spi.graph.Reference;
+import org.jboss.dna.spi.graph.ValueFactories;
+import org.jboss.dna.spi.graph.ValueFactory;
+
+/**
+ * @author Randall Hauch
+ */
+public class DelegatingValueFactories extends AbstractValueFactories {
+
+    private final ValueFactories delegate;
+
+    protected DelegatingValueFactories( ValueFactories delegate ) {
+        assert delegate != null;
+        this.delegate = delegate;
+    }
+
+    public ValueFactory<Binary> getBinaryFactory() {
+        return delegate.getBinaryFactory();
+    }
+
+    public ValueFactory<Boolean> getBooleanFactory() {
+        return delegate.getBooleanFactory();
+    }
+
+    public DateTimeFactory getDateFactory() {
+        return delegate.getDateFactory();
+    }
+
+    public ValueFactory<BigDecimal> getDecimalFactory() {
+        return delegate.getDecimalFactory();
+    }
+
+    public ValueFactory<Double> getDoubleFactory() {
+        return delegate.getDoubleFactory();
+    }
+
+    public ValueFactory<Long> getLongFactory() {
+        return delegate.getLongFactory();
+    }
+
+    public NameFactory getNameFactory() {
+        return delegate.getNameFactory();
+    }
+
+    public ValueFactory<Object> getObjectFactory() {
+        return delegate.getObjectFactory();
+    }
+
+    public PathFactory getPathFactory() {
+        return delegate.getPathFactory();
+    }
+
+    public ValueFactory<Reference> getReferenceFactory() {
+        return delegate.getReferenceFactory();
+    }
+
+    public ValueFactory<String> getStringFactory() {
+        return delegate.getStringFactory();
+    }
+
+    public ValueFactory<URI> getUriFactory() {
+        return delegate.getUriFactory();
+    }
+
+}




More information about the dna-commits mailing list