DNA SVN: r375 - in trunk: connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/executor and 8 other directories.
by dna-commits@lists.jboss.org
Author: rhauch
Date: 2008-07-28 17:51:05 -0400 (Mon, 28 Jul 2008)
New Revision: 375
Added:
trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/contribution/MultiChildContribution.java
trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/contribution/MultiPropertyContribution.java
trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/contribution/NonEmptyContribution.java
trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/contribution/OneChildContribution.java
trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/contribution/OnePropertyContribution.java
trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/contribution/ThreePropertyContribution.java
trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/contribution/TwoPropertyContribution.java
trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/merge/FiveContributionMergePlan.java
trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/merge/FourContributionMergePlan.java
trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/merge/OneContributionMergePlan.java
trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/merge/ThreeContributionMergePlan.java
trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/merge/TwoContributionMergePlan.java
Removed:
trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/contribution/AbstractContribution.java
trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/contribution/PropertyContribution.java
trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/merge/BasicMergePlan.java
trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/merge/DoubleContributionMergePlan.java
trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/merge/SingleContributionMergePlan.java
trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/merge/TripleContributionMergePlan.java
Modified:
trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/contribution/Contribution.java
trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/contribution/EmptyContribution.java
trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/contribution/NodeContribution.java
trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/executor/ActsOnProjectedPathCommand.java
trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/executor/FederatingCommandExecutor.java
trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/merge/MergePlan.java
trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/merge/MultipleContributionMergePlan.java
trunk/connectors/dna-connector-inmemory/src/main/java/org/jboss/dna/connector/inmemory/InMemoryRepository.java
trunk/connectors/dna-connector-jbosscache/src/main/java/org/jboss/dna/connector/jbosscache/JBossCacheConnection.java
trunk/dna-spi/src/main/java/org/jboss/dna/spi/graph/Path.java
trunk/dna-spi/src/main/java/org/jboss/dna/spi/graph/PathNotFoundException.java
trunk/dna-spi/src/main/java/org/jboss/dna/spi/graph/commands/NodeConflictBehavior.java
trunk/dna-spi/src/main/java/org/jboss/dna/spi/graph/commands/impl/BasicCreateNodeCommand.java
trunk/dna-spi/src/main/java/org/jboss/dna/spi/graph/impl/BasicPath.java
trunk/dna-spi/src/test/java/org/jboss/dna/spi/graph/impl/BasicPathTest.java
Log:
More work on the federated connector.
Deleted: trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/contribution/AbstractContribution.java
===================================================================
--- trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/contribution/AbstractContribution.java 2008-07-28 15:00:27 UTC (rev 374)
+++ trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/contribution/AbstractContribution.java 2008-07-28 21:51:05 UTC (rev 375)
@@ -1,132 +0,0 @@
-/*
- * 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.connector.federation.contribution;
-
-import java.util.Collections;
-import java.util.List;
-import java.util.Map;
-import org.jboss.dna.spi.graph.DateTime;
-import org.jboss.dna.spi.graph.Name;
-import org.jboss.dna.spi.graph.Property;
-import org.jboss.dna.spi.graph.Path.Segment;
-
-/**
- * @author Randall Hauch
- */
-public abstract class AbstractContribution implements Contribution {
-
- /**
- * This is the first version of this class. See the documentation of BasicMergePlan.serialVersionUID.
- */
- private static final long serialVersionUID = 1L;
-
- protected static final List<Segment> EMPTY_CHILDREN = Collections.emptyList();
- protected static final Map<Name, Property> EMPTY_PROPERTIES = Collections.emptyMap();
-
- private final String sourceName;
- private DateTime expirationTimeInUtc;
-
- /**
- * Create a contribution for the source with the supplied name.
- *
- * @param sourceName the name of the source, which may not be null or blank
- */
- protected AbstractContribution( String sourceName ) {
- assert sourceName != null && sourceName.trim().length() != 0;
- this.sourceName = sourceName;
- }
-
- /**
- * {@inheritDoc}
- */
- public String getSourceName() {
- return this.sourceName;
- }
-
- /**
- * {@inheritDoc}
- */
- public List<Segment> getChildren() {
- return EMPTY_CHILDREN;
- }
-
- /**
- * {@inheritDoc}
- */
- public Map<Name, Property> getProperties() {
- return EMPTY_PROPERTIES;
- }
-
- /**
- * {@inheritDoc}
- *
- * @see org.jboss.dna.connector.federation.contribution.Contribution#isExpired(org.jboss.dna.spi.graph.DateTime)
- */
- public boolean isExpired( DateTime utcTime ) {
- assert utcTime != null;
- assert utcTime.toUtcTimeZone().equals(utcTime); // check that it is passed UTC time
- return !expirationTimeInUtc.isAfter(utcTime);
- }
-
- /**
- * {@inheritDoc}
- */
- public DateTime getExpirationTimeInUtc() {
- return this.expirationTimeInUtc;
- }
-
- /**
- * @param expirationTimeInUtc Sets expirationTimeInUtc to the specified value.
- */
- public void setExpirationTimeInUtc( DateTime expirationTimeInUtc ) {
- this.expirationTimeInUtc = expirationTimeInUtc;
- }
-
- /**
- * {@inheritDoc}
- * <p>
- * This implementation returns the hash code of the {@link #getSourceName() source name}, and is compatible with the
- * implementation of {@link #equals(Object)}.
- * </p>
- */
- @Override
- public int hashCode() {
- return this.sourceName.hashCode();
- }
-
- /**
- * {@inheritDoc}
- * <p>
- * This implementation only compares the {@link #getSourceName() source name}.
- * </p>
- */
- @Override
- public boolean equals( Object obj ) {
- if (obj == this) return true;
- if (obj instanceof AbstractContribution) {
- AbstractContribution that = (AbstractContribution)obj;
- return this.getSourceName().equals(that.getSourceName());
- }
- return false;
- }
-
-}
Modified: trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/contribution/Contribution.java
===================================================================
--- trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/contribution/Contribution.java 2008-07-28 15:00:27 UTC (rev 374)
+++ trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/contribution/Contribution.java 2008-07-28 21:51:05 UTC (rev 375)
@@ -22,9 +22,10 @@
package org.jboss.dna.connector.federation.contribution;
import java.io.Serializable;
-import java.util.List;
-import java.util.Map;
-import net.jcip.annotations.NotThreadSafe;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.NoSuchElementException;
+import net.jcip.annotations.Immutable;
import org.jboss.dna.spi.graph.DateTime;
import org.jboss.dna.spi.graph.Name;
import org.jboss.dna.spi.graph.Path;
@@ -39,22 +40,131 @@
*
* @author Randall Hauch
*/
-@NotThreadSafe
-public interface Contribution extends Serializable {
+@Immutable
+public abstract class Contribution implements Serializable {
/**
+ * Create an empty contribution from the named source.
+ *
+ * @param sourceName the name of the source, which may not be null or blank
+ * @return the contribution
+ */
+ public static Contribution create( String sourceName ) {
+ return new EmptyContribution(sourceName);
+ }
+
+ /**
+ * Create a contribution of a single property from the named source.
+ *
+ * @param sourceName the name of the source, which may not be null or blank
+ * @param pathInSource the path in the source for this contributed information; may not be null
+ * @param property the property from the source; may not be null
+ * @return the contribution
+ */
+ public static Contribution create( String sourceName,
+ Path pathInSource,
+ Property property ) {
+ if (property == null) {
+ return new EmptyContribution(sourceName);
+ }
+ return new OnePropertyContribution(sourceName, pathInSource, property);
+ }
+
+ /**
+ * Create a contribution of a single child from the named source.
+ *
+ * @param sourceName the name of the source, which may not be null or blank
+ * @param pathInSource the path in the source for this contributed information; may not be null
+ * @param child the child from the source; may not be null or empty
+ * @return the contribution
+ */
+ public static Contribution create( String sourceName,
+ Path pathInSource,
+ Segment child ) {
+ if (child == null) {
+ return new EmptyContribution(sourceName);
+ }
+ return new OneChildContribution(sourceName, pathInSource, child);
+ }
+
+ /**
+ * Create a contribution of the supplied properties and children from the named source.
+ *
+ * @param sourceName the name of the source, which may not be null or blank
+ * @param pathInSource the path in the source for this contributed information; may not be null
+ * @param properties the properties from the source; may not be null
+ * @param children the children from the source; may not be null or empty
+ * @return the contribution
+ */
+ public static Contribution create( String sourceName,
+ Path pathInSource,
+ Collection<Property> properties,
+ Collection<Segment> children ) {
+ if (properties == null || properties.isEmpty()) {
+ // There are no properties ...
+ if (children == null || children.isEmpty()) {
+ return new EmptyContribution(sourceName);
+ }
+ if (children.size() == 1) {
+ return new OneChildContribution(sourceName, pathInSource, children.iterator().next());
+ }
+ return new MultiChildContribution(sourceName, pathInSource, children);
+ }
+ // There are some properties ...
+ if (children == null || children.isEmpty()) {
+ // There are no children ...
+ switch (properties.size()) {
+ case 1:
+ return new OnePropertyContribution(sourceName, pathInSource, properties.iterator().next());
+ case 2:
+ Iterator<Property> iter = properties.iterator();
+ return new TwoPropertyContribution(sourceName, pathInSource, iter.next(), iter.next());
+ case 3:
+ Iterator<Property> iter3 = properties.iterator();
+ return new ThreePropertyContribution(sourceName, pathInSource, iter3.next(), iter3.next(), iter3.next());
+ }
+ return new MultiPropertyContribution(sourceName, pathInSource, properties);
+ }
+ // There are some properties AND some children ...
+ return new NodeContribution(sourceName, pathInSource, properties, children);
+ }
+
+ /**
+ * This is the first version of this class. See the documentation of BasicMergePlan.serialVersionUID.
+ */
+ private static final long serialVersionUID = 1L;
+
+ protected static final Iterator<Property> EMPTY_PROPERTY_ITERATOR = new EmptyIterator<Property>();
+ protected static final Iterator<Segment> EMPTY_CHILDREN_ITERATOR = new EmptyIterator<Segment>();
+
+ private final String sourceName;
+ private DateTime expirationTimeInUtc;
+
+ /**
+ * Create a contribution for the source with the supplied name and path.
+ *
+ * @param sourceName the name of the source, which may not be null or blank
+ */
+ protected Contribution( String sourceName ) {
+ assert sourceName != null && sourceName.trim().length() != 0;
+ this.sourceName = sourceName;
+ }
+
+ /**
* Get the name of the source that made this contribution.
*
* @return the name of the contributing source
*/
- public String getSourceName();
+ public String getSourceName() {
+ return this.sourceName;
+ }
/**
* Get the source-specific path of this information.
*
* @return the path as known to the source, or null for {@link EmptyContribution}
*/
- public Path getPathInSource();
+ public abstract Path getPathInSource();
/**
* Determine whether this contribution has expired given the supplied current time.
@@ -62,26 +172,307 @@
* @param utcTime the current time expressed in UTC; may not be null
* @return true if at least one contribution has expired, or false otherwise
*/
- public boolean isExpired( DateTime utcTime );
+ public boolean isExpired( DateTime utcTime ) {
+ assert utcTime != null;
+ assert utcTime.toUtcTimeZone().equals(utcTime); // check that it is passed UTC time
+ return !expirationTimeInUtc.isAfter(utcTime);
+ }
/**
* Get the expiration time, already in UTC.
*
* @return the expiration time in UTC
*/
- public DateTime getExpirationTimeInUtc();
+ public DateTime getExpirationTimeInUtc() {
+ return this.expirationTimeInUtc;
+ }
/**
- * Get the properties that make up this contribution. This map is immutable.
+ * Get the properties that are in this contribution. This resulting iterator does not support {@link Iterator#remove()
+ * removal}.
*
- * @return the map of properties; never null
+ * @return the properties; never null
*/
- public Map<Name, Property> getProperties();
+ public Iterator<Property> getProperties() {
+ return EMPTY_PROPERTY_ITERATOR;
+ }
/**
- * Get the children that make up this contribution. This list is immutable.
+ * Get the number of properties that are in this contribution.
*
- * @return the list of children; never null
+ * @return the number of properties
*/
- public List<Segment> getChildren();
+ public int getPropertyCount() {
+ return 0;
+ }
+
+ /**
+ * Get the contributed property with the supplied name.
+ *
+ * @param name the name of the property
+ * @return the contributed property that matches the name, or null if no such property is in the contribution
+ */
+ public Property getProperty( Name name ) {
+ return null;
+ }
+
+ /**
+ * Get the children that make up this contribution. This resulting iterator does not support {@link Iterator#remove() removal}
+ * .
+ *
+ * @return the children; never null
+ */
+ public Iterator<Segment> getChildren() {
+ return EMPTY_CHILDREN_ITERATOR;
+ }
+
+ /**
+ * Get the number of children that make up this contribution.
+ *
+ * @return the number of children
+ */
+ public int getChildrenCount() {
+ return 0;
+ }
+
+ /**
+ * {@inheritDoc}
+ * <p>
+ * This implementation returns the hash code of the {@link #getSourceName() source name}, and is compatible with the
+ * implementation of {@link #equals(Object)}.
+ * </p>
+ */
+ @Override
+ public int hashCode() {
+ return this.sourceName.hashCode();
+ }
+
+ /**
+ * {@inheritDoc}
+ * <p>
+ * This implementation only compares the {@link #getSourceName() source name}.
+ * </p>
+ */
+ @Override
+ public boolean equals( Object obj ) {
+ if (obj == this) return true;
+ if (obj instanceof Contribution) {
+ Contribution that = (Contribution)obj;
+ if (!this.getSourceName().equals(that.getSourceName())) return false;
+ return true;
+ }
+ return false;
+ }
+
+ protected static class ImmutableIterator<T> implements Iterator<T> {
+ private final Iterator<T> iter;
+
+ protected ImmutableIterator( Iterator<T> iter ) {
+ this.iter = iter;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see java.util.Iterator#hasNext()
+ */
+ public boolean hasNext() {
+ return iter.hasNext();
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see java.util.Iterator#next()
+ */
+ public T next() {
+ return iter.next();
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see java.util.Iterator#remove()
+ */
+ public void remove() {
+ throw new UnsupportedOperationException();
+ }
+ }
+
+ protected static class EmptyIterator<T> implements Iterator<T> {
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see java.util.Iterator#hasNext()
+ */
+ public boolean hasNext() {
+ return false;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see java.util.Iterator#next()
+ */
+ public T next() {
+ throw new NoSuchElementException();
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see java.util.Iterator#remove()
+ */
+ public void remove() {
+ throw new UnsupportedOperationException();
+ }
+
+ }
+
+ protected static class OneValueIterator<T> implements Iterator<T> {
+
+ private final T value;
+ private boolean next = true;
+
+ protected OneValueIterator( T value ) {
+ this.value = value;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see java.util.Iterator#hasNext()
+ */
+ public boolean hasNext() {
+ return next;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see java.util.Iterator#next()
+ */
+ public T next() {
+ if (!next) {
+ next = false;
+ return value;
+ }
+ throw new NoSuchElementException();
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see java.util.Iterator#remove()
+ */
+ public void remove() {
+ throw new UnsupportedOperationException();
+ }
+
+ }
+
+ protected static class TwoValueIterator<T> implements Iterator<T> {
+
+ private final T value1;
+ private final T value2;
+ private int next = 2;
+
+ protected TwoValueIterator( T value1,
+ T value2 ) {
+ this.value1 = value1;
+ this.value2 = value2;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see java.util.Iterator#hasNext()
+ */
+ public boolean hasNext() {
+ return next > 0;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see java.util.Iterator#next()
+ */
+ public T next() {
+ if (next == 2) {
+ next = 1;
+ return value1;
+ }
+ if (next == 1) {
+ next = 0;
+ return value2;
+ }
+ throw new NoSuchElementException();
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see java.util.Iterator#remove()
+ */
+ public void remove() {
+ throw new UnsupportedOperationException();
+ }
+ }
+
+ protected static class ThreeValueIterator<T> implements Iterator<T> {
+
+ private final T value1;
+ private final T value2;
+ private final T value3;
+ private int next = 3;
+
+ protected ThreeValueIterator( T value1,
+ T value2,
+ T value3 ) {
+ this.value1 = value1;
+ this.value2 = value2;
+ this.value3 = value3;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see java.util.Iterator#hasNext()
+ */
+ public boolean hasNext() {
+ return next > 0;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see java.util.Iterator#next()
+ */
+ public T next() {
+ if (next == 3) {
+ next = 2;
+ return value1;
+ }
+ if (next == 2) {
+ next = 1;
+ return value2;
+ }
+ if (next == 1) {
+ next = 0;
+ return value3;
+ }
+ throw new NoSuchElementException();
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see java.util.Iterator#remove()
+ */
+ public void remove() {
+ throw new UnsupportedOperationException();
+ }
+
+ }
}
Modified: trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/contribution/EmptyContribution.java
===================================================================
--- trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/contribution/EmptyContribution.java 2008-07-28 15:00:27 UTC (rev 374)
+++ trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/contribution/EmptyContribution.java 2008-07-28 21:51:05 UTC (rev 375)
@@ -21,6 +21,7 @@
*/
package org.jboss.dna.connector.federation.contribution;
+import net.jcip.annotations.Immutable;
import org.jboss.dna.spi.graph.Path;
/**
@@ -33,10 +34,11 @@
*
* @author Randall Hauch
*/
-public class EmptyContribution extends AbstractContribution {
+@Immutable
+public class EmptyContribution extends Contribution {
/**
- * This is the first version of this class. See the documentation of BasicMergePlan.serialVersionUID.
+ * This is the first version of this class. See the documentation of MergePlan.serialVersionUID.
*/
private static final long serialVersionUID = 1L;
@@ -54,8 +56,22 @@
*
* @see org.jboss.dna.connector.federation.contribution.Contribution#getPathInSource()
*/
+ @Override
public Path getPathInSource() {
return null;
}
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public boolean equals( Object obj ) {
+ if (obj == this) return true;
+ if (obj instanceof EmptyContribution) {
+ EmptyContribution that = (EmptyContribution)obj;
+ if (!this.getSourceName().equals(that.getSourceName())) return false;
+ return true;
+ }
+ return false;
+ }
}
Added: trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/contribution/MultiChildContribution.java
===================================================================
--- trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/contribution/MultiChildContribution.java (rev 0)
+++ trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/contribution/MultiChildContribution.java 2008-07-28 21:51:05 UTC (rev 375)
@@ -0,0 +1,82 @@
+/*
+ * 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.connector.federation.contribution;
+
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import net.jcip.annotations.Immutable;
+import org.jboss.dna.spi.graph.Path;
+import org.jboss.dna.spi.graph.Path.Segment;
+
+/**
+ * The contribution of a source to the information for a single federated node.
+ *
+ * @author Randall Hauch
+ */
+@Immutable
+public class MultiChildContribution extends NonEmptyContribution {
+
+ /**
+ * This is the first version of this class. See the documentation of MergePlan.serialVersionUID.
+ */
+ private static final long serialVersionUID = 1L;
+
+ private List<Segment> children;
+
+ /**
+ * Create a contribution of children from the source with the supplied name.
+ *
+ * @param sourceName the name of the source, which may not be null or blank
+ * @param pathInSource the path in the source for this contributed information; may not be null
+ * @param children the children from the source; may not be null or empty
+ */
+ public MultiChildContribution( String sourceName,
+ Path pathInSource,
+ Iterable<Segment> children ) {
+ super(sourceName, pathInSource);
+ this.children = new LinkedList<Segment>();
+ for (Segment child : children) {
+ if (child != null) this.children.add(child);
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.jboss.dna.connector.federation.contribution.Contribution#getChildren()
+ */
+ @Override
+ public Iterator<Segment> getChildren() {
+ return new ImmutableIterator<Segment>(children.iterator());
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.jboss.dna.connector.federation.contribution.Contribution#getChildrenCount()
+ */
+ @Override
+ public int getChildrenCount() {
+ return children.size();
+ }
+}
Property changes on: trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/contribution/MultiChildContribution.java
___________________________________________________________________
Name: svn:mime-type
+ text/plain
Copied: trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/contribution/MultiPropertyContribution.java (from rev 369, trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/contribution/PropertyContribution.java)
===================================================================
--- trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/contribution/MultiPropertyContribution.java (rev 0)
+++ trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/contribution/MultiPropertyContribution.java 2008-07-28 21:51:05 UTC (rev 375)
@@ -0,0 +1,93 @@
+/*
+ * 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.connector.federation.contribution;
+
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+import net.jcip.annotations.Immutable;
+import org.jboss.dna.spi.graph.Name;
+import org.jboss.dna.spi.graph.Path;
+import org.jboss.dna.spi.graph.Property;
+
+/**
+ * The record of a source contributing only properties to a node.
+ *
+ * @author Randall Hauch
+ */
+@Immutable
+public class MultiPropertyContribution extends NonEmptyContribution {
+
+ /**
+ * This is the first version of this class. See the documentation of MergePlan.serialVersionUID.
+ */
+ private static final long serialVersionUID = 1L;
+
+ private final Map<Name, Property> properties;
+
+ /**
+ * Create a contribution of node properties from the source with the supplied name.
+ *
+ * @param sourceName the name of the source, which may not be null or blank
+ * @param pathInSource the path in the source for this contributed information; may not be null
+ * @param properties the properties from the source; may not be null
+ */
+ public MultiPropertyContribution( String sourceName,
+ Path pathInSource,
+ Iterable<Property> properties ) {
+ super(sourceName, pathInSource);
+ this.properties = new HashMap<Name, Property>();
+ for (Property property : properties) {
+ if (property != null) this.properties.put(property.getName(), property);
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.jboss.dna.connector.federation.contribution.Contribution#getProperties()
+ */
+ @Override
+ public Iterator<Property> getProperties() {
+ return new ImmutableIterator<Property>(this.properties.values().iterator());
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.jboss.dna.connector.federation.contribution.Contribution#getPropertyCount()
+ */
+ @Override
+ public int getPropertyCount() {
+ return this.properties.size();
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.jboss.dna.connector.federation.contribution.Contribution#getProperty(org.jboss.dna.spi.graph.Name)
+ */
+ @Override
+ public Property getProperty( Name name ) {
+ return this.properties.get(name);
+ }
+}
Modified: trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/contribution/NodeContribution.java
===================================================================
--- trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/contribution/NodeContribution.java 2008-07-28 15:00:27 UTC (rev 374)
+++ trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/contribution/NodeContribution.java 2008-07-28 21:51:05 UTC (rev 375)
@@ -21,27 +21,24 @@
*/
package org.jboss.dna.connector.federation.contribution;
-import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.LinkedList;
import java.util.List;
-import net.jcip.annotations.NotThreadSafe;
+import net.jcip.annotations.Immutable;
import org.jboss.dna.spi.graph.Path;
import org.jboss.dna.spi.graph.Property;
import org.jboss.dna.spi.graph.Path.Segment;
/**
* The contribution of a source to the information for a single federated node.
- * <p>
- * This class does return a mutable list of {@link #getChildren() children} and mutable map of {@link #getProperties() properties}
- * .
- * </p>
*
* @author Randall Hauch
*/
-@NotThreadSafe
-public class NodeContribution extends PropertyContribution {
+@Immutable
+public class NodeContribution extends MultiPropertyContribution {
/**
- * This is the first version of this class. See the documentation of BasicMergePlan.serialVersionUID.
+ * This is the first version of this class. See the documentation of MergePlan.serialVersionUID.
*/
private static final long serialVersionUID = 1L;
@@ -60,19 +57,29 @@
Iterable<Property> properties,
Iterable<Segment> children ) {
super(sourceName, pathInSource, properties);
- this.children = new ArrayList<Segment>(1);
+ this.children = new LinkedList<Segment>();
for (Segment child : children) {
- this.children.add(child);
+ if (child != null) this.children.add(child);
}
}
/**
- * Get the children that make up this contribution. This list is immutable.
+ * {@inheritDoc}
*
- * @return the list of children; never null
+ * @see org.jboss.dna.connector.federation.contribution.Contribution#getChildren()
*/
@Override
- public List<Segment> getChildren() {
- return this.children;
+ public Iterator<Segment> getChildren() {
+ return new ImmutableIterator<Segment>(children.iterator());
}
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.jboss.dna.connector.federation.contribution.Contribution#getChildrenCount()
+ */
+ @Override
+ public int getChildrenCount() {
+ return children.size();
+ }
}
Added: trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/contribution/NonEmptyContribution.java
===================================================================
--- trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/contribution/NonEmptyContribution.java (rev 0)
+++ trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/contribution/NonEmptyContribution.java 2008-07-28 21:51:05 UTC (rev 375)
@@ -0,0 +1,92 @@
+/*
+ * 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.connector.federation.contribution;
+
+import net.jcip.annotations.Immutable;
+import org.jboss.dna.common.util.HashCode;
+import org.jboss.dna.spi.graph.Path;
+
+/**
+ * The record of a non-empty source contribution from a single location within the source.
+ *
+ * @author Randall Hauch
+ */
+@Immutable
+public abstract class NonEmptyContribution extends Contribution {
+
+ /**
+ * This is the first version of this class. See the documentation of MergePlan.serialVersionUID.
+ */
+ private static final long serialVersionUID = 1L;
+
+ private final Path pathInSource;
+
+ /**
+ * Create a contribution of node properties from the source with the supplied name.
+ *
+ * @param sourceName the name of the source, which may not be null or blank
+ * @param pathInSource the path in the source for this contributed information; may not be null
+ */
+ protected NonEmptyContribution( String sourceName,
+ Path pathInSource ) {
+ super(sourceName);
+ assert pathInSource != null;
+ this.pathInSource = pathInSource;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.jboss.dna.connector.federation.contribution.Contribution#getPathInSource()
+ */
+ @Override
+ public Path getPathInSource() {
+ return pathInSource;
+ }
+
+ /**
+ * {@inheritDoc}
+ * <p>
+ * This implementation returns the hash code of the {@link #getSourceName() source name}, and is compatible with the
+ * implementation of {@link #equals(Object)}.
+ * </p>
+ */
+ @Override
+ public int hashCode() {
+ return HashCode.compute(this.getSourceName(), this.getPathInSource());
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public boolean equals( Object obj ) {
+ if (obj == this) return true;
+ if (obj instanceof NonEmptyContribution) {
+ NonEmptyContribution that = (NonEmptyContribution)obj;
+ if (!this.getSourceName().equals(that.getSourceName())) return false;
+ if (!this.getPathInSource().equals(that.getPathInSource())) return false;
+ return true;
+ }
+ return false;
+ }
+}
Property changes on: trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/contribution/NonEmptyContribution.java
___________________________________________________________________
Name: svn:mime-type
+ text/plain
Added: trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/contribution/OneChildContribution.java
===================================================================
--- trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/contribution/OneChildContribution.java (rev 0)
+++ trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/contribution/OneChildContribution.java 2008-07-28 21:51:05 UTC (rev 375)
@@ -0,0 +1,79 @@
+/*
+ * 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.connector.federation.contribution;
+
+import java.util.Iterator;
+import net.jcip.annotations.Immutable;
+import org.jboss.dna.spi.graph.Path;
+import org.jboss.dna.spi.graph.Path.Segment;
+
+/**
+ * The record of a source contributing only properties to a node.
+ *
+ * @author Randall Hauch
+ */
+@Immutable
+public class OneChildContribution extends NonEmptyContribution {
+
+ /**
+ * This is the first version of this class. See the documentation of MergePlan.serialVersionUID.
+ */
+ private static final long serialVersionUID = 1L;
+
+ private final Segment child;
+
+ /**
+ * Create a contribution of node properties from the source with the supplied name.
+ *
+ * @param sourceName the name of the source, which may not be null or blank
+ * @param pathInSource the path in the source for this contributed information; may not be null
+ * @param child the child contributed from the source; may not be null
+ */
+ public OneChildContribution( String sourceName,
+ Path pathInSource,
+ Segment child ) {
+ super(sourceName, pathInSource);
+ assert child != null;
+ this.child = child;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.jboss.dna.connector.federation.contribution.Contribution#getChildren()
+ */
+ @Override
+ public Iterator<Segment> getChildren() {
+ return new OneValueIterator<Segment>(child);
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.jboss.dna.connector.federation.contribution.Contribution#getChildrenCount()
+ */
+ @Override
+ public int getChildrenCount() {
+ return 1;
+ }
+
+}
Property changes on: trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/contribution/OneChildContribution.java
___________________________________________________________________
Name: svn:mime-type
+ text/plain
Added: trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/contribution/OnePropertyContribution.java
===================================================================
--- trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/contribution/OnePropertyContribution.java (rev 0)
+++ trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/contribution/OnePropertyContribution.java 2008-07-28 21:51:05 UTC (rev 375)
@@ -0,0 +1,91 @@
+/*
+ * 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.connector.federation.contribution;
+
+import java.util.Iterator;
+import net.jcip.annotations.Immutable;
+import org.jboss.dna.spi.graph.Name;
+import org.jboss.dna.spi.graph.Path;
+import org.jboss.dna.spi.graph.Property;
+
+/**
+ * The record of a source contributing only properties to a node.
+ *
+ * @author Randall Hauch
+ */
+@Immutable
+public class OnePropertyContribution extends NonEmptyContribution {
+
+ /**
+ * This is the first version of this class. See the documentation of MergePlan.serialVersionUID.
+ */
+ private static final long serialVersionUID = 1L;
+
+ private final Property property;
+
+ /**
+ * Create a contribution of node properties from the source with the supplied name.
+ *
+ * @param sourceName the name of the source, which may not be null or blank
+ * @param pathInSource the path in the source for this contributed information; may not be null
+ * @param property the property from the source; may not be null
+ */
+ public OnePropertyContribution( String sourceName,
+ Path pathInSource,
+ Property property ) {
+ super(sourceName, pathInSource);
+ assert property != null;
+ assert property.isEmpty() == false;
+ this.property = property;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.jboss.dna.connector.federation.contribution.Contribution#getProperties()
+ */
+ @Override
+ public Iterator<Property> getProperties() {
+ return new OneValueIterator<Property>(property);
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.jboss.dna.connector.federation.contribution.Contribution#getPropertyCount()
+ */
+ @Override
+ public int getPropertyCount() {
+ return 1;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.jboss.dna.connector.federation.contribution.Contribution#getProperty(org.jboss.dna.spi.graph.Name)
+ */
+ @Override
+ public Property getProperty( Name name ) {
+ return this.property.getName().equals(name) ? property : null;
+ }
+
+}
Property changes on: trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/contribution/OnePropertyContribution.java
___________________________________________________________________
Name: svn:mime-type
+ text/plain
Deleted: trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/contribution/PropertyContribution.java
===================================================================
--- trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/contribution/PropertyContribution.java 2008-07-28 15:00:27 UTC (rev 374)
+++ trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/contribution/PropertyContribution.java 2008-07-28 21:51:05 UTC (rev 375)
@@ -1,84 +0,0 @@
-/*
- * 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.connector.federation.contribution;
-
-import java.util.HashMap;
-import java.util.Map;
-import org.jboss.dna.spi.graph.Name;
-import org.jboss.dna.spi.graph.Path;
-import org.jboss.dna.spi.graph.Property;
-
-/**
- * The record of a source contributing only properties to a node.
- * <p>
- * This class does return a mutable mutable map of {@link #getProperties() properties}.
- * </p>
- *
- * @author Randall Hauch
- */
-public class PropertyContribution extends AbstractContribution {
-
- /**
- * This is the first version of this class. See the documentation of BasicMergePlan.serialVersionUID.
- */
- private static final long serialVersionUID = 1L;
-
- private final Map<Name, Property> properties;
- private final Path pathInSource;
-
- /**
- * Create a contribution of node properties from the source with the supplied name.
- *
- * @param sourceName the name of the source, which may not be null or blank
- * @param pathInSource the path in the source for this contributed information; may not be null
- * @param properties the properties from the source; may not be null
- */
- public PropertyContribution( String sourceName,
- Path pathInSource,
- Iterable<Property> properties ) {
- super(sourceName);
- assert pathInSource != null;
- this.properties = new HashMap<Name, Property>();
- this.pathInSource = pathInSource;
- for (Property property : properties) {
- this.properties.put(property.getName(), property);
- }
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public Map<Name, Property> getProperties() {
- return this.properties;
- }
-
- /**
- * {@inheritDoc}
- *
- * @see org.jboss.dna.connector.federation.contribution.Contribution#getPathInSource()
- */
- public Path getPathInSource() {
- return pathInSource;
- }
-
-}
Added: trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/contribution/ThreePropertyContribution.java
===================================================================
--- trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/contribution/ThreePropertyContribution.java (rev 0)
+++ trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/contribution/ThreePropertyContribution.java 2008-07-28 21:51:05 UTC (rev 375)
@@ -0,0 +1,106 @@
+/*
+ * 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.connector.federation.contribution;
+
+import java.util.Iterator;
+import net.jcip.annotations.Immutable;
+import org.jboss.dna.spi.graph.Name;
+import org.jboss.dna.spi.graph.Path;
+import org.jboss.dna.spi.graph.Property;
+
+/**
+ * The record of a source contributing only properties to a node.
+ *
+ * @author Randall Hauch
+ */
+@Immutable
+public class ThreePropertyContribution extends NonEmptyContribution {
+
+ /**
+ * This is the first version of this class. See the documentation of MergePlan.serialVersionUID.
+ */
+ private static final long serialVersionUID = 1L;
+
+ private final Property property1;
+ private final Property property2;
+ private final Property property3;
+
+ /**
+ * Create a contribution of node properties from the source with the supplied name.
+ *
+ * @param sourceName the name of the source, which may not be null or blank
+ * @param pathInSource the path in the source for this contributed information; may not be null
+ * @param property1 the first property from the source; may not be null
+ * @param property2 the second property from the source; may not be null
+ * @param property3 the third property from the source; may not be null
+ */
+ public ThreePropertyContribution( String sourceName,
+ Path pathInSource,
+ Property property1,
+ Property property2,
+ Property property3 ) {
+ super(sourceName, pathInSource);
+ assert property1 != null;
+ assert property1.isEmpty() == false;
+ assert property2 != null;
+ assert property2.isEmpty() == false;
+ assert property3 != null;
+ assert property3.isEmpty() == false;
+ this.property1 = property1;
+ this.property2 = property2;
+ this.property3 = property3;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.jboss.dna.connector.federation.contribution.Contribution#getProperties()
+ */
+ @Override
+ public Iterator<Property> getProperties() {
+ return new ThreeValueIterator<Property>(property1, property2, property3);
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.jboss.dna.connector.federation.contribution.Contribution#getPropertyCount()
+ */
+ @Override
+ public int getPropertyCount() {
+ return 3;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.jboss.dna.connector.federation.contribution.Contribution#getProperty(org.jboss.dna.spi.graph.Name)
+ */
+ @Override
+ public Property getProperty( Name name ) {
+ if (this.property1.getName().equals(name)) return property1;
+ if (this.property2.getName().equals(name)) return property2;
+ if (this.property3.getName().equals(name)) return property3;
+ return null;
+ }
+
+}
Property changes on: trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/contribution/ThreePropertyContribution.java
___________________________________________________________________
Name: svn:mime-type
+ text/plain
Added: trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/contribution/TwoPropertyContribution.java
===================================================================
--- trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/contribution/TwoPropertyContribution.java (rev 0)
+++ trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/contribution/TwoPropertyContribution.java 2008-07-28 21:51:05 UTC (rev 375)
@@ -0,0 +1,99 @@
+/*
+ * 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.connector.federation.contribution;
+
+import java.util.Iterator;
+import net.jcip.annotations.Immutable;
+import org.jboss.dna.spi.graph.Name;
+import org.jboss.dna.spi.graph.Path;
+import org.jboss.dna.spi.graph.Property;
+
+/**
+ * The record of a source contributing only properties to a node.
+ *
+ * @author Randall Hauch
+ */
+@Immutable
+public class TwoPropertyContribution extends NonEmptyContribution {
+
+ /**
+ * This is the first version of this class. See the documentation of MergePlan.serialVersionUID.
+ */
+ private static final long serialVersionUID = 1L;
+
+ private final Property property1;
+ private final Property property2;
+
+ /**
+ * Create a contribution of node properties from the source with the supplied name.
+ *
+ * @param sourceName the name of the source, which may not be null or blank
+ * @param pathInSource the path in the source for this contributed information; may not be null
+ * @param property1 the first property from the source; may not be null
+ * @param property2 the first property from the source; may not be null
+ */
+ public TwoPropertyContribution( String sourceName,
+ Path pathInSource,
+ Property property1,
+ Property property2 ) {
+ super(sourceName, pathInSource);
+ assert property1 != null;
+ assert property1.isEmpty() == false;
+ assert property2 != null;
+ assert property2.isEmpty() == false;
+ this.property1 = property1;
+ this.property2 = property2;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.jboss.dna.connector.federation.contribution.Contribution#getProperties()
+ */
+ @Override
+ public Iterator<Property> getProperties() {
+ return new TwoValueIterator<Property>(property1, property2);
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.jboss.dna.connector.federation.contribution.Contribution#getPropertyCount()
+ */
+ @Override
+ public int getPropertyCount() {
+ return 2;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.jboss.dna.connector.federation.contribution.Contribution#getProperty(org.jboss.dna.spi.graph.Name)
+ */
+ @Override
+ public Property getProperty( Name name ) {
+ if (this.property1.getName().equals(name)) return property1;
+ if (this.property2.getName().equals(name)) return property2;
+ return null;
+ }
+
+}
Property changes on: trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/contribution/TwoPropertyContribution.java
___________________________________________________________________
Name: svn:mime-type
+ text/plain
Modified: trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/executor/ActsOnProjectedPathCommand.java
===================================================================
--- trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/executor/ActsOnProjectedPathCommand.java 2008-07-28 15:00:27 UTC (rev 374)
+++ trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/executor/ActsOnProjectedPathCommand.java 2008-07-28 21:51:05 UTC (rev 375)
@@ -29,7 +29,7 @@
* @author Randall Hauch
* @param <T> the command type
*/
-public class ActsOnProjectedPathCommand<T extends GraphCommand> implements ActsOnPath, GraphCommand {
+public class ActsOnProjectedPathCommand<T extends ActsOnPath & GraphCommand> implements ActsOnPath, GraphCommand {
private final T delegate;
private final Path projectedPath;
Modified: trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/executor/FederatingCommandExecutor.java
===================================================================
--- trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/executor/FederatingCommandExecutor.java 2008-07-28 15:00:27 UTC (rev 374)
+++ trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/executor/FederatingCommandExecutor.java 2008-07-28 21:51:05 UTC (rev 375)
@@ -21,30 +21,34 @@
*/
package org.jboss.dna.connector.federation.executor;
-import java.io.ObjectInputStream;
+import java.util.Collection;
+import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
+import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import net.jcip.annotations.NotThreadSafe;
-import org.jboss.dna.common.i18n.I18n;
import org.jboss.dna.common.util.Logger;
-import org.jboss.dna.connector.federation.FederationI18n;
import org.jboss.dna.connector.federation.Projection;
import org.jboss.dna.connector.federation.contribution.Contribution;
-import org.jboss.dna.connector.federation.merge.BasicMergePlan;
+import org.jboss.dna.connector.federation.merge.MergePlan;
import org.jboss.dna.spi.ExecutionContext;
-import org.jboss.dna.spi.graph.Binary;
import org.jboss.dna.spi.graph.DateTime;
import org.jboss.dna.spi.graph.Name;
import org.jboss.dna.spi.graph.Path;
+import org.jboss.dna.spi.graph.PathFactory;
+import org.jboss.dna.spi.graph.PathNotFoundException;
import org.jboss.dna.spi.graph.Property;
-import org.jboss.dna.spi.graph.ValueFactory;
+import org.jboss.dna.spi.graph.Path.Segment;
import org.jboss.dna.spi.graph.commands.GetChildrenCommand;
import org.jboss.dna.spi.graph.commands.GetNodeCommand;
import org.jboss.dna.spi.graph.commands.GetPropertiesCommand;
+import org.jboss.dna.spi.graph.commands.GraphCommand;
+import org.jboss.dna.spi.graph.commands.NodeConflictBehavior;
import org.jboss.dna.spi.graph.commands.executor.AbstractCommandExecutor;
+import org.jboss.dna.spi.graph.commands.impl.BasicCreateNodeCommand;
import org.jboss.dna.spi.graph.commands.impl.BasicGetNodeCommand;
import org.jboss.dna.spi.graph.commands.impl.BasicGetPropertiesCommand;
import org.jboss.dna.spi.graph.connection.RepositoryConnection;
@@ -114,6 +118,9 @@
this.connectionsBySourceName = new HashMap<String, RepositoryConnection>();
this.mergePlanPropertyName = context.getValueFactories().getNameFactory().create("dna:mergePlan");
this.sourceNames = new HashSet<String>();
+ for (Projection projection : this.sourceProjections) {
+ this.sourceNames.add(projection.getSourceName());
+ }
}
/**
@@ -215,14 +222,20 @@
RepositoryConnection cacheConnection = getConnectionToCache();
BasicGetNodeCommand fromCache = new BasicGetNodeCommand(path);
cacheConnection.execute(getEnvironment(), fromCache);
+ if (fromCache.hasError()) {
+ if (fromCache.getError() instanceof PathNotFoundException) {
+ // Start at the root and populate the cache down to this node ...
+ }
+ }
+
if (fromCache.hasError()) return fromCache;
// Look up the merge plan ...
- BasicMergePlan basicMergePlan = getMergePlan(fromCache);
- if (basicMergePlan != null) {
- if (isCurrent(path, basicMergePlan)) return fromCache;
+ MergePlan mergePlan = getMergePlan(fromCache);
+ if (mergePlan != null) {
+ if (isCurrent(path, mergePlan)) return fromCache;
// Some of the merge plan is out of date, so we need to read the information from those regions that are expired ...
- BasicMergePlan newMergePlan = new BasicMergePlan();
+ // MergePlan newMergePlan = new BasicMergePlan();
// for (Projection projection : sourceProjections) {
// // Does this region apply to the path ...
// if (projection.appliesTo(path)) {
@@ -246,53 +259,93 @@
// What about other (new) regions?
} else {
// At this point, there is no merge plan, so read information from the sources ...
- // for (FederatedRegion region : regions) {
- // if (!region.appliesTo(path)) continue;
- // // Issue a command to get the node from the
- // // BasicGetNode
- // }
+ PathFactory pathFactory = getEnvironment().getValueFactories().getPathFactory();
+ List<Contribution> contributions = new LinkedList<Contribution>();
+ for (Projection projection : this.sourceProjections) {
+ final String source = projection.getSourceName();
+ // Get the paths-in-source where we should fetch node contributions ...
+ Set<Path> pathsInSource = projection.getPathsInSource(path, pathFactory);
+ if (pathsInSource.isEmpty()) {
+ // The source has no contributions ...
+ contributions.add(Contribution.create(source));
+ } else {
+ // There is at least one contribution ...
+ RepositoryConnection sourceConnection = getConnection(projection);
+
+ // Get the contributions ...
+ final int numPaths = pathsInSource.size();
+ if (numPaths == 1) {
+ Path pathInSource = pathsInSource.iterator().next();
+ BasicGetNodeCommand fromSource = new BasicGetNodeCommand(pathInSource);
+ sourceConnection.execute(getEnvironment(), fromSource);
+ if (!fromSource.hasError()) {
+ Collection<Property> properties = fromSource.getProperties().values();
+ Collection<Segment> children = fromSource.getChildren();
+ Contribution contribution = Contribution.create(source, pathInSource, properties, children);
+ contributions.add(contribution);
+ }
+ } else {
+ BasicGetNodeCommand[] fromSourceCommands = new BasicGetNodeCommand[numPaths];
+ int i = 0;
+ for (Path pathInSource : pathsInSource) {
+ fromSourceCommands[i++] = new BasicGetNodeCommand(pathInSource);
+ }
+ sourceConnection.execute(getEnvironment(), fromSourceCommands);
+ for (BasicGetNodeCommand fromSource : fromSourceCommands) {
+ if (fromSource.hasError()) continue;
+ Collection<Property> properties = fromSource.getProperties().values();
+ Collection<Segment> children = fromSource.getChildren();
+ Contribution contribution = Contribution.create(source, fromSource.getPath(), properties, children);
+ contributions.add(contribution);
+ }
+ }
+ }
+ }
+ // Merge the results into a single set of results ...
+ mergePlan = MergePlan.create(contributions);
+ BasicGetNodeCommand mergedNode = new BasicGetNodeCommand(null);
+
+ // Place the results into the cache ...
+ NodeConflictBehavior conflictBehavior = NodeConflictBehavior.UPDATE;
+ BasicCreateNodeCommand newNode = new BasicCreateNodeCommand(path, mergedNode.getProperties().values(),
+ conflictBehavior);
+ List<Segment> children = mergedNode.getChildren();
+ GraphCommand[] intoCache = new GraphCommand[1 + children.size()];
+ int i = 0;
+ intoCache[i++] = newNode;
+ List<Property> noProperties = Collections.emptyList();
+ for (Segment child : mergedNode.getChildren()) {
+ intoCache[i++] = new BasicCreateNodeCommand(pathFactory.create(path, child), noProperties, conflictBehavior);
+ }
+ cacheConnection.execute(getEnvironment(), mergedNode);
+
+ // Return the results ...
+ return mergedNode;
}
- // And read the information from any new region ...
+
return null;
}
- protected Contribution getContribution( String sourceName,
- Path path ) {
- return null;
+ protected Contribution getContribution( RepositoryConnection connection,
+ String sourceName,
+ Path path ) throws RepositorySourceException, InterruptedException {
+ BasicGetNodeCommand fromSource = new BasicGetNodeCommand(path);
+ connection.execute(getEnvironment(), fromSource);
+ if (fromSource.hasError()) return null;
+
+ Collection<Property> properties = fromSource.getProperties().values();
+ Collection<Segment> children = fromSource.getChildren();
+ Contribution contribution = Contribution.create(sourceName, path, properties, children);
+ return contribution;
}
- protected BasicMergePlan getMergePlan( BasicGetPropertiesCommand command ) {
+ protected MergePlan getMergePlan( BasicGetPropertiesCommand command ) {
Property mergePlanProperty = command.getProperties().get(mergePlanPropertyName);
if (mergePlanProperty == null || mergePlanProperty.isEmpty()) {
return null;
}
- ValueFactory<Binary> binaryFactory = getEnvironment().getValueFactories().getBinaryFactory();
- Binary binaryValue = binaryFactory.create(mergePlanProperty.getValues().next());
- binaryValue.acquire();
- ObjectInputStream stream = null;
- BasicMergePlan basicMergePlan = null;
- RepositorySourceException error = null;
- try {
- stream = new ObjectInputStream(binaryValue.getStream());
- basicMergePlan = (BasicMergePlan)stream.readObject();
- } catch (Throwable err) {
- I18n msg = FederationI18n.errorReadingMergePlan;
- error = new RepositorySourceException(getSourceName(), msg.text(command.getPath()), err);
- throw error;
- } finally {
- try {
- if (stream != null) stream.close();
- } catch (Throwable err) {
- if (error == null) {
- I18n msg = FederationI18n.errorReadingMergePlan;
- error = new RepositorySourceException(getSourceName(), msg.text(command.getPath()), err);
- throw error;
- }
- } finally {
- binaryValue.release();
- }
- }
- return basicMergePlan;
+ Object value = mergePlanProperty.getValues().next();
+ return value instanceof MergePlan ? (MergePlan)value : null;
}
/**
@@ -303,27 +356,27 @@
* @return true if the merge plan is current, or false if it needs to be (at least partially) rebuilt
*/
protected boolean isCurrent( Path path,
- BasicMergePlan plan ) {
+ MergePlan plan ) {
// First check the time ...
DateTime now = getCurrentTimeInUtc();
if (plan.isExpired(now)) return false;
// Does the plan have any contributions from sources that don't exist ?
- for (String contributingSource : plan.getNamesOfContributingSources()) {
- if (!sourceNames.contains(contributingSource)) return false;
+ for (Contribution contribution : plan) {
+ if (!sourceNames.contains(contribution.getSourceName())) return false;
}
-
- // Determine if any new source projections exists that aren't part of the plan ...
- for (String sourceName : sourceNames) {
- if (plan.isSource(sourceName)) continue;
- // The source is new ... see whether there are any regions that apply ...
- // for (FederatedRegion region : this.regionsBySourceName.get(sourceName)) {
- // // If the region's path is not at/above the path, the region doesn't matter
- // if (!region.appliesTo(path)) continue;
- // // The region applies to the path ...
- // return false;
- // }
- }
+ //
+ // // Determine if any new source projections exists that aren't part of the plan ...
+ // for (String sourceName : sourceNames) {
+ // if (plan.isSource(sourceName)) continue;
+ // // The source is new ... see whether there are any regions that apply ...
+ // // for (FederatedRegion region : this.regionsBySourceName.get(sourceName)) {
+ // // // If the region's path is not at/above the path, the region doesn't matter
+ // // if (!region.appliesTo(path)) continue;
+ // // // The region applies to the path ...
+ // // return false;
+ // // }
+ // }
return true;
}
Deleted: trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/merge/BasicMergePlan.java
===================================================================
--- trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/merge/BasicMergePlan.java 2008-07-28 15:00:27 UTC (rev 374)
+++ trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/merge/BasicMergePlan.java 2008-07-28 21:51:05 UTC (rev 375)
@@ -1,205 +0,0 @@
-/*
- * 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.connector.federation.merge;
-
-import java.io.InvalidClassException;
-import java.io.Serializable;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Set;
-import net.jcip.annotations.NotThreadSafe;
-import org.jboss.dna.connector.federation.contribution.Contribution;
-import org.jboss.dna.connector.federation.contribution.EmptyContribution;
-import org.jboss.dna.spi.graph.DateTime;
-import org.jboss.dna.spi.graph.Name;
-import org.jboss.dna.spi.graph.Property;
-
-/**
- * This class represents the details about how information from different sources are merged into a single federated node.
- * <p>
- * A merge plan basically consists of the individual contribution from each source and the information about how these
- * contributions were merged into the single federated node.
- * </p>
- * <p>
- * Merge plans are designed to be {@link Serializable serializable}, as they are persisted on the federated node and deserialized
- * to assist in the management of the federated node.
- * </p>
- *
- * @author Randall Hauch
- */
-@NotThreadSafe
-public class BasicMergePlan implements Serializable {
-
- /**
- * Define the earliest version of this class that is supported. The Java runtime, upon deserialization, compares the
- * serialized object's version to this, and if less than this version will throw a {@link InvalidClassException}. If, however,
- * the serialized object's version is compatible with this class, it will be deserialized successfully.
- * <p>
- * <a href="http://java.sun.com/j2se/1.5.0/docs/guide/serialization/spec/version.html...">Sun's documentation</a> describes
- * the following changes can be made without negatively affecting the deserialization of older versions:
- * <ul>
- * <li>Adding fields - When the class being reconstituted has a field that does not occur in the stream, that field in the
- * object will be initialized to the default value for its type. If class-specific initialization is needed, the class may
- * provide a readObject method that can initialize the field to nondefault values.</i>
- * <li>Adding classes - The stream will contain the type hierarchy of each object in the stream. Comparing this hierarchy in
- * the stream with the current class can detect additional classes. Since there is no information in the stream from which to
- * initialize the object, the class's fields will be initialized to the default values.</i>
- * <li>Removing classes - Comparing the class hierarchy in the stream with that of the current class can detect that a class
- * has been deleted. In this case, the fields and objects corresponding to that class are read from the stream. Primitive
- * fields are discarded, but the objects referenced by the deleted class are created, since they may be referred to later in
- * the stream. They will be garbage-collected when the stream is garbage-collected or reset.</i>
- * <li>Adding writeObject/readObject methods - If the version reading the stream has these methods then readObject is
- * expected, as usual, to read the required data written to the stream by the default serialization. It should call
- * defaultReadObject first before reading any optional data. The writeObject method is expected as usual to call
- * defaultWriteObject to write the required data and then may write optional data.</i>
- * <li>Removing writeObject/readObject methods - If the class reading the stream does not have these methods, the required
- * data will be read by default serialization, and the optional data will be discarded.</i>
- * <li>Adding java.io.Serializable - This is equivalent to adding types. There will be no values in the stream for this class
- * so its fields will be initialized to default values. The support for subclassing nonserializable classes requires that the
- * class's supertype have a no-arg constructor and the class itself will be initialized to default values. If the no-arg
- * constructor is not available, the InvalidClassException is thrown.</i>
- * <li>Changing the access to a field - The access modifiers public, package, protected, and private have no effect on the
- * ability of serialization to assign values to the fields.</i>
- * <li>Changing a field from static to nonstatic or transient to nontransient - When relying on default serialization to
- * compute the serializable fields, this change is equivalent to adding a field to the class. The new field will be written to
- * the stream but earlier classes will ignore the value since serialization will not assign values to static or transient
- * fields.</i>
- * </ul>
- * All other kinds of modifications should be avoided.
- * </p>
- */
- private static final long serialVersionUID = 1L;
-
- private final Map<String, Contribution> contributions = new HashMap<String, Contribution>();
- private Map<Name, Property> annotations = null;
- private DateTime expirationTimeInUtc;
-
- /**
- * Create this version
- */
- public BasicMergePlan() {
- }
-
- /**
- * Determine whether this merge plan has expired given the supplied current time. The {@link #getExpirationTimeInUtc()
- * expiration time} is the earliest time that any of the {@link #getContributionFrom(String) contributions}
- * {@link Contribution#getExpirationTimeInUtc()}.
- *
- * @param utcTime the current time expressed in UTC; may not be null
- * @return true if at least one contribution has expired, or false otherwise
- */
- public boolean isExpired( DateTime utcTime ) {
- assert utcTime != null;
- assert utcTime.toUtcTimeZone().equals(utcTime); // check that it is passed UTC time
- return !expirationTimeInUtc.isAfter(utcTime);
- }
-
- /**
- * Get the expiration time (in UTC) that is the earliest time that any of the {@link #getContributionFrom(String)
- * contributions} {@link Contribution#getExpirationTimeInUtc()}.
- *
- * @return the expiration time in UTC, or null if there is no known expiration time
- */
- public DateTime getExpirationTimeInUtc() {
- return expirationTimeInUtc;
- }
-
- /**
- * Get the contribution from the source with the supplied name. Note that contributions always include sources that contribute
- * information and sources that contribute no information. If a source is not included in this list, its contributions are
- * <i>unknown</i>; that is, it is unknown whether that source does or does not contribute to the node.
- *
- * @param sourceName the name of the source
- * @return the contribution, or null if the contribution of the source is unknown
- */
- public Contribution getContributionFrom( String sourceName ) {
- return contributions.get(sourceName);
- }
-
- /**
- * Return whether the named source was consulted for a contribution.
- *
- * @param sourceName the name of the source
- * @return true if the source has some {@link Contribution contribution} (even if it is an {@link EmptyContribution})
- */
- public boolean isSource( String sourceName ) {
- return contributions.containsKey(sourceName);
- }
-
- /**
- * Get the names of the contributing sources.
- *
- * @return the names of the sources that have some contribution
- */
- public Set<String> getNamesOfContributingSources() {
- return contributions.keySet();
- }
-
- /**
- * Add the supplied contribution, replacing and returning any previous contribution for the same source.
- *
- * @param contribution the new contribution
- * @return the previous contribution for the source, or null if there was no previous contribution.
- */
- public Contribution addContribution( Contribution contribution ) {
- assert contribution != null;
- Contribution previous = contributions.put(contribution.getSourceName(), contribution);
- DateTime contributionExpirationInUtc = contribution.getExpirationTimeInUtc();
- if (expirationTimeInUtc == null || contributionExpirationInUtc.isBefore(expirationTimeInUtc)) {
- expirationTimeInUtc = contributionExpirationInUtc;
- }
- return previous;
- }
-
- /**
- * Get the plan annotation property with the given name. Plan annotations are custom properties that may be set by
- * MergeProcessor implementations to store custom properties on the plan. This method does nothing if the supplied name is
- * null
- *
- * @param name the name of the annotation
- * @return the existing annotation, or null if there is no annotation with the supplied name
- * @see #setAnnotation(Property)
- */
- public Property getAnnotation( Name name ) {
- if (name == null) return null;
- if (this.annotations == null) return null;
- return this.annotations.get(name);
- }
-
- /**
- * Set the plan annotation property. This method replaces and returns any existing annotation property with the same name.
- * This method also returns immediately if the supplied annotation is null.
- *
- * @param annotation the new annotation
- * @return the previous annotation property with the same name, or null if there was no previous annotation property for the
- * name
- * @see #getAnnotation(Name)
- */
- public Property setAnnotation( Property annotation ) {
- if (annotation == null) return null;
- if (this.annotations == null) {
- this.annotations = new HashMap<Name, Property>();
- }
- return this.annotations.put(annotation.getName(), annotation);
- }
-
-}
Deleted: trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/merge/DoubleContributionMergePlan.java
===================================================================
--- trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/merge/DoubleContributionMergePlan.java 2008-07-28 15:00:27 UTC (rev 374)
+++ trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/merge/DoubleContributionMergePlan.java 2008-07-28 21:51:05 UTC (rev 375)
@@ -1,115 +0,0 @@
-/*
- * 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.connector.federation.merge;
-
-import java.util.Iterator;
-import java.util.NoSuchElementException;
-import net.jcip.annotations.ThreadSafe;
-import org.jboss.dna.connector.federation.contribution.Contribution;
-
-/**
- * @author Randall Hauch
- */
-@ThreadSafe
-public class DoubleContributionMergePlan extends MergePlan {
-
- private static final long serialVersionUID = 1L;
- private final Contribution contribution1;
- private final Contribution contribution2;
-
- /**
- * @param contribution1 the first contribution for this merge plan
- * @param contribution2 the second contribution for this merge plan
- */
- public DoubleContributionMergePlan( Contribution contribution1,
- Contribution contribution2 ) {
- assert contribution1 != null;
- assert contribution2 != null;
- this.contribution1 = contribution1;
- this.contribution2 = contribution2;
- }
-
- /**
- * {@inheritDoc}
- *
- * @see org.jboss.dna.connector.federation.merge.MergePlan#getContributionCount()
- */
- @Override
- public int getContributionCount() {
- return 2;
- }
-
- /**
- * {@inheritDoc}
- *
- * @see org.jboss.dna.connector.federation.merge.MergePlan#getContributionFrom(java.lang.String)
- */
- @Override
- public Contribution getContributionFrom( String sourceName ) {
- if (contribution1.getSourceName().equals(sourceName)) return contribution1;
- if (contribution2.getSourceName().equals(sourceName)) return contribution2;
- return null;
- }
-
- /**
- * {@inheritDoc}
- *
- * @see java.lang.Iterable#iterator()
- */
- public Iterator<Contribution> iterator() {
- return new Iterator<Contribution>() {
- private int next = 2;
-
- public boolean hasNext() {
- return next > 0;
- }
-
- @SuppressWarnings( "synthetic-access" )
- public Contribution next() {
- if (next == 2) {
- next = 1;
- return contribution2;
- }
- if (next == 1) {
- next = 0;
- return contribution1;
- }
- throw new NoSuchElementException();
- }
-
- public void remove() {
- throw new UnsupportedOperationException();
- }
- };
- }
-
- /**
- * {@inheritDoc}
- *
- * @see org.jboss.dna.connector.federation.merge.MergePlan#isSource(java.lang.String)
- */
- @Override
- public boolean isSource( String sourceName ) {
- return contribution1.getSourceName().equals(sourceName) || contribution2.getSourceName().equals(sourceName);
- }
-
-}
Added: trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/merge/FiveContributionMergePlan.java
===================================================================
--- trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/merge/FiveContributionMergePlan.java (rev 0)
+++ trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/merge/FiveContributionMergePlan.java 2008-07-28 21:51:05 UTC (rev 375)
@@ -0,0 +1,150 @@
+/*
+ * 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.connector.federation.merge;
+
+import java.util.Iterator;
+import java.util.NoSuchElementException;
+import net.jcip.annotations.ThreadSafe;
+import org.jboss.dna.connector.federation.contribution.Contribution;
+
+/**
+ * @author Randall Hauch
+ */
+@ThreadSafe
+public class FiveContributionMergePlan extends MergePlan {
+
+ private static final long serialVersionUID = 1L;
+ private final Contribution contribution1;
+ private final Contribution contribution2;
+ private final Contribution contribution3;
+ private final Contribution contribution4;
+ private final Contribution contribution5;
+
+ /**
+ * @param contribution1 the first contribution for this merge plan
+ * @param contribution2 the second contribution for this merge plan
+ * @param contribution3 the third contribution for this merge plan
+ * @param contribution4 the fourth contribution for this merge plan
+ * @param contribution5 the fifth contribution for this merge plan
+ */
+ public FiveContributionMergePlan( Contribution contribution1,
+ Contribution contribution2,
+ Contribution contribution3,
+ Contribution contribution4,
+ Contribution contribution5 ) {
+ assert contribution1 != null;
+ assert contribution2 != null;
+ assert contribution3 != null;
+ assert contribution4 != null;
+ assert contribution5 != null;
+ this.contribution1 = contribution1;
+ this.contribution2 = contribution2;
+ this.contribution3 = contribution3;
+ this.contribution4 = contribution4;
+ this.contribution5 = contribution5;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.jboss.dna.connector.federation.merge.MergePlan#getContributionCount()
+ */
+ @Override
+ public int getContributionCount() {
+ return 5;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.jboss.dna.connector.federation.merge.MergePlan#getContributionFrom(java.lang.String)
+ */
+ @Override
+ public Contribution getContributionFrom( String sourceName ) {
+ if (contribution1.getSourceName().equals(sourceName)) return contribution1;
+ if (contribution2.getSourceName().equals(sourceName)) return contribution2;
+ if (contribution3.getSourceName().equals(sourceName)) return contribution3;
+ if (contribution4.getSourceName().equals(sourceName)) return contribution4;
+ if (contribution5.getSourceName().equals(sourceName)) return contribution5;
+ return null;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see java.lang.Iterable#iterator()
+ */
+ public Iterator<Contribution> iterator() {
+ return new Iterator<Contribution>() {
+ private int next = 4;
+
+ public boolean hasNext() {
+ return next > 0;
+ }
+
+ @SuppressWarnings( "synthetic-access" )
+ public Contribution next() {
+ if (next == 5) {
+ next = 4;
+ return contribution1;
+ }
+ if (next == 4) {
+ next = 3;
+ return contribution2;
+ }
+ if (next == 3) {
+ next = 2;
+ return contribution3;
+ }
+ if (next == 2) {
+ next = 1;
+ return contribution4;
+ }
+ if (next == 1) {
+ next = 0;
+ return contribution5;
+ }
+ throw new NoSuchElementException();
+ }
+
+ public void remove() {
+ throw new UnsupportedOperationException();
+ }
+ };
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.jboss.dna.connector.federation.merge.MergePlan#isSource(java.lang.String)
+ */
+ @Override
+ public boolean isSource( String sourceName ) {
+ if (contribution1.getSourceName().equals(sourceName)) return true;
+ if (contribution2.getSourceName().equals(sourceName)) return true;
+ if (contribution3.getSourceName().equals(sourceName)) return true;
+ if (contribution4.getSourceName().equals(sourceName)) return true;
+ if (contribution5.getSourceName().equals(sourceName)) return true;
+ return false;
+ }
+
+}
Property changes on: trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/merge/FiveContributionMergePlan.java
___________________________________________________________________
Name: svn:mime-type
+ text/plain
Added: trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/merge/FourContributionMergePlan.java
===================================================================
--- trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/merge/FourContributionMergePlan.java (rev 0)
+++ trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/merge/FourContributionMergePlan.java 2008-07-28 21:51:05 UTC (rev 375)
@@ -0,0 +1,139 @@
+/*
+ * 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.connector.federation.merge;
+
+import java.util.Iterator;
+import java.util.NoSuchElementException;
+import net.jcip.annotations.ThreadSafe;
+import org.jboss.dna.connector.federation.contribution.Contribution;
+
+/**
+ * @author Randall Hauch
+ */
+@ThreadSafe
+public class FourContributionMergePlan extends MergePlan {
+
+ private static final long serialVersionUID = 1L;
+ private final Contribution contribution1;
+ private final Contribution contribution2;
+ private final Contribution contribution3;
+ private final Contribution contribution4;
+
+ /**
+ * @param contribution1 the first contribution for this merge plan
+ * @param contribution2 the second contribution for this merge plan
+ * @param contribution3 the third contribution for this merge plan
+ * @param contribution4 the fourth contribution for this merge plan
+ */
+ public FourContributionMergePlan( Contribution contribution1,
+ Contribution contribution2,
+ Contribution contribution3,
+ Contribution contribution4 ) {
+ assert contribution1 != null;
+ assert contribution2 != null;
+ assert contribution3 != null;
+ assert contribution4 != null;
+ this.contribution1 = contribution1;
+ this.contribution2 = contribution2;
+ this.contribution3 = contribution3;
+ this.contribution4 = contribution4;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.jboss.dna.connector.federation.merge.MergePlan#getContributionCount()
+ */
+ @Override
+ public int getContributionCount() {
+ return 4;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.jboss.dna.connector.federation.merge.MergePlan#getContributionFrom(java.lang.String)
+ */
+ @Override
+ public Contribution getContributionFrom( String sourceName ) {
+ if (contribution1.getSourceName().equals(sourceName)) return contribution1;
+ if (contribution2.getSourceName().equals(sourceName)) return contribution2;
+ if (contribution3.getSourceName().equals(sourceName)) return contribution3;
+ if (contribution4.getSourceName().equals(sourceName)) return contribution4;
+ return null;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see java.lang.Iterable#iterator()
+ */
+ public Iterator<Contribution> iterator() {
+ return new Iterator<Contribution>() {
+ private int next = 4;
+
+ public boolean hasNext() {
+ return next > 0;
+ }
+
+ @SuppressWarnings( "synthetic-access" )
+ public Contribution next() {
+ if (next == 4) {
+ next = 3;
+ return contribution1;
+ }
+ if (next == 3) {
+ next = 2;
+ return contribution2;
+ }
+ if (next == 2) {
+ next = 1;
+ return contribution3;
+ }
+ if (next == 1) {
+ next = 0;
+ return contribution4;
+ }
+ throw new NoSuchElementException();
+ }
+
+ public void remove() {
+ throw new UnsupportedOperationException();
+ }
+ };
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.jboss.dna.connector.federation.merge.MergePlan#isSource(java.lang.String)
+ */
+ @Override
+ public boolean isSource( String sourceName ) {
+ if (contribution1.getSourceName().equals(sourceName)) return true;
+ if (contribution2.getSourceName().equals(sourceName)) return true;
+ if (contribution3.getSourceName().equals(sourceName)) return true;
+ if (contribution4.getSourceName().equals(sourceName)) return true;
+ return false;
+ }
+
+}
Property changes on: trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/merge/FourContributionMergePlan.java
___________________________________________________________________
Name: svn:mime-type
+ text/plain
Modified: trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/merge/MergePlan.java
===================================================================
--- trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/merge/MergePlan.java 2008-07-28 15:00:27 UTC (rev 374)
+++ trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/merge/MergePlan.java 2008-07-28 21:51:05 UTC (rev 375)
@@ -23,6 +23,7 @@
import java.io.InvalidClassException;
import java.io.Serializable;
+import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
@@ -54,16 +55,40 @@
ArgCheck.isNotNull(contributions, "contributions");
switch (contributions.length) {
case 1:
- return new SingleContributionMergePlan(contributions[0]);
+ return new OneContributionMergePlan(contributions[0]);
case 2:
- return new DoubleContributionMergePlan(contributions[0], contributions[1]);
+ return new TwoContributionMergePlan(contributions[0], contributions[1]);
case 3:
- return new TripleContributionMergePlan(contributions[0], contributions[1], contributions[2]);
+ return new ThreeContributionMergePlan(contributions[0], contributions[1], contributions[2]);
+ case 4:
+ return new FourContributionMergePlan(contributions[0], contributions[1], contributions[2], contributions[3]);
+ case 5:
+ return new FiveContributionMergePlan(contributions[0], contributions[1], contributions[2], contributions[3],
+ contributions[4]);
default:
return new MultipleContributionMergePlan(contributions);
}
}
+ public static MergePlan create( Collection<Contribution> contributions ) {
+ ArgCheck.isNotNull(contributions, "contributions");
+ Iterator<Contribution> iter = contributions.iterator();
+ switch (contributions.size()) {
+ case 1:
+ return new OneContributionMergePlan(iter.next());
+ case 2:
+ return new TwoContributionMergePlan(iter.next(), iter.next());
+ case 3:
+ return new ThreeContributionMergePlan(iter.next(), iter.next(), iter.next());
+ case 4:
+ return new FourContributionMergePlan(iter.next(), iter.next(), iter.next(), iter.next());
+ case 5:
+ return new FiveContributionMergePlan(iter.next(), iter.next(), iter.next(), iter.next(), iter.next());
+ default:
+ return new MultipleContributionMergePlan(contributions);
+ }
+ }
+
public static MergePlan addContribution( MergePlan plan,
Contribution contribution ) {
if (plan instanceof MultipleContributionMergePlan) {
@@ -71,20 +96,26 @@
multiPlan.addContribution(contribution);
return multiPlan;
}
- if (plan instanceof SingleContributionMergePlan) {
- MergePlan newPlan = new DoubleContributionMergePlan(plan.iterator().next(), contribution);
- newPlan.setAnnotations(plan.getAnnotations());
+ MergePlan newPlan = null;
+ if (plan instanceof OneContributionMergePlan) {
+ newPlan = new TwoContributionMergePlan(plan.iterator().next(), contribution);
+ } else if (plan instanceof TwoContributionMergePlan) {
+ Iterator<Contribution> iter = plan.iterator();
+ newPlan = new ThreeContributionMergePlan(iter.next(), iter.next(), contribution);
+ } else if (plan instanceof ThreeContributionMergePlan) {
+ Iterator<Contribution> iter = plan.iterator();
+ newPlan = new FourContributionMergePlan(iter.next(), iter.next(), iter.next(), contribution);
+ } else if (plan instanceof FourContributionMergePlan) {
+ Iterator<Contribution> iter = plan.iterator();
+ newPlan = new FiveContributionMergePlan(iter.next(), iter.next(), iter.next(), iter.next(), contribution);
+ } else {
+ MultipleContributionMergePlan multiPlan = new MultipleContributionMergePlan();
+ for (Contribution existingContribution : plan) {
+ multiPlan.addContribution(existingContribution);
+ }
+ multiPlan.addContribution(contribution);
+ newPlan = multiPlan;
}
- if (plan instanceof DoubleContributionMergePlan) {
- Iterator<Contribution> iterator = plan.iterator();
- MergePlan newPlan = new TripleContributionMergePlan(iterator.next(), iterator.next(), contribution);
- newPlan.setAnnotations(plan.getAnnotations());
- }
- MultipleContributionMergePlan newPlan = new MultipleContributionMergePlan();
- for (Contribution existingContribution : plan) {
- newPlan.addContribution(existingContribution);
- }
- newPlan.addContribution(contribution);
newPlan.setAnnotations(plan.getAnnotations());
return newPlan;
}
Modified: trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/merge/MultipleContributionMergePlan.java
===================================================================
--- trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/merge/MultipleContributionMergePlan.java 2008-07-28 15:00:27 UTC (rev 374)
+++ trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/merge/MultipleContributionMergePlan.java 2008-07-28 21:51:05 UTC (rev 375)
@@ -49,6 +49,31 @@
}
/**
+ * @param contributions the contributions for this merge plan
+ */
+ public MultipleContributionMergePlan( Iterable<Contribution> contributions ) {
+ assert contributions != null;
+ this.contributions = new CopyOnWriteArrayList<Contribution>();
+ for (Contribution contribution : contributions) {
+ assert contribution != null;
+ this.contributions.add(contribution);
+ }
+ }
+
+ /**
+ * @param contributions the contributions for this merge plan
+ */
+ public MultipleContributionMergePlan( Iterator<Contribution> contributions ) {
+ assert contributions != null;
+ this.contributions = new CopyOnWriteArrayList<Contribution>();
+ while (contributions.hasNext()) {
+ Contribution contribution = contributions.next();
+ assert contribution != null;
+ this.contributions.add(contribution);
+ }
+ }
+
+ /**
* {@inheritDoc}
*
* @see org.jboss.dna.connector.federation.merge.MergePlan#getContributionCount()
Copied: trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/merge/OneContributionMergePlan.java (from rev 369, trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/merge/SingleContributionMergePlan.java)
===================================================================
--- trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/merge/OneContributionMergePlan.java (rev 0)
+++ trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/merge/OneContributionMergePlan.java 2008-07-28 21:51:05 UTC (rev 375)
@@ -0,0 +1,104 @@
+/*
+ * 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.connector.federation.merge;
+
+import java.util.Iterator;
+import java.util.NoSuchElementException;
+import net.jcip.annotations.ThreadSafe;
+import org.jboss.dna.connector.federation.contribution.Contribution;
+
+/**
+ * @author Randall Hauch
+ */
+@ThreadSafe
+public class OneContributionMergePlan extends MergePlan {
+
+ private static final long serialVersionUID = 1L;
+ private final Contribution contribution;
+
+ /**
+ * @param contribution the contribution for this merge plan
+ */
+ public OneContributionMergePlan( Contribution contribution ) {
+ assert contribution != null;
+ this.contribution = contribution;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.jboss.dna.connector.federation.merge.MergePlan#getContributionCount()
+ */
+ @Override
+ public int getContributionCount() {
+ return 1;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.jboss.dna.connector.federation.merge.MergePlan#getContributionFrom(java.lang.String)
+ */
+ @Override
+ public Contribution getContributionFrom( String sourceName ) {
+ return isSource(sourceName) ? contribution : null;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see java.lang.Iterable#iterator()
+ */
+ public Iterator<Contribution> iterator() {
+ return new Iterator<Contribution>() {
+ private boolean next = true;
+
+ public boolean hasNext() {
+ return next;
+ }
+
+ @SuppressWarnings( "synthetic-access" )
+ public Contribution next() {
+ if (next) {
+ next = false;
+ return contribution;
+ }
+ throw new NoSuchElementException();
+ }
+
+ public void remove() {
+ throw new UnsupportedOperationException();
+ }
+ };
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.jboss.dna.connector.federation.merge.MergePlan#isSource(java.lang.String)
+ */
+ @Override
+ public boolean isSource( String sourceName ) {
+ return contribution.getSourceName().equals(sourceName);
+ }
+
+}
Deleted: trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/merge/SingleContributionMergePlan.java
===================================================================
--- trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/merge/SingleContributionMergePlan.java 2008-07-28 15:00:27 UTC (rev 374)
+++ trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/merge/SingleContributionMergePlan.java 2008-07-28 21:51:05 UTC (rev 375)
@@ -1,104 +0,0 @@
-/*
- * 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.connector.federation.merge;
-
-import java.util.Iterator;
-import java.util.NoSuchElementException;
-import net.jcip.annotations.ThreadSafe;
-import org.jboss.dna.connector.federation.contribution.Contribution;
-
-/**
- * @author Randall Hauch
- */
-@ThreadSafe
-public class SingleContributionMergePlan extends MergePlan {
-
- private static final long serialVersionUID = 1L;
- private final Contribution contribution;
-
- /**
- * @param contribution the contribution for this merge plan
- */
- public SingleContributionMergePlan( Contribution contribution ) {
- assert contribution != null;
- this.contribution = contribution;
- }
-
- /**
- * {@inheritDoc}
- *
- * @see org.jboss.dna.connector.federation.merge.MergePlan#getContributionCount()
- */
- @Override
- public int getContributionCount() {
- return 1;
- }
-
- /**
- * {@inheritDoc}
- *
- * @see org.jboss.dna.connector.federation.merge.MergePlan#getContributionFrom(java.lang.String)
- */
- @Override
- public Contribution getContributionFrom( String sourceName ) {
- return isSource(sourceName) ? contribution : null;
- }
-
- /**
- * {@inheritDoc}
- *
- * @see java.lang.Iterable#iterator()
- */
- public Iterator<Contribution> iterator() {
- return new Iterator<Contribution>() {
- private boolean next = true;
-
- public boolean hasNext() {
- return next;
- }
-
- @SuppressWarnings( "synthetic-access" )
- public Contribution next() {
- if (next) {
- next = false;
- return contribution;
- }
- throw new NoSuchElementException();
- }
-
- public void remove() {
- throw new UnsupportedOperationException();
- }
- };
- }
-
- /**
- * {@inheritDoc}
- *
- * @see org.jboss.dna.connector.federation.merge.MergePlan#isSource(java.lang.String)
- */
- @Override
- public boolean isSource( String sourceName ) {
- return contribution.getSourceName().equals(sourceName);
- }
-
-}
Copied: trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/merge/ThreeContributionMergePlan.java (from rev 369, trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/merge/TripleContributionMergePlan.java)
===================================================================
--- trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/merge/ThreeContributionMergePlan.java (rev 0)
+++ trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/merge/ThreeContributionMergePlan.java 2008-07-28 21:51:05 UTC (rev 375)
@@ -0,0 +1,128 @@
+/*
+ * 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.connector.federation.merge;
+
+import java.util.Iterator;
+import java.util.NoSuchElementException;
+import net.jcip.annotations.ThreadSafe;
+import org.jboss.dna.connector.federation.contribution.Contribution;
+
+/**
+ * @author Randall Hauch
+ */
+@ThreadSafe
+public class ThreeContributionMergePlan extends MergePlan {
+
+ private static final long serialVersionUID = 1L;
+ private final Contribution contribution1;
+ private final Contribution contribution2;
+ private final Contribution contribution3;
+
+ /**
+ * @param contribution1 the first contribution for this merge plan
+ * @param contribution2 the second contribution for this merge plan
+ * @param contribution3 the third contribution for this merge plan
+ */
+ public ThreeContributionMergePlan( Contribution contribution1,
+ Contribution contribution2,
+ Contribution contribution3 ) {
+ assert contribution1 != null;
+ assert contribution2 != null;
+ assert contribution3 != null;
+ this.contribution1 = contribution1;
+ this.contribution2 = contribution2;
+ this.contribution3 = contribution3;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.jboss.dna.connector.federation.merge.MergePlan#getContributionCount()
+ */
+ @Override
+ public int getContributionCount() {
+ return 3;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.jboss.dna.connector.federation.merge.MergePlan#getContributionFrom(java.lang.String)
+ */
+ @Override
+ public Contribution getContributionFrom( String sourceName ) {
+ if (contribution1.getSourceName().equals(sourceName)) return contribution1;
+ if (contribution2.getSourceName().equals(sourceName)) return contribution2;
+ if (contribution3.getSourceName().equals(sourceName)) return contribution3;
+ return null;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see java.lang.Iterable#iterator()
+ */
+ public Iterator<Contribution> iterator() {
+ return new Iterator<Contribution>() {
+ private int next = 3;
+
+ public boolean hasNext() {
+ return next > 0;
+ }
+
+ @SuppressWarnings( "synthetic-access" )
+ public Contribution next() {
+ if (next == 3) {
+ next = 2;
+ return contribution1;
+ }
+ if (next == 2) {
+ next = 1;
+ return contribution2;
+ }
+ if (next == 1) {
+ next = 0;
+ return contribution3;
+ }
+ throw new NoSuchElementException();
+ }
+
+ public void remove() {
+ throw new UnsupportedOperationException();
+ }
+ };
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.jboss.dna.connector.federation.merge.MergePlan#isSource(java.lang.String)
+ */
+ @Override
+ public boolean isSource( String sourceName ) {
+ if (contribution1.getSourceName().equals(sourceName)) return true;
+ if (contribution2.getSourceName().equals(sourceName)) return true;
+ if (contribution3.getSourceName().equals(sourceName)) return true;
+ return false;
+ }
+
+}
Deleted: trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/merge/TripleContributionMergePlan.java
===================================================================
--- trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/merge/TripleContributionMergePlan.java 2008-07-28 15:00:27 UTC (rev 374)
+++ trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/merge/TripleContributionMergePlan.java 2008-07-28 21:51:05 UTC (rev 375)
@@ -1,126 +0,0 @@
-/*
- * 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.connector.federation.merge;
-
-import java.util.Iterator;
-import java.util.NoSuchElementException;
-import net.jcip.annotations.ThreadSafe;
-import org.jboss.dna.connector.federation.contribution.Contribution;
-
-/**
- * @author Randall Hauch
- */
-@ThreadSafe
-public class TripleContributionMergePlan extends MergePlan {
-
- private static final long serialVersionUID = 1L;
- private final Contribution contribution1;
- private final Contribution contribution2;
- private final Contribution contribution3;
-
- /**
- * @param contribution1 the first contribution for this merge plan
- * @param contribution2 the second contribution for this merge plan
- * @param contribution3 the third contribution for this merge plan
- */
- public TripleContributionMergePlan( Contribution contribution1,
- Contribution contribution2,
- Contribution contribution3 ) {
- assert contribution1 != null;
- assert contribution2 != null;
- assert contribution3 != null;
- this.contribution1 = contribution1;
- this.contribution2 = contribution2;
- this.contribution3 = contribution3;
- }
-
- /**
- * {@inheritDoc}
- *
- * @see org.jboss.dna.connector.federation.merge.MergePlan#getContributionCount()
- */
- @Override
- public int getContributionCount() {
- return 3;
- }
-
- /**
- * {@inheritDoc}
- *
- * @see org.jboss.dna.connector.federation.merge.MergePlan#getContributionFrom(java.lang.String)
- */
- @Override
- public Contribution getContributionFrom( String sourceName ) {
- if (contribution1.getSourceName().equals(sourceName)) return contribution1;
- if (contribution2.getSourceName().equals(sourceName)) return contribution2;
- if (contribution3.getSourceName().equals(sourceName)) return contribution3;
- return null;
- }
-
- /**
- * {@inheritDoc}
- *
- * @see java.lang.Iterable#iterator()
- */
- public Iterator<Contribution> iterator() {
- return new Iterator<Contribution>() {
- private int next = 3;
-
- public boolean hasNext() {
- return next > 0;
- }
-
- @SuppressWarnings( "synthetic-access" )
- public Contribution next() {
- if (next == 3) {
- next = 2;
- return contribution3;
- }
- if (next == 2) {
- next = 1;
- return contribution2;
- }
- if (next == 1) {
- next = 0;
- return contribution1;
- }
- throw new NoSuchElementException();
- }
-
- public void remove() {
- throw new UnsupportedOperationException();
- }
- };
- }
-
- /**
- * {@inheritDoc}
- *
- * @see org.jboss.dna.connector.federation.merge.MergePlan#isSource(java.lang.String)
- */
- @Override
- public boolean isSource( String sourceName ) {
- return contribution1.getSourceName().equals(sourceName) || contribution2.getSourceName().equals(sourceName)
- || contribution3.getSourceName().equals(sourceName);
- }
-
-}
Copied: trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/merge/TwoContributionMergePlan.java (from rev 369, trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/merge/DoubleContributionMergePlan.java)
===================================================================
--- trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/merge/TwoContributionMergePlan.java (rev 0)
+++ trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/merge/TwoContributionMergePlan.java 2008-07-28 21:51:05 UTC (rev 375)
@@ -0,0 +1,115 @@
+/*
+ * 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.connector.federation.merge;
+
+import java.util.Iterator;
+import java.util.NoSuchElementException;
+import net.jcip.annotations.ThreadSafe;
+import org.jboss.dna.connector.federation.contribution.Contribution;
+
+/**
+ * @author Randall Hauch
+ */
+@ThreadSafe
+public class TwoContributionMergePlan extends MergePlan {
+
+ private static final long serialVersionUID = 1L;
+ private final Contribution contribution1;
+ private final Contribution contribution2;
+
+ /**
+ * @param contribution1 the first contribution for this merge plan
+ * @param contribution2 the second contribution for this merge plan
+ */
+ public TwoContributionMergePlan( Contribution contribution1,
+ Contribution contribution2 ) {
+ assert contribution1 != null;
+ assert contribution2 != null;
+ this.contribution1 = contribution1;
+ this.contribution2 = contribution2;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.jboss.dna.connector.federation.merge.MergePlan#getContributionCount()
+ */
+ @Override
+ public int getContributionCount() {
+ return 2;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.jboss.dna.connector.federation.merge.MergePlan#getContributionFrom(java.lang.String)
+ */
+ @Override
+ public Contribution getContributionFrom( String sourceName ) {
+ if (contribution1.getSourceName().equals(sourceName)) return contribution1;
+ if (contribution2.getSourceName().equals(sourceName)) return contribution2;
+ return null;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see java.lang.Iterable#iterator()
+ */
+ public Iterator<Contribution> iterator() {
+ return new Iterator<Contribution>() {
+ private int next = 2;
+
+ public boolean hasNext() {
+ return next > 0;
+ }
+
+ @SuppressWarnings( "synthetic-access" )
+ public Contribution next() {
+ if (next == 2) {
+ next = 1;
+ return contribution1;
+ }
+ if (next == 1) {
+ next = 0;
+ return contribution2;
+ }
+ throw new NoSuchElementException();
+ }
+
+ public void remove() {
+ throw new UnsupportedOperationException();
+ }
+ };
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.jboss.dna.connector.federation.merge.MergePlan#isSource(java.lang.String)
+ */
+ @Override
+ public boolean isSource( String sourceName ) {
+ return contribution1.getSourceName().equals(sourceName) || contribution2.getSourceName().equals(sourceName);
+ }
+
+}
Modified: trunk/connectors/dna-connector-inmemory/src/main/java/org/jboss/dna/connector/inmemory/InMemoryRepository.java
===================================================================
--- trunk/connectors/dna-connector-inmemory/src/main/java/org/jboss/dna/connector/inmemory/InMemoryRepository.java 2008-07-28 15:00:27 UTC (rev 374)
+++ trunk/connectors/dna-connector-inmemory/src/main/java/org/jboss/dna/connector/inmemory/InMemoryRepository.java 2008-07-28 21:51:05 UTC (rev 375)
@@ -49,6 +49,7 @@
import org.jboss.dna.spi.graph.commands.SetPropertiesCommand;
import org.jboss.dna.spi.graph.commands.executor.AbstractCommandExecutor;
import org.jboss.dna.spi.graph.commands.executor.CommandExecutor;
+import org.jboss.dna.spi.graph.impl.BasicPath;
/**
* @author Randall Hauch
@@ -135,6 +136,37 @@
return node;
}
+ /**
+ * Find the lowest existing node along the path.
+ *
+ * @param path the path to the node; may not be null
+ * @return the lowest existing node along the path, or the root node if no node exists on the path
+ */
+ public Path getLowestExistingPath( Path path ) {
+ assert path != null;
+ Node node = getRoot();
+ int segmentNumber = 0;
+ for (Path.Segment segment : path) {
+ Node desiredChild = null;
+ for (Node child : node.getChildren()) {
+ if (child == null) continue;
+ Path.Segment childName = child.getName();
+ if (childName == null) continue;
+ if (childName.equals(segment)) {
+ desiredChild = child;
+ break;
+ }
+ }
+ if (desiredChild != null) {
+ node = desiredChild;
+ } else {
+ return path.subpath(0, segmentNumber);
+ }
+ ++segmentNumber;
+ }
+ return BasicPath.ROOT;
+ }
+
protected UUID generateUuid() {
return UUID.randomUUID();
}
@@ -305,6 +337,10 @@
Path parent = path.getAncestor();
// Look up the parent node, which must exist ...
Node parentNode = getNode(parent);
+ if (parentNode == null) {
+ Path lowestExisting = getLowestExistingPath(parent);
+ throw new PathNotFoundException(path, lowestExisting, InMemoryConnectorI18n.nodeDoesNotExist.text(parent));
+ }
Node node = createNode(getEnvironment(), parentNode, path.getLastSegment().getName());
// Now add the properties to the supplied node ...
for (Property property : command.getProperties()) {
@@ -404,7 +440,8 @@
// Look up the node with the supplied path ...
Node node = InMemoryRepository.this.getNode(path);
if (node == null) {
- throw new PathNotFoundException(path, InMemoryConnectorI18n.nodeDoesNotExist.text(path));
+ Path lowestExisting = getLowestExistingPath(path);
+ throw new PathNotFoundException(path, lowestExisting, InMemoryConnectorI18n.nodeDoesNotExist.text(path));
}
return null;
}
Modified: trunk/connectors/dna-connector-jbosscache/src/main/java/org/jboss/dna/connector/jbosscache/JBossCacheConnection.java
===================================================================
--- trunk/connectors/dna-connector-jbosscache/src/main/java/org/jboss/dna/connector/jbosscache/JBossCacheConnection.java 2008-07-28 15:00:27 UTC (rev 374)
+++ trunk/connectors/dna-connector-jbosscache/src/main/java/org/jboss/dna/connector/jbosscache/JBossCacheConnection.java 2008-07-28 21:51:05 UTC (rev 375)
@@ -35,6 +35,7 @@
import org.jboss.dna.spi.cache.CachePolicy;
import org.jboss.dna.spi.graph.Name;
import org.jboss.dna.spi.graph.Path;
+import org.jboss.dna.spi.graph.PathFactory;
import org.jboss.dna.spi.graph.PathNotFoundException;
import org.jboss.dna.spi.graph.Property;
import org.jboss.dna.spi.graph.PropertyFactory;
@@ -185,6 +186,15 @@
return Fqn.fromElements(pathSegment);
}
+ protected Path getPath( PathFactory factory,
+ Fqn<Path.Segment> fqn ) {
+ Path.Segment[] segments = new Path.Segment[fqn.size()];
+ for (int i = 0; i != segments.length; ++i) {
+ segments[i] = fqn.get(i);
+ }
+ return factory.create(factory.createRootPath(), segments);
+ }
+
protected Node<Name, Object> getNode( ExecutionContext context,
Path path ) {
// Look up the node with the supplied path ...
@@ -192,7 +202,16 @@
Node<Name, Object> node = cache.getNode(fqn);
if (node == null) {
String nodePath = path.getString(context.getNamespaceRegistry());
- throw new PathNotFoundException(path, JBossCacheConnectorI18n.nodeDoesNotExist.text(nodePath));
+ Path lowestExisting = null;
+ while (fqn != null) {
+ fqn = fqn.getParent();
+ node = cache.getNode(fqn);
+ if (node != null) {
+ lowestExisting = getPath(context.getValueFactories().getPathFactory(), fqn);
+ fqn = null;
+ }
+ }
+ throw new PathNotFoundException(path, lowestExisting, JBossCacheConnectorI18n.nodeDoesNotExist.text(nodePath));
}
return node;
Modified: trunk/dna-spi/src/main/java/org/jboss/dna/spi/graph/Path.java
===================================================================
--- trunk/dna-spi/src/main/java/org/jboss/dna/spi/graph/Path.java 2008-07-28 15:00:27 UTC (rev 374)
+++ trunk/dna-spi/src/main/java/org/jboss/dna/spi/graph/Path.java 2008-07-28 21:51:05 UTC (rev 375)
@@ -401,7 +401,7 @@
* @param degree
* @return the ancestor of the supplied degree
* @throws IllegalArgumentException if the degree is negative
- * @throws PathNotFoundException if the degree is greater than the {@link #size() length} of this path
+ * @throws InvalidPathException if the degree is greater than the {@link #size() length} of this path
*/
public Path getAncestor( int degree );
Modified: trunk/dna-spi/src/main/java/org/jboss/dna/spi/graph/PathNotFoundException.java
===================================================================
--- trunk/dna-spi/src/main/java/org/jboss/dna/spi/graph/PathNotFoundException.java 2008-07-28 15:00:27 UTC (rev 374)
+++ trunk/dna-spi/src/main/java/org/jboss/dna/spi/graph/PathNotFoundException.java 2008-07-28 21:51:05 UTC (rev 375)
@@ -31,44 +31,53 @@
private static final long serialVersionUID = -3703984046286975978L;
private final Path path;
+ private final Path lowestAncestorThatDoesExist;
/**
* @param path
+ * @param lowestAncestorThatDoesExist
*/
- public PathNotFoundException( Path path ) {
+ public PathNotFoundException( Path path, Path lowestAncestorThatDoesExist ) {
this.path = path;
+ this.lowestAncestorThatDoesExist = lowestAncestorThatDoesExist;
}
/**
* @param path
+ * @param lowestAncestorThatDoesExist
* @param message
*/
- public PathNotFoundException( Path path,
+ public PathNotFoundException( Path path, Path lowestAncestorThatDoesExist,
String message ) {
super(message);
this.path = path;
+ this.lowestAncestorThatDoesExist = lowestAncestorThatDoesExist;
}
/**
* @param path
+ * @param lowestAncestorThatDoesExist
* @param cause
*/
- public PathNotFoundException( Path path,
+ public PathNotFoundException( Path path, Path lowestAncestorThatDoesExist,
Throwable cause ) {
super(cause);
this.path = path;
+ this.lowestAncestorThatDoesExist = lowestAncestorThatDoesExist;
}
/**
* @param path
+ * @param lowestAncestorThatDoesExist
* @param message
* @param cause
*/
- public PathNotFoundException( Path path,
+ public PathNotFoundException( Path path, Path lowestAncestorThatDoesExist,
String message,
Throwable cause ) {
super(message, cause);
this.path = path;
+ this.lowestAncestorThatDoesExist = lowestAncestorThatDoesExist;
}
/**
@@ -87,4 +96,12 @@
public Path getPath() {
return path;
}
+
+ /**
+ * Get the lowest (closest) existing {@link Path#getAncestor() ancestor} of the {@link #getPath() non-existant path}.
+ * @return the lowest ancestor that does exist
+ */
+ public Path getLowestAncestorThatDoesExist() {
+ return lowestAncestorThatDoesExist;
+ }
}
Modified: trunk/dna-spi/src/main/java/org/jboss/dna/spi/graph/commands/NodeConflictBehavior.java
===================================================================
--- trunk/dna-spi/src/main/java/org/jboss/dna/spi/graph/commands/NodeConflictBehavior.java 2008-07-28 15:00:27 UTC (rev 374)
+++ trunk/dna-spi/src/main/java/org/jboss/dna/spi/graph/commands/NodeConflictBehavior.java 2008-07-28 21:51:05 UTC (rev 375)
@@ -31,6 +31,7 @@
DO_NOT_REPLACE,
APPEND,
- REPLACE;
+ REPLACE,
+ UPDATE;
}
Modified: trunk/dna-spi/src/main/java/org/jboss/dna/spi/graph/commands/impl/BasicCreateNodeCommand.java
===================================================================
--- trunk/dna-spi/src/main/java/org/jboss/dna/spi/graph/commands/impl/BasicCreateNodeCommand.java 2008-07-28 15:00:27 UTC (rev 374)
+++ trunk/dna-spi/src/main/java/org/jboss/dna/spi/graph/commands/impl/BasicCreateNodeCommand.java 2008-07-28 21:51:05 UTC (rev 375)
@@ -21,7 +21,7 @@
*/
package org.jboss.dna.spi.graph.commands.impl;
-import java.util.List;
+import java.util.Collection;
import net.jcip.annotations.NotThreadSafe;
import org.jboss.dna.common.util.StringUtil;
import org.jboss.dna.spi.graph.Path;
@@ -39,7 +39,7 @@
*/
private static final long serialVersionUID = -5452285887178397354L;
private final Path path;
- private final List<Property> properties;
+ private final Collection<Property> properties;
private final NodeConflictBehavior conflictBehavior;
/**
@@ -48,7 +48,7 @@
* @param conflictBehavior the desired behavior when a node exists at the <code>path</code>; may not be null
*/
public BasicCreateNodeCommand( Path path,
- List<Property> properties,
+ Collection<Property> properties,
NodeConflictBehavior conflictBehavior ) {
super();
assert path != null;
Modified: trunk/dna-spi/src/main/java/org/jboss/dna/spi/graph/impl/BasicPath.java
===================================================================
--- trunk/dna-spi/src/main/java/org/jboss/dna/spi/graph/impl/BasicPath.java 2008-07-28 15:00:27 UTC (rev 374)
+++ trunk/dna-spi/src/main/java/org/jboss/dna/spi/graph/impl/BasicPath.java 2008-07-28 21:51:05 UTC (rev 375)
@@ -35,7 +35,6 @@
import org.jboss.dna.spi.graph.InvalidPathException;
import org.jboss.dna.spi.graph.NamespaceRegistry;
import org.jboss.dna.spi.graph.Path;
-import org.jboss.dna.spi.graph.PathNotFoundException;
/**
* A basic implementation of {@link Path}.
@@ -99,7 +98,7 @@
int endIndex = this.segments.size() - degree;
if (endIndex < 0) {
String msg = SpiI18n.pathAncestorDegreeIsInvalid.text(this.getString(), Inflector.getInstance().ordinalize(degree));
- throw new PathNotFoundException(this, msg);
+ throw new InvalidPathException(msg);
}
return subpath(0, endIndex);
}
Modified: trunk/dna-spi/src/test/java/org/jboss/dna/spi/graph/impl/BasicPathTest.java
===================================================================
--- trunk/dna-spi/src/test/java/org/jboss/dna/spi/graph/impl/BasicPathTest.java 2008-07-28 15:00:27 UTC (rev 374)
+++ trunk/dna-spi/src/test/java/org/jboss/dna/spi/graph/impl/BasicPathTest.java 2008-07-28 21:51:05 UTC (rev 375)
@@ -35,7 +35,6 @@
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.PathNotFoundException;
import org.junit.Before;
import org.junit.Test;
@@ -241,7 +240,7 @@
assertThat(path.getAncestor(3), is(ROOT));
}
- @Test( expected = PathNotFoundException.class )
+ @Test( expected = InvalidPathException.class )
public void shouldNotAllowAncestorDegreeLargerThanSize() {
path.getAncestor(path.size() + 1);
}
15 years, 9 months
DNA SVN: r374 - in trunk: sequencers/dna-sequencer-zip and 2 other directories.
by dna-commits@lists.jboss.org
Author: rhauch
Date: 2008-07-28 11:00:27 -0400 (Mon, 28 Jul 2008)
New Revision: 374
Modified:
trunk/pom.xml
trunk/sequencers/dna-sequencer-zip/
trunk/sequencers/dna-sequencer-zip/src/main/java/org/jboss/dna/sequencer/zip/ZipSequencer.java
trunk/sequencers/dna-sequencer-zip/src/test/java/org/jboss/dna/sequencer/zip/SequencingOutputTestClass.java
trunk/sequencers/dna-sequencer-zip/src/test/java/org/jboss/dna/sequencer/zip/ZipSequencerTest.java
Log:
Added ZIP sequencer to parent POM, and updated the signature of the ZIP sequencer implementation to reflect recent changes in the framework.
Modified: trunk/pom.xml
===================================================================
--- trunk/pom.xml 2008-07-28 14:56:25 UTC (rev 373)
+++ trunk/pom.xml 2008-07-28 15:00:27 UTC (rev 374)
@@ -104,6 +104,7 @@
<module>sequencers/dna-sequencer-cnd</module>
<module>sequencers/dna-sequencer-java</module>
<module>sequencers/dna-sequencer-msoffice</module>
+ <module>sequencers/dna-sequencer-zip</module>
<module>connectors/dna-connector-federation</module>
<module>connectors/dna-connector-inmemory</module>
<module>connectors/dna-connector-jbosscache</module>
Property changes on: trunk/sequencers/dna-sequencer-zip
___________________________________________________________________
Name: svn:ignore
+ target
Modified: trunk/sequencers/dna-sequencer-zip/src/main/java/org/jboss/dna/sequencer/zip/ZipSequencer.java
===================================================================
--- trunk/sequencers/dna-sequencer-zip/src/main/java/org/jboss/dna/sequencer/zip/ZipSequencer.java 2008-07-28 14:56:25 UTC (rev 373)
+++ trunk/sequencers/dna-sequencer-zip/src/main/java/org/jboss/dna/sequencer/zip/ZipSequencer.java 2008-07-28 15:00:27 UTC (rev 374)
@@ -22,19 +22,31 @@
package org.jboss.dna.sequencer.zip;
+import java.io.ByteArrayOutputStream;
+import java.io.InputStream;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipInputStream;
+import org.jboss.dna.common.monitor.ProgressMonitor;
+import org.jboss.dna.spi.sequencers.SequencerContext;
+import org.jboss.dna.spi.sequencers.SequencerOutput;
import org.jboss.dna.spi.sequencers.StreamSequencer;
-import org.jboss.dna.spi.sequencers.SequencerOutput;
-import org.jboss.dna.common.monitor.ProgressMonitor;
-import java.io.*;
-import java.util.zip.ZipInputStream;
-import java.util.zip.ZipEntry;
-
/**
* @author Michael Trezzi
*/
public class ZipSequencer implements StreamSequencer {
- public void sequence(InputStream stream, SequencerOutput output, ProgressMonitor progressMonitor) {
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.jboss.dna.spi.sequencers.StreamSequencer#sequence(java.io.InputStream,
+ * org.jboss.dna.spi.sequencers.SequencerOutput, org.jboss.dna.spi.sequencers.SequencerContext,
+ * org.jboss.dna.common.monitor.ProgressMonitor)
+ */
+ public void sequence( InputStream stream,
+ SequencerOutput output,
+ SequencerContext context,
+ ProgressMonitor progressMonitor ) {
try {
ZipInputStream in = new ZipInputStream(stream);
ZipEntry entry = in.getNextEntry();
@@ -42,31 +54,27 @@
// Create top-level node
output.setProperty("zip:content", "jcr:primaryType", "zip:content");
- while (entry != null)
- {
+ while (entry != null) {
- if(entry.isDirectory()) { // If entry is directory, create nt:folder node
- output.setProperty("zip:content/"+entry.getName(), "jcr:primaryType", "nt:folder");
+ if (entry.isDirectory()) { // If entry is directory, create nt:folder node
+ output.setProperty("zip:content/" + entry.getName(), "jcr:primaryType", "nt:folder");
} else { // If entry is File, create nt:file
- output.setProperty("zip:content/"+entry.getName()+"/jcr:content", "jcr:primaryType", "nt:resource" );
+ output.setProperty("zip:content/" + entry.getName() + "/jcr:content", "jcr:primaryType", "nt:resource");
int n;
ByteArrayOutputStream baout = new ByteArrayOutputStream();
while ((n = in.read(buf, 0, 1024)) > -1) {
baout.write(buf, 0, n);
}
- output.setProperty("zip:content/"+entry.getName()+"/jcr:content", "jcr:data", baout.toByteArray());
+ output.setProperty("zip:content/" + entry.getName() + "/jcr:content", "jcr:data", baout.toByteArray());
// all other nt:file properties should be generated by other sequencers (mimetype, encoding,...)
}
in.closeEntry();
entry = in.getNextEntry();
}
- }
- catch (Exception e)
- {
+ } catch (Exception e) {
e.printStackTrace();
}
-
}
}
Modified: trunk/sequencers/dna-sequencer-zip/src/test/java/org/jboss/dna/sequencer/zip/SequencingOutputTestClass.java
===================================================================
--- trunk/sequencers/dna-sequencer-zip/src/test/java/org/jboss/dna/sequencer/zip/SequencingOutputTestClass.java 2008-07-28 14:56:25 UTC (rev 373)
+++ trunk/sequencers/dna-sequencer-zip/src/test/java/org/jboss/dna/sequencer/zip/SequencingOutputTestClass.java 2008-07-28 15:00:27 UTC (rev 374)
@@ -22,45 +22,49 @@
package org.jboss.dna.sequencer.zip;
+import java.util.ArrayList;
+import java.util.List;
+import org.jboss.dna.spi.graph.Name;
+import org.jboss.dna.spi.graph.NamespaceRegistry;
+import org.jboss.dna.spi.graph.Path;
+import org.jboss.dna.spi.graph.ValueFactories;
import org.jboss.dna.spi.sequencers.SequencerOutput;
-import org.jboss.dna.spi.graph.*;
-import org.junit.Test;
import org.junit.Ignore;
-import java.util.Collection;
-import java.util.List;
-import java.util.ArrayList;
-
/**
* @author Michael Trezzi
*/
@Ignore
public class SequencingOutputTestClass implements SequencerOutput {
- List<PropertyClassTest> properties = new ArrayList();
- List<PropertyClassTest> references = new ArrayList();
+ List<PropertyClassTest> properties = new ArrayList<PropertyClassTest>();
+ List<PropertyClassTest> references = new ArrayList<PropertyClassTest>();
-
-
public ValueFactories getFactories() {
return null;
}
-
+
public NamespaceRegistry getNamespaceRegistry() {
return null;
}
- public void setProperty(String nodePath, String propertyName, Object... values) {
- System.out.println("Setting property on '"+nodePath+"' "+propertyName+":"+values[0]);
- properties.add(new PropertyClassTest(nodePath,propertyName,values[0]));
+ public void setProperty( String nodePath,
+ String propertyName,
+ Object... values ) {
+ System.out.println("Setting property on '" + nodePath + "' " + propertyName + ":" + values[0]);
+ properties.add(new PropertyClassTest(nodePath, propertyName, values[0]));
}
- public void setReference(String nodePath, String propertyName, String... paths) {
- System.out.println("Setting reference on "+nodePath+" "+propertyName+":"+paths[0]);
- references.add(new PropertyClassTest(nodePath,propertyName,paths[0]));
+ public void setReference( String nodePath,
+ String propertyName,
+ String... paths ) {
+ System.out.println("Setting reference on " + nodePath + " " + propertyName + ":" + paths[0]);
+ references.add(new PropertyClassTest(nodePath, propertyName, paths[0]));
}
- public void setProperty(Path nodePath, Name propertyName, Object... values) {
- System.out.println("Setting property on "+nodePath.getString()+" "+propertyName.getString()+":"+values[0]);
- properties.add(new PropertyClassTest(nodePath.getString(),propertyName.getString(),values[0]));
+ public void setProperty( Path nodePath,
+ Name propertyName,
+ Object... values ) {
+ System.out.println("Setting property on " + nodePath.getString() + " " + propertyName.getString() + ":" + values[0]);
+ properties.add(new PropertyClassTest(nodePath.getString(), propertyName.getString(), values[0]));
}
}
Modified: trunk/sequencers/dna-sequencer-zip/src/test/java/org/jboss/dna/sequencer/zip/ZipSequencerTest.java
===================================================================
--- trunk/sequencers/dna-sequencer-zip/src/test/java/org/jboss/dna/sequencer/zip/ZipSequencerTest.java 2008-07-28 14:56:25 UTC (rev 373)
+++ trunk/sequencers/dna-sequencer-zip/src/test/java/org/jboss/dna/sequencer/zip/ZipSequencerTest.java 2008-07-28 15:00:27 UTC (rev 374)
@@ -22,12 +22,12 @@
package org.jboss.dna.sequencer.zip;
-import org.junit.Test;
-import org.junit.After;
import static org.hamcrest.core.Is.is;
import static org.junit.Assert.assertThat;
-
import java.io.InputStream;
+import org.jboss.dna.spi.sequencers.SequencerContext;
+import org.junit.After;
+import org.junit.Test;
/**
* @author Michael Trezzi
@@ -54,10 +54,11 @@
public void shouldBeAbleToExtractZip() {
InputStream is = getTestZip("testzip.zip");
ZipSequencer zs = new ZipSequencer();
- SequencingOutputTestClass seqtest = new SequencingOutputTestClass();
- zs.sequence(is,seqtest,null);
+ SequencingOutputTestClass seqtest = new SequencingOutputTestClass();
+ SequencerContext context = null;
+ zs.sequence(is, seqtest, context, null);
assertThat(seqtest.properties.get(2).getPath(), is("zip:content/test subfolder/test2.txt/jcr:content"));
}
-
+
}
15 years, 9 months
DNA SVN: r373 - trunk/sequencers/dna-sequencer-java/src/main/java/org/jboss/dna/sequencer/java.
by dna-commits@lists.jboss.org
Author: rhauch
Date: 2008-07-28 10:56:25 -0400 (Mon, 28 Jul 2008)
New Revision: 373
Modified:
trunk/sequencers/dna-sequencer-java/src/main/java/org/jboss/dna/sequencer/java/AbstractJavaMetadata.java
trunk/sequencers/dna-sequencer-java/src/main/java/org/jboss/dna/sequencer/java/JavaMetadataSequencer.java
Log:
Cleaned up a few warnings.
Modified: trunk/sequencers/dna-sequencer-java/src/main/java/org/jboss/dna/sequencer/java/AbstractJavaMetadata.java
===================================================================
--- trunk/sequencers/dna-sequencer-java/src/main/java/org/jboss/dna/sequencer/java/AbstractJavaMetadata.java 2008-07-26 21:33:14 UTC (rev 372)
+++ trunk/sequencers/dna-sequencer-java/src/main/java/org/jboss/dna/sequencer/java/AbstractJavaMetadata.java 2008-07-28 14:56:25 UTC (rev 373)
@@ -65,7 +65,7 @@
/**
* Abstract definition of a <tt>JavaMetadata<tt>. This class exposes some useful methods, that can
* be used to create meta data of a compilation unit. Methods can also separately be used.
- *
+ *
* @author Serge Pagop
*/
public abstract class AbstractJavaMetadata {
@@ -155,7 +155,7 @@
protected List<TypeMetadata> createTypeMetadata( CompilationUnit unit ) {
List<TypeMetadata> metadata = new ArrayList<TypeMetadata>();
List<AbstractTypeDeclaration> topLevelType = unit.types();
-
+
for (AbstractTypeDeclaration abstractTypeDeclaration : topLevelType) {
// process TypeDeclaration (class, interface)
if (abstractTypeDeclaration instanceof TypeDeclaration) {
@@ -202,13 +202,13 @@
// process EnumDeclaration
if (abstractTypeDeclaration instanceof EnumDeclaration) {
- EnumDeclaration enumDeclaration = (EnumDeclaration)abstractTypeDeclaration;
+ // EnumDeclaration enumDeclaration = (EnumDeclaration)abstractTypeDeclaration;
// TODO get infos from enum declaration and create a enum meta data object.
}
// process annotationTypeDeclaration
if (abstractTypeDeclaration instanceof AnnotationTypeDeclaration) {
- AnnotationTypeDeclaration annotationTypeDeclaration = (AnnotationTypeDeclaration)abstractTypeDeclaration;
+ // AnnotationTypeDeclaration annotationTypeDeclaration = (AnnotationTypeDeclaration)abstractTypeDeclaration;
// TODO get infos from annotation type declaration and create a annotation meta data object.
}
}
Modified: trunk/sequencers/dna-sequencer-java/src/main/java/org/jboss/dna/sequencer/java/JavaMetadataSequencer.java
===================================================================
--- trunk/sequencers/dna-sequencer-java/src/main/java/org/jboss/dna/sequencer/java/JavaMetadataSequencer.java 2008-07-26 21:33:14 UTC (rev 372)
+++ trunk/sequencers/dna-sequencer-java/src/main/java/org/jboss/dna/sequencer/java/JavaMetadataSequencer.java 2008-07-28 14:56:25 UTC (rev 373)
@@ -347,7 +347,7 @@
}
}
if (fieldMetadata instanceof ParameterizedFieldMetadata) {
- ParameterizedFieldMetadata parameterizedFieldMetadata = (ParameterizedFieldMetadata)fieldMetadata;
+ // ParameterizedFieldMetadata parameterizedFieldMetadata = (ParameterizedFieldMetadata)fieldMetadata;
// TODO
}
}
15 years, 9 months
DNA SVN: r372 - in trunk/sequencers/dna-sequencer-java/src: main/java/org/jboss/dna/sequencer/java/metadata and 3 other directories.
by dna-commits@lists.jboss.org
Author: spagop
Date: 2008-07-26 17:33:14 -0400 (Sat, 26 Jul 2008)
New Revision: 372
Modified:
trunk/sequencers/dna-sequencer-java/src/main/java/org/jboss/dna/sequencer/java/AbstractJavaMetadata.java
trunk/sequencers/dna-sequencer-java/src/main/java/org/jboss/dna/sequencer/java/JavaMetadataSequencer.java
trunk/sequencers/dna-sequencer-java/src/main/java/org/jboss/dna/sequencer/java/metadata/ClassMetadata.java
trunk/sequencers/dna-sequencer-java/src/main/java/org/jboss/dna/sequencer/java/metadata/ConstructorMetadata.java
trunk/sequencers/dna-sequencer-java/src/main/java/org/jboss/dna/sequencer/java/metadata/JavaMetadata.java
trunk/sequencers/dna-sequencer-java/src/main/java/org/jboss/dna/sequencer/java/metadata/MethodMetadata.java
trunk/sequencers/dna-sequencer-java/src/main/java/org/jboss/dna/sequencer/java/metadata/ParameterizedFieldMetadata.java
trunk/sequencers/dna-sequencer-java/src/main/java/org/jboss/dna/sequencer/java/metadata/TypeMetadata.java
trunk/sequencers/dna-sequencer-java/src/main/resources/org/jboss/dna/sequencer/java/java-source-artifact.cnd
trunk/sequencers/dna-sequencer-java/src/test/java/org/jboss/dna/sequencer/java/JavaMetadataSequencerTest.java
trunk/sequencers/dna-sequencer-java/src/test/java/org/jboss/dna/sequencer/java/JavaMetadataTest.java
trunk/sequencers/dna-sequencer-java/src/test/workspace/projectX/src/org/acme/MySource.java
Log:
minimal enhancement for the sequencer (imports,fields, methods). Take the support of same-name siblings with index in consideration
Modified: trunk/sequencers/dna-sequencer-java/src/main/java/org/jboss/dna/sequencer/java/AbstractJavaMetadata.java
===================================================================
--- trunk/sequencers/dna-sequencer-java/src/main/java/org/jboss/dna/sequencer/java/AbstractJavaMetadata.java 2008-07-25 20:39:42 UTC (rev 371)
+++ trunk/sequencers/dna-sequencer-java/src/main/java/org/jboss/dna/sequencer/java/AbstractJavaMetadata.java 2008-07-26 21:33:14 UTC (rev 372)
@@ -155,6 +155,7 @@
protected List<TypeMetadata> createTypeMetadata( CompilationUnit unit ) {
List<TypeMetadata> metadata = new ArrayList<TypeMetadata>();
List<AbstractTypeDeclaration> topLevelType = unit.types();
+
for (AbstractTypeDeclaration abstractTypeDeclaration : topLevelType) {
// process TypeDeclaration (class, interface)
if (abstractTypeDeclaration instanceof TypeDeclaration) {
@@ -192,7 +193,7 @@
// methods of the class top level type
MethodDeclaration[] methodDeclarations = typeDeclaration.getMethods();
for (MethodDeclaration methodDeclaration : methodDeclarations) {
- MethodMetadata methodMetadata = getFieldMetadataFrom(methodDeclaration);
+ MethodMetadata methodMetadata = getMethodMetadataFrom(methodDeclaration);
classMetadata.getMethods().add(methodMetadata);
}
metadata.add(classMetadata);
@@ -220,7 +221,7 @@
* @param methodDeclaration - the MethodDeclaration.
* @return methodMetadata - the method meta data.
*/
- private MethodMetadata getFieldMetadataFrom( MethodDeclaration methodDeclaration ) {
+ private MethodMetadata getMethodMetadataFrom( MethodDeclaration methodDeclaration ) {
if (methodDeclaration != null) {
if (methodDeclaration.isConstructor()) {
return getConstructorMetadataFrom(methodDeclaration);
Modified: trunk/sequencers/dna-sequencer-java/src/main/java/org/jboss/dna/sequencer/java/JavaMetadataSequencer.java
===================================================================
--- trunk/sequencers/dna-sequencer-java/src/main/java/org/jboss/dna/sequencer/java/JavaMetadataSequencer.java 2008-07-25 20:39:42 UTC (rev 371)
+++ trunk/sequencers/dna-sequencer-java/src/main/java/org/jboss/dna/sequencer/java/JavaMetadataSequencer.java 2008-07-26 21:33:14 UTC (rev 372)
@@ -24,14 +24,27 @@
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
+import java.util.Map;
import org.apache.commons.lang.StringUtils;
import org.jboss.dna.common.monitor.ProgressMonitor;
import org.jboss.dna.sequencer.java.metadata.AnnotationMetadata;
+import org.jboss.dna.sequencer.java.metadata.ClassMetadata;
+import org.jboss.dna.sequencer.java.metadata.ConstructorMetadata;
+import org.jboss.dna.sequencer.java.metadata.FieldMetadata;
+import org.jboss.dna.sequencer.java.metadata.ImportMetadata;
+import org.jboss.dna.sequencer.java.metadata.ImportOnDemandMetadata;
import org.jboss.dna.sequencer.java.metadata.JavaMetadata;
import org.jboss.dna.sequencer.java.metadata.MarkerAnnotationMetadata;
+import org.jboss.dna.sequencer.java.metadata.MethodMetadata;
+import org.jboss.dna.sequencer.java.metadata.MethodTypeMemberMetadata;
import org.jboss.dna.sequencer.java.metadata.NormalAnnotationMetadata;
import org.jboss.dna.sequencer.java.metadata.PackageMetadata;
+import org.jboss.dna.sequencer.java.metadata.ParameterizedFieldMetadata;
+import org.jboss.dna.sequencer.java.metadata.PrimitiveFieldMetadata;
+import org.jboss.dna.sequencer.java.metadata.SingleImportMetadata;
import org.jboss.dna.sequencer.java.metadata.SingleMemberAnnotationMetadata;
+import org.jboss.dna.sequencer.java.metadata.TypeMetadata;
+import org.jboss.dna.sequencer.java.metadata.Variable;
import org.jboss.dna.spi.graph.NameFactory;
import org.jboss.dna.spi.graph.Path;
import org.jboss.dna.spi.graph.PathFactory;
@@ -47,22 +60,79 @@
* <ul>
* <li><strong>java:compilationUnit</strong> node of type <code>java:compilationUnit</code>
* <ul>
- * <li><strong>java:package</strong> - optional child node that represents the package declaration of the compilation unit</li>
+ * <li> <strong>java:package</strong> - optional child node that represents the package child node of the compilation unit
+ * <ul>
+ * <li> <strong>java:packageDeclaration</strong> -
+ * <ul>
+ * <li><strong>java:packageName</strong></li>
* </ul>
* </li>
* </ul>
+ * </li>
+ * <li> <strong>java:import</strong> - optional child node that represents the import declaration of the compilation unit
+ * <ul>
+ * <li> <strong>java:importDeclaration</strong> -
+ * <ul>
+ * <li> <strong>java:singleTypeImportDeclaration</strong>
+ * <ul>
+ * <li> <strong>java:packageDeclaration</strong> -
+ * <ul>
+ * <li><strong>java:typeName</strong></li>
+ * </ul>
+ * </li>
+ * </ul>
+ * </li>
+ * <li> <strong>java:typeImportOnDemandDeclaration</strong>
+ * <ul>
+ * <li> <strong>java:packageDeclaration</strong> -
+ * <ul>
+ * <li><strong>java:typeName</strong></li>
+ * </ul>
+ * </li>
+ * </ul>
+ * </li>
+ * </ul>
+ * </li>
+ * </ul>
+ * </li>
+ * <li><strong>java:unitType</strong> - optional child node that represents the top level type (class, interface, enum,
+ * annotation) declaration of the compilation unit</li>
+ * <ul>
+ * <li> <strong>java:classDeclaration</strong> - optional child node that represents the class declaration of the compilation
+ * unit
+ * <ul>
+ * <li> <strong>java:normalClass</strong> -
+ * <ul>
+ * <li> <strong>java:normalClassDeclaration</strong> -
+ * <ul>
+ * <li> <strong>java:modifier</strong> - </li>
+ * <li> <strong>java:name</strong> - </li>
+ * <li> <strong>java:field</strong> - </li>
+ * <li> <strong>java:method</strong> - </li>
+ * <li> <strong>java:constructor</strong> - </li>
+ * </ul>
+ * </li>
+ * </ul>
+ * </li>
+ * </ul>
+ * </li>
+ * </ul>
+ * </li>
+ * </ul>
* </p>
*
* @author Serge Pagop
*/
public class JavaMetadataSequencer implements StreamSequencer {
+ private static final String SLASH = "/";
+
public static final String JAVA_COMPILATION_UNIT_NODE = "java:compilationUnit";
public static final String JAVA_COMPILATION_UNIT_PRIMARY_TYPE = "jcr:primaryType";
+ // package declaration
public static final String JAVA_PACKAGE_CHILD_NODE = "java:package";
public static final String JAVA_PACKAGE_DECLARATION_CHILD_NODE = "java:packageDeclaration";
public static final String JAVA_PACKAGE_NAME = "java:packageName";
-
// Annnotation declaration
public static final String JAVA_ANNOTATION_CHILD_NODE = "java:annotation";
public static final String JAVA_ANNOTATION_DECLARATION_CHILD_NODE = "java:annotationDeclaration";
@@ -71,19 +141,40 @@
public static final String JAVA_NORMAL_ANNOTATION_CHILD_NODE = "java:normalAnnotation";
public static final String JAVA_SINGLE_ELEMENT_ANNOTATION_CHILD_NODE = "java:singleElementAnnotation";
public static final String JAVA_ANNOTATION_TYPE_NAME = "java:typeName";
-
// Import declaration
public static final String JAVA_IMPORT_CHILD_NODE = "java:import";
public static final String JAVA_IMPORT_DECLARATION_CHILD_NODE = "java:importDeclaration";
public static final String JAVA_SINGLE_IMPORT_CHILD_NODE = "java:singleImport";
public static final String JAVA_SINGLE_TYPE_IMPORT_DECLARATION_CHILD_NODE = "java:singleTypeImportDeclaration";
-
public static final String JAVA_IMPORT_ON_DEMAND_CHILD_NODE = "java:importOnDemand";
public static final String JAVA_TYPE_IMPORT_ON_DEMAND_DECLARATION_CHILD_NODE = "java:typeImportOnDemandDeclaration";
- public static final String JAVA_IMPORT_TYPE_NAME = "typeName";
+ public static final String JAVA_IMPORT_TYPE_NAME = "java:typeName";
+ // normal class declaration
+ public static final String JAVA_UNIT_TYPE_CHILD_NODE = "java:unitType";
+ public static final String JAVA_CLASS_DECLARATION_CHILD_NODE = "java:classDeclaration";
+ public static final String JAVA_NORMAL_CLASS_CHILD_NODE = "java:normalClass";
+ public static final String JAVA_NORMAL_CLASS_DECLARATION_CHILD_NODE = "java:normalClassDeclaration";
+ public static final String JAVA_CLASS_NAME = "java:name";
+ public static final String JAVA_PUBLIC_CLASS_MODIFIER = "java:modifier";
- private static final String SLASH = "/";
-
+ public static final String JAVA_TYPE_NAME = "java:name";
+ // primitive type
+ public static final String JAVA_FIELD_CHILD_NODE = "java:field";
+ public static final String JAVA_FIELD_TYPE_CHILD_NODE = "java:fieldType";
+ public static final String JAVA_TYPE_CHILD_NODE = "java:type";
+ public static final String JAVA_PRIMITIVE_TYPE_CHILD_NODE = "java:primitiveType";
+
+ // reference type
+ public static final String JAVA_REFERENCE_TYPE_CHILD_NODE = "java:referenceType";
+
+ // method declaration
+ public static final String JAVA_METHOD_CHILD_NODE = "java:method";
+ public static final String JAVA_METHOD_DECLARATION_CHILD_NODE = "java:methodDeclaration";
+ public static final String JAVA_METHOD_NAME = "java:name";
+
+ public static final String JAVA_CONSTRUCTOR_CHILD_NODE = "java:constructor";
+ public static final String JAVA_CONSTRUCTOR_DECLARATION_CHILD_NODE = "java:constructorDeclaration";
+
/**
* {@inheritDoc}
*
@@ -114,11 +205,11 @@
nameFactory.create(JAVA_COMPILATION_UNIT_PRIMARY_TYPE),
"java:compilationUnit");
- // Process package declaration of a unit.
+ // sequence package declaration of a unit.
PackageMetadata packageMetadata = javaMetadata.getPackageMetadata();
if (packageMetadata != null) {
if (StringUtils.isNotEmpty(packageMetadata.getName())) {
-
+
Path javaPackageDeclarationChildNode = pathFactory.create(JAVA_COMPILATION_UNIT_NODE + SLASH
+ JAVA_PACKAGE_CHILD_NODE + SLASH
+ JAVA_PACKAGE_DECLARATION_CHILD_NODE);
@@ -128,58 +219,185 @@
}
List<AnnotationMetadata> annotations = packageMetadata.getAnnotationMetada();
- if (!annotations.isEmpty()) {
- for (AnnotationMetadata annotationMetadata : annotations) {
- if (annotationMetadata instanceof MarkerAnnotationMetadata) {
- MarkerAnnotationMetadata markerAnnotationMetadata = (MarkerAnnotationMetadata)annotationMetadata;
- Path markerAnnotationChildNode = pathFactory.create(JAVA_COMPILATION_UNIT_NODE + SLASH
- + JAVA_PACKAGE_CHILD_NODE + SLASH
- + JAVA_PACKAGE_DECLARATION_CHILD_NODE + SLASH
- + JAVA_ANNOTATION_CHILD_NODE + SLASH
- + JAVA_ANNOTATION_DECLARATION_CHILD_NODE + SLASH
- + JAVA_ANNOTATION_TYPE_CHILD_NODE + SLASH
- + JAVA_MARKER_ANNOTATION_CHILD_NODE);
- output.setProperty(markerAnnotationChildNode,
- nameFactory.create(JAVA_ANNOTATION_TYPE_NAME),
- markerAnnotationMetadata.getName());
+ int markerAnnotationIndex = 1;
+ int singleAnnatationIndex = 1;
+ int normalAnnotationIndex = 1;
+ for (AnnotationMetadata annotationMetadata : annotations) {
+ if (annotationMetadata instanceof MarkerAnnotationMetadata) {
+ MarkerAnnotationMetadata markerAnnotationMetadata = (MarkerAnnotationMetadata)annotationMetadata;
+ Path markerAnnotationChildNode = pathFactory.create(JAVA_COMPILATION_UNIT_NODE + SLASH
+ + JAVA_PACKAGE_CHILD_NODE + SLASH
+ + JAVA_PACKAGE_DECLARATION_CHILD_NODE + SLASH
+ + JAVA_ANNOTATION_CHILD_NODE + SLASH
+ + JAVA_ANNOTATION_DECLARATION_CHILD_NODE + SLASH
+ + JAVA_ANNOTATION_TYPE_CHILD_NODE + SLASH
+ + JAVA_MARKER_ANNOTATION_CHILD_NODE + "["
+ + markerAnnotationIndex + "]");
+ output.setProperty(markerAnnotationChildNode,
+ nameFactory.create(JAVA_ANNOTATION_TYPE_NAME),
+ markerAnnotationMetadata.getName());
+ markerAnnotationIndex++;
+ }
+ if (annotationMetadata instanceof SingleMemberAnnotationMetadata) {
+ SingleMemberAnnotationMetadata singleMemberAnnotationMetadata = (SingleMemberAnnotationMetadata)annotationMetadata;
+ Path singleMemberAnnotationChildNode = pathFactory.create(JAVA_COMPILATION_UNIT_NODE + SLASH
+ + JAVA_PACKAGE_CHILD_NODE + SLASH
+ + JAVA_PACKAGE_DECLARATION_CHILD_NODE + SLASH
+ + JAVA_ANNOTATION_CHILD_NODE + SLASH
+ + JAVA_ANNOTATION_DECLARATION_CHILD_NODE
+ + SLASH + JAVA_ANNOTATION_TYPE_CHILD_NODE
+ + SLASH
+ + JAVA_SINGLE_ELEMENT_ANNOTATION_CHILD_NODE
+ + "[" + singleAnnatationIndex + "]");
+ output.setProperty(singleMemberAnnotationChildNode,
+ nameFactory.create(JAVA_ANNOTATION_TYPE_NAME),
+ singleMemberAnnotationMetadata.getName());
+ singleAnnatationIndex++;
+ }
+ if (annotationMetadata instanceof NormalAnnotationMetadata) {
+ NormalAnnotationMetadata normalAnnotationMetadata = (NormalAnnotationMetadata)annotationMetadata;
+ Path normalAnnotationChildNode = pathFactory.create(JAVA_COMPILATION_UNIT_NODE + SLASH
+ + JAVA_PACKAGE_CHILD_NODE + SLASH
+ + JAVA_PACKAGE_DECLARATION_CHILD_NODE + SLASH
+ + JAVA_ANNOTATION_CHILD_NODE + SLASH
+ + JAVA_ANNOTATION_DECLARATION_CHILD_NODE + SLASH
+ + JAVA_ANNOTATION_TYPE_CHILD_NODE + SLASH
+ + JAVA_NORMAL_ANNOTATION_CHILD_NODE + "["
+ + normalAnnotationIndex + "]");
+
+ output.setProperty(normalAnnotationChildNode,
+ nameFactory.create(JAVA_ANNOTATION_TYPE_NAME),
+ normalAnnotationMetadata.getName());
+ normalAnnotationIndex++;
+ }
+ }
+ }
+
+ // sequence import declarations of a unit
+ List<ImportMetadata> imports = javaMetadata.getImports();
+ int importOnDemandIndex = 1;
+ int singleImportIndex = 1;
+ for (ImportMetadata importMetadata : imports) {
+ if (importMetadata instanceof ImportOnDemandMetadata) {
+ ImportOnDemandMetadata importOnDemandMetadata = (ImportOnDemandMetadata)importMetadata;
+ Path importOnDemandChildNode = pathFactory.create(JAVA_COMPILATION_UNIT_NODE + SLASH + JAVA_IMPORT_CHILD_NODE
+ + SLASH + JAVA_IMPORT_DECLARATION_CHILD_NODE + SLASH
+ + JAVA_IMPORT_ON_DEMAND_CHILD_NODE + SLASH
+ + JAVA_TYPE_IMPORT_ON_DEMAND_DECLARATION_CHILD_NODE + "["
+ + importOnDemandIndex + "]");
+ output.setProperty(importOnDemandChildNode,
+ nameFactory.create(JAVA_IMPORT_TYPE_NAME),
+ importOnDemandMetadata.getName());
+ importOnDemandIndex++;
+ }
+ if (importMetadata instanceof SingleImportMetadata) {
+ SingleImportMetadata singleImportMetadata = (SingleImportMetadata)importMetadata;
+ Path singleImportChildNode = pathFactory.create(JAVA_COMPILATION_UNIT_NODE + SLASH + JAVA_IMPORT_CHILD_NODE
+ + SLASH + JAVA_IMPORT_DECLARATION_CHILD_NODE + SLASH
+ + JAVA_SINGLE_IMPORT_CHILD_NODE + SLASH
+ + JAVA_SINGLE_TYPE_IMPORT_DECLARATION_CHILD_NODE + "["
+ + singleImportIndex + "]");
+ output.setProperty(singleImportChildNode,
+ nameFactory.create(JAVA_IMPORT_TYPE_NAME),
+ singleImportMetadata.getName());
+ singleImportIndex++;
+ }
+ }
+
+ // sequence type declaration (class declaration) information
+ List<TypeMetadata> types = javaMetadata.getTypeMetadata();
+ for (TypeMetadata typeMetadata : types) {
+ // class declaration
+ if (typeMetadata instanceof ClassMetadata) {
+ ClassMetadata classMetadata = (ClassMetadata)typeMetadata;
+ Path classChildNode = pathFactory.create(JAVA_COMPILATION_UNIT_NODE + SLASH + JAVA_UNIT_TYPE_CHILD_NODE
+ + SLASH + JAVA_CLASS_DECLARATION_CHILD_NODE + SLASH
+ + JAVA_NORMAL_CLASS_CHILD_NODE + SLASH
+ + JAVA_NORMAL_CLASS_DECLARATION_CHILD_NODE);
+ output.setProperty(classChildNode, nameFactory.create(JAVA_CLASS_NAME), classMetadata.getName());
+
+ // process modifiers of the class declaration
+ Map<Integer, String> classModifiers = classMetadata.getModifiers();
+ if (!classModifiers.isEmpty()) {
+ String publicModifier = classModifiers.get(TypeMetadata.PUBLIC_MODIFIER);
+ if (publicModifier != null) {
+ output.setProperty(classChildNode, nameFactory.create(JAVA_PUBLIC_CLASS_MODIFIER), publicModifier);
}
- if (annotationMetadata instanceof SingleMemberAnnotationMetadata) {
- SingleMemberAnnotationMetadata singleMemberAnnotationMetadata = (SingleMemberAnnotationMetadata)annotationMetadata;
- Path singleMemberAnnotationChildNode = pathFactory.create(JAVA_COMPILATION_UNIT_NODE + SLASH
- + JAVA_PACKAGE_CHILD_NODE + SLASH
- + JAVA_PACKAGE_DECLARATION_CHILD_NODE
- + SLASH + JAVA_ANNOTATION_CHILD_NODE
- + SLASH
- + JAVA_ANNOTATION_DECLARATION_CHILD_NODE
- + SLASH + JAVA_ANNOTATION_TYPE_CHILD_NODE
- + SLASH
- + JAVA_SINGLE_ELEMENT_ANNOTATION_CHILD_NODE);
- output.setProperty(singleMemberAnnotationChildNode,
- nameFactory.create(JAVA_ANNOTATION_TYPE_NAME),
- singleMemberAnnotationMetadata.getName());
+ }
+ // process fields of the class unit.
+ List<FieldMetadata> fields = classMetadata.getFields();
+ int primitiveIndex = 1;
+ for (FieldMetadata fieldMetadata : fields) {
+ if (fieldMetadata instanceof PrimitiveFieldMetadata) {
+ PrimitiveFieldMetadata primitiveFieldMetadata = (PrimitiveFieldMetadata)fieldMetadata;
+ List<Variable> variables = primitiveFieldMetadata.getVariables();
+ for (Variable variable : variables) {
+ Path primitiveChildNode = pathFactory.create(JAVA_COMPILATION_UNIT_NODE + SLASH
+ + JAVA_UNIT_TYPE_CHILD_NODE + SLASH
+ + JAVA_CLASS_DECLARATION_CHILD_NODE + SLASH
+ + JAVA_NORMAL_CLASS_CHILD_NODE + SLASH
+ + JAVA_NORMAL_CLASS_DECLARATION_CHILD_NODE + SLASH
+ + JAVA_FIELD_CHILD_NODE + SLASH
+ + JAVA_FIELD_TYPE_CHILD_NODE + SLASH
+ + JAVA_TYPE_CHILD_NODE + SLASH
+ + JAVA_PRIMITIVE_TYPE_CHILD_NODE + "["
+ + primitiveIndex + "]");
+ output.setProperty(primitiveChildNode, nameFactory.create(JAVA_TYPE_NAME), variable.getName());
+ primitiveIndex++;
+ }
}
- if (annotationMetadata instanceof NormalAnnotationMetadata) {
- NormalAnnotationMetadata normalAnnotationMetadata = (NormalAnnotationMetadata)annotationMetadata;
- Path normalAnnotationChildNode = pathFactory.create(JAVA_COMPILATION_UNIT_NODE + SLASH
- + JAVA_PACKAGE_CHILD_NODE + SLASH
- + JAVA_PACKAGE_DECLARATION_CHILD_NODE + SLASH
- + JAVA_ANNOTATION_CHILD_NODE + SLASH
- + JAVA_ANNOTATION_DECLARATION_CHILD_NODE + SLASH
- + JAVA_ANNOTATION_TYPE_CHILD_NODE + SLASH
- + JAVA_NORMAL_ANNOTATION_CHILD_NODE);
-
-
- output.setProperty(normalAnnotationChildNode,
- nameFactory.create(JAVA_ANNOTATION_TYPE_NAME),
- normalAnnotationMetadata.getName());
+ if (fieldMetadata instanceof ParameterizedFieldMetadata) {
+ ParameterizedFieldMetadata parameterizedFieldMetadata = (ParameterizedFieldMetadata)fieldMetadata;
+ // TODO
}
}
+
+ // process methods of the unit.
+ List<MethodMetadata> methods = classMetadata.getMethods();
+ int methodIndex = 1;
+ int constructorIndex = 1;
+ for (MethodMetadata methodMetadata : methods) {
+ if (methodMetadata.isContructor()) {
+ // process contructor
+ ConstructorMetadata constructorMetadata = (ConstructorMetadata)methodMetadata;
+
+ Path constructorChildNode = pathFactory.create(JAVA_COMPILATION_UNIT_NODE + SLASH
+ + JAVA_UNIT_TYPE_CHILD_NODE + SLASH
+ + JAVA_CLASS_DECLARATION_CHILD_NODE + SLASH
+ + JAVA_NORMAL_CLASS_CHILD_NODE + SLASH
+ + JAVA_NORMAL_CLASS_DECLARATION_CHILD_NODE + SLASH
+ + JAVA_CONSTRUCTOR_CHILD_NODE + SLASH
+ + JAVA_CONSTRUCTOR_DECLARATION_CHILD_NODE + "["
+ + constructorIndex + "]");
+ output.setProperty(constructorChildNode,
+ nameFactory.create(JAVA_METHOD_NAME),
+ constructorMetadata.getName());
+ constructorIndex++;
+ } else {
+
+ // normal method
+ MethodTypeMemberMetadata methodTypeMemberMetadata = (MethodTypeMemberMetadata)methodMetadata;
+ Path methodChildNode = pathFactory.create(JAVA_COMPILATION_UNIT_NODE + SLASH
+ + JAVA_UNIT_TYPE_CHILD_NODE + SLASH
+ + JAVA_CLASS_DECLARATION_CHILD_NODE + SLASH
+ + JAVA_NORMAL_CLASS_CHILD_NODE + SLASH
+ + JAVA_NORMAL_CLASS_DECLARATION_CHILD_NODE + SLASH
+ + JAVA_METHOD_CHILD_NODE + SLASH
+ + JAVA_METHOD_DECLARATION_CHILD_NODE + "[" + methodIndex
+ + "]");
+ output.setProperty(methodChildNode,
+ nameFactory.create(JAVA_METHOD_NAME),
+ methodTypeMemberMetadata.getName());
+ methodIndex++;
+ }
+ }
}
+ // interface declaration
+
+ // enumeration declaration
}
+ }
- // Process import declarations of a unit
- //TODO write BDD to show how the works
- }
progressMonitor.done();
}
}
Modified: trunk/sequencers/dna-sequencer-java/src/main/java/org/jboss/dna/sequencer/java/metadata/ClassMetadata.java
===================================================================
--- trunk/sequencers/dna-sequencer-java/src/main/java/org/jboss/dna/sequencer/java/metadata/ClassMetadata.java 2008-07-25 20:39:42 UTC (rev 371)
+++ trunk/sequencers/dna-sequencer-java/src/main/java/org/jboss/dna/sequencer/java/metadata/ClassMetadata.java 2008-07-26 21:33:14 UTC (rev 372)
@@ -21,7 +21,6 @@
*/
package org.jboss.dna.sequencer.java.metadata;
-import java.util.List;
/**
Modified: trunk/sequencers/dna-sequencer-java/src/main/java/org/jboss/dna/sequencer/java/metadata/ConstructorMetadata.java
===================================================================
--- trunk/sequencers/dna-sequencer-java/src/main/java/org/jboss/dna/sequencer/java/metadata/ConstructorMetadata.java 2008-07-25 20:39:42 UTC (rev 371)
+++ trunk/sequencers/dna-sequencer-java/src/main/java/org/jboss/dna/sequencer/java/metadata/ConstructorMetadata.java 2008-07-26 21:33:14 UTC (rev 372)
@@ -26,4 +26,16 @@
*/
public class ConstructorMetadata extends MethodMetadata {
+ public ConstructorMetadata() {
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.jboss.dna.sequencer.java.metadata.MethodMetadata#isContructor()
+ */
+ @Override
+ public boolean isContructor() {
+ return true;
+ }
}
Modified: trunk/sequencers/dna-sequencer-java/src/main/java/org/jboss/dna/sequencer/java/metadata/JavaMetadata.java
===================================================================
--- trunk/sequencers/dna-sequencer-java/src/main/java/org/jboss/dna/sequencer/java/metadata/JavaMetadata.java 2008-07-25 20:39:42 UTC (rev 371)
+++ trunk/sequencers/dna-sequencer-java/src/main/java/org/jboss/dna/sequencer/java/metadata/JavaMetadata.java 2008-07-26 21:33:14 UTC (rev 372)
@@ -33,17 +33,16 @@
* @author Serge Pagop
*/
public class JavaMetadata extends AbstractJavaMetadata {
-
+
/** The package representation of a compilation unit. */
private PackageMetadata packageMetadata;
-
+
/** All the import declarations of a compilation unit. */
- private List<ImportMetadata> importMetadata;
-
- /** variables */
-
- /** methods */
+ private List<ImportMetadata> imports;
+ /** Types of unit */
+ private List<TypeMetadata> types;
+
private JavaMetadata() {
}
@@ -75,14 +74,16 @@
CompilationUnit unit = (CompilationUnit)CompilationUnitParser.runJLS3Conversion(source, true);
if (unit != null) {
javaMetadata.packageMetadata = javaMetadata.createPackageMetadata(unit);
- javaMetadata.importMetadata = javaMetadata.createImportMetadata(unit);
+ javaMetadata.imports = javaMetadata.createImportMetadata(unit);
+ javaMetadata.types = javaMetadata.createTypeMetadata(unit);
+
}
return javaMetadata;
}
/**
- * Gets the <code>PackageMetadata</code>.
+ * Gets the {@link PackageMetadata} from the unit.
*
* @return the PackageMetadata or null if there is not package declaration for the unit.
*/
@@ -91,11 +92,20 @@
}
/**
- * Gets a list of <code>ImportMetadata</code>.
+ * Gets a list of {@linkImportMetadata} from the unit.
*
- * @return all the importMetadata of this unit if there is one.
+ * @return all imports of this unit if there is one.
*/
- public List<ImportMetadata> getImportMetadata() {
- return importMetadata;
+ public List<ImportMetadata> getImports() {
+ return imports;
}
+
+ /**
+ * Gets the list for type declarations (class/interface/enum/annotation) of this unit.
+ *
+ * @return all typeMetadata of this unit.
+ */
+ public List<TypeMetadata> getTypeMetadata() {
+ return types;
+ }
}
Modified: trunk/sequencers/dna-sequencer-java/src/main/java/org/jboss/dna/sequencer/java/metadata/MethodMetadata.java
===================================================================
--- trunk/sequencers/dna-sequencer-java/src/main/java/org/jboss/dna/sequencer/java/metadata/MethodMetadata.java 2008-07-25 20:39:42 UTC (rev 371)
+++ trunk/sequencers/dna-sequencer-java/src/main/java/org/jboss/dna/sequencer/java/metadata/MethodMetadata.java 2008-07-26 21:33:14 UTC (rev 372)
@@ -26,7 +26,6 @@
*/
public class MethodMetadata {
private String name;
-
/**
* @return name
*/
@@ -40,5 +39,11 @@
public void setName( String name ) {
this.name = name;
}
-
+
+ /**
+ * @return isContructor
+ */
+ public boolean isContructor() {
+ return false;
+ }
}
Modified: trunk/sequencers/dna-sequencer-java/src/main/java/org/jboss/dna/sequencer/java/metadata/ParameterizedFieldMetadata.java
===================================================================
--- trunk/sequencers/dna-sequencer-java/src/main/java/org/jboss/dna/sequencer/java/metadata/ParameterizedFieldMetadata.java 2008-07-25 20:39:42 UTC (rev 371)
+++ trunk/sequencers/dna-sequencer-java/src/main/java/org/jboss/dna/sequencer/java/metadata/ParameterizedFieldMetadata.java 2008-07-26 21:33:14 UTC (rev 372)
@@ -21,7 +21,6 @@
*/
package org.jboss.dna.sequencer.java.metadata;
-import java.util.List;
/**
* Field meta data for parameterized type.
Modified: trunk/sequencers/dna-sequencer-java/src/main/java/org/jboss/dna/sequencer/java/metadata/TypeMetadata.java
===================================================================
--- trunk/sequencers/dna-sequencer-java/src/main/java/org/jboss/dna/sequencer/java/metadata/TypeMetadata.java 2008-07-25 20:39:42 UTC (rev 371)
+++ trunk/sequencers/dna-sequencer-java/src/main/java/org/jboss/dna/sequencer/java/metadata/TypeMetadata.java 2008-07-26 21:33:14 UTC (rev 372)
@@ -83,6 +83,7 @@
}
/**
+ *
* @return modifiers
*/
public Map<Integer, String> getModifiers() {
@@ -97,7 +98,9 @@
}
/**
- * @return fields of this top level unit.
+ * Gets a ordered lists of {@link FieldMetadata} from the unit.
+ *
+ * @return all fields of this unit if there is one.
*/
public List<FieldMetadata> getFields() {
return this.fields;
@@ -111,7 +114,9 @@
}
/**
- * @return methods of this top level unit.
+ * Gets all {@link MethodMetadata} from the unit.
+ *
+ * @return all methods from the units.
*/
public List<MethodMetadata> getMethods() {
return methods;
Modified: trunk/sequencers/dna-sequencer-java/src/main/resources/org/jboss/dna/sequencer/java/java-source-artifact.cnd
===================================================================
--- trunk/sequencers/dna-sequencer-java/src/main/resources/org/jboss/dna/sequencer/java/java-source-artifact.cnd 2008-07-25 20:39:42 UTC (rev 371)
+++ trunk/sequencers/dna-sequencer-java/src/main/resources/org/jboss/dna/sequencer/java/java-source-artifact.cnd 2008-07-26 21:33:14 UTC (rev 372)
@@ -108,51 +108,38 @@
- java:name (string)
+ java:type (java:primitiveType, java:referenceType) mandatory multiple
-/**
- * No Return type
- */
-[java:noReturnType] > nt:unstructured
- - java:noReturn (string)
- < 'void'
-
-/**
- * Integral type
- */
-[java:integralType] > nt:unstructured
- - java:predefinedIntegralType (string) mandatory
- < 'byte', 'short', 'int', 'long', 'char'
-
-/**
- * Floating point type
- */
-[java:floatingPointType] > nt:unstructured
- - java:predefinedFloatingType (string) mandatory
- < 'float', 'double'
-
/**
- * Primitive type
+ * Primitive type:
+ * - Integral type ('byte', 'short', 'int', 'long', 'char')
+ * - Floating point type ('float', 'double')
+ * - Boolean type ('boolean')
+ * - No return type (''void')
*/
[java:primitiveType] > nt:unstructured
- - java:booleanType (string)
- < 'boolean'
- + java:numericType (java:integralType, java:floatingPointType)
+ - java:description (string)
+ - java:modifier (string)
+ < 'public', 'protected', 'private'
+ - java:declaredAs (string) multiple
+ < 'static','final', 'transient', 'volatile'
+ - java:type (string)
+ < 'byte','short','char','int,'long','float','double','boolean','void'
+ - java:name (string) mandatory
-
/**
* Reference type (TODO to enhance)
*/
[java:referenceType] > nt:unstructured
-
-/**
- * Field type
- */
-[java:fieldType] > nt:unstructured
- - java:description (string)
+- java:description (string)
- java:modifier (string)
- < 'public', 'protected', 'private'
+ < 'public', 'protected', 'private'
- java:declaredAs (string) multiple
< 'static','final', 'transient', 'volatile'
- java:name (string) mandatory
+
+/**
+ * Field type
+ */
+[java:fieldType] > nt:unstructured
+ java:type (java:primitiveType, java:referenceType) mandatory multiple
/**
@@ -162,7 +149,7 @@
- java:description (string)
- java:modifier (string)
< 'public', 'protected', 'private'
- + java:resultType (java:noReturnType, java:primitiveType, java:referenceType) mandatory
+ + java:resultType (java:primitiveType, java:referenceType) mandatory
- java:name (string) mandatory
- java:declaredAs (string) multiple
< 'static','final', 'native', 'strictfp', 'synchronized'
@@ -192,14 +179,14 @@
* Import declarations
*/
[java:singleTypeImportDeclaration] > nt:unstructured
- - keyword (string) mandatory
+ - java:keyword (string) mandatory
< 'import'
- - typeName (string) mandatory
+ - java:typeName (string) mandatory
[java:typeImportOnDemandDeclaration] > nt:unstructured
- - keyword (string) mandatory
+ - java:keyword (string) mandatory
< 'import'
- - typeName (string) mandatory
+ - java:typeName (string) mandatory
[java:importDeclaration] > nt:unstructured
+ java:singleImport (java:singleTypeImportDeclaration) = java:singleTypeImportDeclaration
@@ -244,4 +231,4 @@
[java:compilationUnit] > nt:unstructured
+ java:package (java:packageDeclaration) = java:packageDeclaration
+ java:import (java:importDeclaration) = java:importDeclaration
- + java:type (java:classDeclaration, java:interfaceDeclaration)
\ No newline at end of file
+ + java:unitType (java:classDeclaration, java:interfaceDeclaration)
\ No newline at end of file
Modified: trunk/sequencers/dna-sequencer-java/src/test/java/org/jboss/dna/sequencer/java/JavaMetadataSequencerTest.java
===================================================================
--- trunk/sequencers/dna-sequencer-java/src/test/java/org/jboss/dna/sequencer/java/JavaMetadataSequencerTest.java 2008-07-25 20:39:42 UTC (rev 371)
+++ trunk/sequencers/dna-sequencer-java/src/test/java/org/jboss/dna/sequencer/java/JavaMetadataSequencerTest.java 2008-07-26 21:33:14 UTC (rev 372)
@@ -84,13 +84,67 @@
assertThat(content, is(notNullValue()));
sequencer.sequence(content, output, context, progress);
assertThat(output.getPropertyValues("java:compilationUnit", "jcr:primaryType"), is(new Object[] {"java:compilationUnit"}));
+
+ // sequencing package
assertThat(output.getPropertyValues("java:compilationUnit/java:package/java:packageDeclaration", "java:packageName"),
is(new Object[] {"org.acme"}));
- // TODO (find a solution to get the annotation of a package)
- // assertThat(output.getPropertyValues("java:compilationUnit/java:package/java:packageDeclaration/java:annotation/java:annotationDeclaration/java:annotationType/java:markerAnnotation",
+
+ // TODO (find a solution to get the annotation of a package). Java Sequencer does not yet support sequencing of
+ // package-info.java with package annotations
+ // assertThat(output.getPropertyValues("java:compilationUnit/java:package/java:packageDeclaration/java:annotation/java:annotationDeclaration/java:annotationType/java:markerAnnotation[1]",
// "java:typeName"),
// is(new Object[] {"org.acme.annotation.MyPackageAnnotation"}));
+ // sequence imports
+ assertThat(output.getPropertyValues("java:compilationUnit/java:import/java:importDeclaration/java:singleImport/java:singleTypeImportDeclaration[1]",
+ "java:typeName"),
+ is(new Object[] {"org.acme.annotation.MyClassAnnotation"}));
+ assertThat(output.getPropertyValues("java:compilationUnit/java:import/java:importDeclaration/java:importOnDemand/java:typeImportOnDemandDeclaration[1]",
+ "java:typeName"),
+ is(new Object[] {"java.util"}));
+
+ // sequence class definition
+ assertThat(output.getPropertyValues("java:compilationUnit/java:unitType/java:classDeclaration/java:normalClass/java:normalClassDeclaration",
+ "java:modifier"),
+ is(new Object[] {"public"}));
+ assertThat(output.getPropertyValues("java:compilationUnit/java:unitType/java:classDeclaration/java:normalClass/java:normalClassDeclaration",
+ "java:name"),
+ is(new Object[] {"MySource"}));
+
+ // sequence fields
+ assertThat(output.getPropertyValues("java:compilationUnit/java:unitType/java:classDeclaration/java:normalClass/java:normalClassDeclaration/java:field/java:fieldType/java:type/java:primitiveType[1]",
+ "java:name"),
+ is(new Object[] {"i"}));
+ assertThat(output.getPropertyValues("java:compilationUnit/java:unitType/java:classDeclaration/java:normalClass/java:normalClassDeclaration/java:field/java:fieldType/java:type/java:primitiveType[2]",
+ "java:name"),
+ is(new Object[] {"j"}));
+ assertThat(output.getPropertyValues("java:compilationUnit/java:unitType/java:classDeclaration/java:normalClass/java:normalClassDeclaration/java:field/java:fieldType/java:type/java:primitiveType[3]",
+ "java:name"),
+ is(new Object[] {"a"}));
+ // assertThat(output.getPropertyValues("java:compilationUnit/java:type/java:classDeclaration/java:normalClass/java:normalClassDeclaration/java:field/java:fieldType/java:type/java:referenceType",
+ // "java:name"),
+ // is(new Object[] {"l"}));
+ // assertThat(output.getPropertyValues("java:compilationUnit/java:type/java:classDeclaration/java:normalClass/java:normalClassDeclaration/java:field/java:fieldType/java:type/java:referenceType",
+ // "java:name"),
+ // is(new Object[] {"o"}));
+ // assertThat(output.getPropertyValues("java:compilationUnit/java:type/java:classDeclaration/java:normalClass/java:normalClassDeclaration/java:field/java:fieldType/java:type/java:referenceType",
+ // "java:name"),
+ // is(new Object[] {"x"}));
+
+ assertThat(output.getPropertyValues("java:compilationUnit/java:unitType/java:classDeclaration/java:normalClass/java:normalClassDeclaration/java:constructor/java:constructorDeclaration[1]",
+ "java:name"),
+ is(new Object[] {"MySource"}));
+
+ assertThat(output.getPropertyValues("java:compilationUnit/java:unitType/java:classDeclaration/java:normalClass/java:normalClassDeclaration/java:method/java:methodDeclaration[1]",
+ "java:name"),
+ is(new Object[] {"getI"}));
+ assertThat(output.getPropertyValues("java:compilationUnit/java:unitType/java:classDeclaration/java:normalClass/java:normalClassDeclaration/java:method/java:methodDeclaration[2]",
+ "java:name"),
+ is(new Object[] {"setI"}));
+ assertThat(output.getPropertyValues("java:compilationUnit/java:unitType/java:classDeclaration/java:normalClass/java:normalClassDeclaration/java:method/java:methodDeclaration[4]",
+ "java:name"),
+ is(new Object[] {"doSomething"}));
+
}
}
Modified: trunk/sequencers/dna-sequencer-java/src/test/java/org/jboss/dna/sequencer/java/JavaMetadataTest.java
===================================================================
--- trunk/sequencers/dna-sequencer-java/src/test/java/org/jboss/dna/sequencer/java/JavaMetadataTest.java 2008-07-25 20:39:42 UTC (rev 371)
+++ trunk/sequencers/dna-sequencer-java/src/test/java/org/jboss/dna/sequencer/java/JavaMetadataTest.java 2008-07-26 21:33:14 UTC (rev 372)
@@ -163,45 +163,48 @@
// get fields
List<FieldMetadata> fields = classMetadata.getFields();
assertNotNull(fields);
- assertTrue(fields.size() == 4);
+ assertTrue(fields.size() == 5);
PrimitiveFieldMetadata primitiveFieldMetadata = (PrimitiveFieldMetadata)fields.get(0);
assertThat(primitiveFieldMetadata.getCode(), is("int"));
assertThat(primitiveFieldMetadata.getVariables().get(0).getName(), is("i"));
+ assertThat(primitiveFieldMetadata.getVariables().get(1).getName(), is("j"));
- ParameterizedFieldMetadata parameterizedFieldMetadata1 = (ParameterizedFieldMetadata)fields.get(1);
+ ParameterizedFieldMetadata parameterizedFieldMetadata1 = (ParameterizedFieldMetadata)fields.get(2);
assertNotNull(parameterizedFieldMetadata1);
assertThat(parameterizedFieldMetadata1.getName(), is("List"));
assertThat(parameterizedFieldMetadata1.getVariables().get(0).getName(), is("l"));
- ParameterizedFieldMetadata parameterizedFieldMetadata2 = (ParameterizedFieldMetadata)fields.get(2);
+ ParameterizedFieldMetadata parameterizedFieldMetadata2 = (ParameterizedFieldMetadata)fields.get(3);
assertNotNull(parameterizedFieldMetadata2);
assertThat(parameterizedFieldMetadata2.getName(), is("B"));
assertThat(parameterizedFieldMetadata2.getVariables().get(0).getName(), is("o"));
-
- SimpleFieldMetadata simpleFieldMetadata = (SimpleFieldMetadata)fields.get(3);
+
+ SimpleFieldMetadata simpleFieldMetadata = (SimpleFieldMetadata)fields.get(4);
assertNotNull(simpleFieldMetadata);
assertThat(simpleFieldMetadata.getName(), is("X"));
assertThat(simpleFieldMetadata.getVariables().get(0).getName(), is("x"));
-
+
// get methods
List<MethodMetadata> methods = classMetadata.getMethods();
assertNotNull(methods);
- assertTrue(methods.size() == 4);
-
- ConstructorMetadata constructorMetadata = (ConstructorMetadata)methods.get(0);
+ assertTrue(methods.size() == 5);
+
+ MethodMetadata methodMetadata = methods.get(0);
+ assertTrue(methodMetadata.isContructor());
+ ConstructorMetadata constructorMetadata = (ConstructorMetadata)methodMetadata;
assertNotNull(constructorMetadata);
assertThat(constructorMetadata.getName(), is("MySource"));
-
+
MethodTypeMemberMetadata methodTypeMemberMetadata1 = (MethodTypeMemberMetadata)methods.get(1);
assertNotNull(methodTypeMemberMetadata1);
assertThat(methodTypeMemberMetadata1.getName(), is("getI"));
-
+
MethodTypeMemberMetadata methodTypeMemberMetadata2 = (MethodTypeMemberMetadata)methods.get(2);
assertNotNull(methodTypeMemberMetadata2);
assertThat(methodTypeMemberMetadata2.getName(), is("setI"));
-
- MethodTypeMemberMetadata methodTypeMemberMetadata3 = (MethodTypeMemberMetadata)methods.get(3);
+
+ MethodTypeMemberMetadata methodTypeMemberMetadata3 = (MethodTypeMemberMetadata)methods.get(4);
assertNotNull(methodTypeMemberMetadata3);
assertThat(methodTypeMemberMetadata3.getName(), is("doSomething"));
}
Modified: trunk/sequencers/dna-sequencer-java/src/test/workspace/projectX/src/org/acme/MySource.java
===================================================================
--- trunk/sequencers/dna-sequencer-java/src/test/workspace/projectX/src/org/acme/MySource.java 2008-07-25 20:39:42 UTC (rev 371)
+++ trunk/sequencers/dna-sequencer-java/src/test/workspace/projectX/src/org/acme/MySource.java 2008-07-26 21:33:14 UTC (rev 372)
@@ -29,14 +29,16 @@
*/
@MyClassAnnotation
public class MySource {
-
- private int i;
+
+ private int i, j;
+ private double a;
private List<String> l;
private A<String>.B<Integer> o;
private X x;
-
- public MySource(){}
-
+
+ public MySource() {
+ }
+
public int getI() {
return this.i;
}
@@ -44,35 +46,43 @@
public void setI( int i ) {
this.i = i;
}
-
+
+ public void setJ( int j ) {
+ this.j = j;
+ }
+
public void doSomething() {
- l= new ArrayList<String>();
+ l = new ArrayList<String>();
l.add("N1");
}
-
+
class A<E> {
E e;
-
- A(E e) {
+
+ A( E e ) {
this.e = e;
}
-
+
@Override
public String toString() {
return String.valueOf(this.e);
}
+
class B<T> {
T t;
- B(T t) {
+
+ B( T t ) {
this.t = t;
}
+
@Override
public String toString() {
return String.valueOf(this.t);
}
}
}
+
class X {
-
+
}
}
15 years, 9 months
DNA SVN: r371 - in trunk: connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/executor and 17 other directories.
by dna-commits@lists.jboss.org
Author: rhauch
Date: 2008-07-25 16:39:42 -0400 (Fri, 25 Jul 2008)
New Revision: 371
Added:
trunk/dna-repository/src/main/java/org/jboss/dna/repository/util/BasicJcrExecutionContext.java
trunk/dna-repository/src/main/java/org/jboss/dna/repository/util/JcrExecutionContext.java
trunk/dna-repository/src/test/java/org/jboss/dna/repository/util/MockJcrExecutionContext.java
trunk/dna-spi/src/main/java/org/jboss/dna/spi/ExecutionContext.java
trunk/dna-spi/src/main/java/org/jboss/dna/spi/ExecutionContexts.java
trunk/dna-spi/src/main/java/org/jboss/dna/spi/graph/connection/BasicExecutionContext.java
Removed:
trunk/dna-repository/src/main/java/org/jboss/dna/repository/util/ExecutionContext.java
trunk/dna-repository/src/main/java/org/jboss/dna/repository/util/SimpleExecutionContext.java
trunk/dna-repository/src/test/java/org/jboss/dna/repository/util/MockExecutionContext.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/ExecutionEnvironment.java
trunk/dna-spi/src/main/java/org/jboss/dna/spi/graph/connection/ExecutionEnvironments.java
Modified:
trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/FederatedRepository.java
trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/FederatedRepositoryConnection.java
trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/FederatedRepositorySource.java
trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/Projection.java
trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/ProjectionParser.java
trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/executor/FederatingCommandExecutor.java
trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/executor/SingleProjectionCommandExecutor.java
trunk/connectors/dna-connector-federation/src/test/java/org/jboss/dna/connector/federation/FederatedRepositoryConnectionTest.java
trunk/connectors/dna-connector-federation/src/test/java/org/jboss/dna/connector/federation/FederatedRepositorySourceTest.java
trunk/connectors/dna-connector-federation/src/test/java/org/jboss/dna/connector/federation/FederatedRepositoryTest.java
trunk/connectors/dna-connector-federation/src/test/java/org/jboss/dna/connector/federation/ProjectionPathRuleTest.java
trunk/connectors/dna-connector-federation/src/test/java/org/jboss/dna/connector/federation/ProjectionTest.java
trunk/connectors/dna-connector-inmemory/src/main/java/org/jboss/dna/connector/inmemory/InMemoryRepository.java
trunk/connectors/dna-connector-inmemory/src/main/java/org/jboss/dna/connector/inmemory/InMemoryRepositoryConnection.java
trunk/connectors/dna-connector-inmemory/src/main/java/org/jboss/dna/connector/inmemory/Node.java
trunk/connectors/dna-connector-inmemory/src/test/java/org/jboss/dna/connector/inmemory/InMemoryRepositoryTest.java
trunk/connectors/dna-connector-jbosscache/src/main/java/org/jboss/dna/connector/jbosscache/JBossCacheConnection.java
trunk/dna-repository/src/main/java/org/jboss/dna/repository/RepositoryService.java
trunk/dna-repository/src/main/java/org/jboss/dna/repository/rules/RuleSetRepositoryMonitor.java
trunk/dna-repository/src/main/java/org/jboss/dna/repository/sequencers/Sequencer.java
trunk/dna-repository/src/main/java/org/jboss/dna/repository/sequencers/SequencerNodeContext.java
trunk/dna-repository/src/main/java/org/jboss/dna/repository/sequencers/SequencingService.java
trunk/dna-repository/src/main/java/org/jboss/dna/repository/sequencers/StreamSequencerAdapter.java
trunk/dna-repository/src/test/java/org/jboss/dna/repository/RepositoryServiceTest.java
trunk/dna-repository/src/test/java/org/jboss/dna/repository/sequencers/MockSequencerA.java
trunk/dna-repository/src/test/java/org/jboss/dna/repository/sequencers/MockSequencerB.java
trunk/dna-repository/src/test/java/org/jboss/dna/repository/sequencers/SequencerNodeContextTest.java
trunk/dna-repository/src/test/java/org/jboss/dna/repository/sequencers/SequencingServiceTest.java
trunk/dna-repository/src/test/java/org/jboss/dna/repository/sequencers/StreamSequencerAdapterTest.java
trunk/dna-spi/src/main/java/org/jboss/dna/spi/ExecutionContextFactory.java
trunk/dna-spi/src/main/java/org/jboss/dna/spi/graph/commands/executor/AbstractCommandExecutor.java
trunk/dna-spi/src/main/java/org/jboss/dna/spi/graph/commands/executor/NoOpCommandExecutor.java
trunk/dna-spi/src/main/java/org/jboss/dna/spi/graph/connection/RepositoryConnection.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/connection/RepositoryOperation.java
trunk/dna-spi/src/main/java/org/jboss/dna/spi/graph/connection/RepositoryOperations.java
trunk/dna-spi/src/test/java/org/jboss/dna/spi/graph/commands/executor/AbstractCommandExecutorTest.java
trunk/dna-spi/src/test/java/org/jboss/dna/spi/graph/connection/RepositoryConnectionPoolTest.java
trunk/dna-spi/src/test/java/org/jboss/dna/spi/graph/connection/RepositorySourceLoadHarness.java
trunk/dna-spi/src/test/java/org/jboss/dna/spi/graph/connection/SimpleRepository.java
trunk/dna-spi/src/test/java/org/jboss/dna/spi/graph/connection/SimpleRepositorySource.java
trunk/dna-spi/src/test/java/org/jboss/dna/spi/graph/connection/TimeDelayingRepositorySource.java
trunk/docs/examples/gettingstarted/sequencers/src/main/java/org/jboss/example/dna/sequencers/SequencingClient.java
Log:
DNA-182 - Rename ExecutionEnvironment to ExecutionContext
http://jira.jboss.com/jira/browse/DNA-182
DNA-183 - Add "getSubject()" method to org.jboss.dna.spi.ExecutionContext
http://jira.jboss.com/jira/browse/DNA-183
Renamed the org.jboss.dna.repository.util.ExecutionContext to JcrExecutionContext. This extended org.jboss.dna.spi.graph.connection.ExecutionEnvironment, which was renamed and moved to org.jboss.dna.spi.ExecutionContext. All of the changes involved changing the parameter names, variable names, and JavaDocs.
Also added Subject to ExecutionContext interface and the appropriate implementations.
Modified: trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/FederatedRepository.java
===================================================================
--- trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/FederatedRepository.java 2008-07-25 19:37:40 UTC (rev 370)
+++ trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/FederatedRepository.java 2008-07-25 20:39:42 UTC (rev 371)
@@ -30,8 +30,8 @@
import net.jcip.annotations.ThreadSafe;
import org.jboss.dna.common.util.ArgCheck;
import org.jboss.dna.connector.federation.executor.FederatingCommandExecutor;
+import org.jboss.dna.spi.ExecutionContext;
import org.jboss.dna.spi.graph.commands.executor.CommandExecutor;
-import org.jboss.dna.spi.graph.connection.ExecutionEnvironment;
import org.jboss.dna.spi.graph.connection.RepositoryConnection;
import org.jboss.dna.spi.graph.connection.RepositoryConnectionFactories;
import org.jboss.dna.spi.graph.connection.RepositorySource;
@@ -47,7 +47,7 @@
@ThreadSafe
public class FederatedRepository {
- private final ExecutionEnvironment env;
+ private final ExecutionContext context;
private final RepositoryConnectionFactories connectionFactories;
private FederatedRepositoryConfig config;
private final AtomicInteger openExecutors = new AtomicInteger(0);
@@ -58,18 +58,18 @@
/**
* Create a federated repository instance.
*
- * @param env the execution environment
+ * @param context the execution context
* @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( ExecutionEnvironment env,
+ public FederatedRepository( ExecutionContext context,
RepositoryConnectionFactories connectionFactories,
FederatedRepositoryConfig config ) {
ArgCheck.isNotNull(connectionFactories, "connectionFactories");
- ArgCheck.isNotNull(env, "env");
+ ArgCheck.isNotNull(context, "context");
ArgCheck.isNotNull(config, "config");
- this.env = env;
+ this.context = context;
this.connectionFactories = connectionFactories;
this.config = config;
}
@@ -84,10 +84,10 @@
}
/**
- * @return the execution environment
+ * @return the execution context
*/
- public ExecutionEnvironment getExecutionEnvironment() {
- return env;
+ public ExecutionContext getExecutionContext() {
+ return context;
}
/**
@@ -221,17 +221,17 @@
}
/**
- * Called by
- * {@link FederatedRepositoryConnection#execute(ExecutionEnvironment, org.jboss.dna.spi.graph.commands.GraphCommand...)}.
+ * Called by {@link FederatedRepositoryConnection#execute(ExecutionContext, org.jboss.dna.spi.graph.commands.GraphCommand...)}
+ * .
*
- * @param env the execution environment in which the executor will be run; may not be null
+ * @param context the execution context in which the executor will be run; may not be null
* @param sourceName the name of the {@link RepositorySource} that is making use of this executor; may not be null or empty
* @return the executor
*/
- protected CommandExecutor getExecutor( ExecutionEnvironment env,
+ protected CommandExecutor getExecutor( ExecutionContext context,
String sourceName ) {
FederatedRepositoryConfig config = this.getConfiguration();
- return new FederatingCommandExecutor(env, sourceName, config.getCacheProjection(), config.getSourceProjections(),
+ return new FederatingCommandExecutor(context, sourceName, config.getCacheProjection(), config.getSourceProjections(),
getConnectionFactories());
}
Modified: trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/FederatedRepositoryConnection.java
===================================================================
--- trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/FederatedRepositoryConnection.java 2008-07-25 19:37:40 UTC (rev 370)
+++ trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/FederatedRepositoryConnection.java 2008-07-25 20:39:42 UTC (rev 371)
@@ -25,10 +25,10 @@
import java.util.concurrent.atomic.AtomicReference;
import javax.transaction.xa.XAResource;
import net.jcip.annotations.ThreadSafe;
+import org.jboss.dna.spi.ExecutionContext;
import org.jboss.dna.spi.cache.CachePolicy;
import org.jboss.dna.spi.graph.commands.GraphCommand;
import org.jboss.dna.spi.graph.commands.executor.CommandExecutor;
-import org.jboss.dna.spi.graph.connection.ExecutionEnvironment;
import org.jboss.dna.spi.graph.connection.RepositoryConnection;
import org.jboss.dna.spi.graph.connection.RepositorySourceException;
import org.jboss.dna.spi.graph.connection.RepositorySourceListener;
@@ -111,14 +111,14 @@
/**
* {@inheritDoc}
*/
- public void execute( ExecutionEnvironment env,
+ public void execute( ExecutionContext context,
GraphCommand... commands ) throws RepositorySourceException, InterruptedException {
if (!this.repository.isRunning()) {
throw new RepositorySourceException(FederationI18n.repositoryHasBeenShutDown.text(this.repository.getName()));
}
if (commands == null || commands.length == 0) return;
- CommandExecutor executor = this.repository.getExecutor(env, sourceName);
+ CommandExecutor executor = this.repository.getExecutor(context, sourceName);
assert executor != null;
for (GraphCommand command : commands) {
executor.execute(command);
Modified: trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/FederatedRepositorySource.java
===================================================================
--- trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/FederatedRepositorySource.java 2008-07-25 19:37:40 UTC (rev 370)
+++ trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/FederatedRepositorySource.java 2008-07-25 20:39:42 UTC (rev 371)
@@ -48,6 +48,7 @@
import org.jboss.dna.common.util.StringUtil;
import org.jboss.dna.connector.federation.executor.FederatingCommandExecutor;
import org.jboss.dna.connector.federation.executor.SingleProjectionCommandExecutor;
+import org.jboss.dna.spi.ExecutionContext;
import org.jboss.dna.spi.ExecutionContextFactory;
import org.jboss.dna.spi.cache.BasicCachePolicy;
import org.jboss.dna.spi.cache.CachePolicy;
@@ -67,7 +68,6 @@
import org.jboss.dna.spi.graph.commands.impl.BasicGetChildrenCommand;
import org.jboss.dna.spi.graph.commands.impl.BasicGetNodeCommand;
import org.jboss.dna.spi.graph.connection.AbstractRepositorySource;
-import org.jboss.dna.spi.graph.connection.ExecutionEnvironment;
import org.jboss.dna.spi.graph.connection.RepositoryConnection;
import org.jboss.dna.spi.graph.connection.RepositoryConnectionFactories;
import org.jboss.dna.spi.graph.connection.RepositorySource;
@@ -291,7 +291,7 @@
/**
* Get the name in JNDI of a {@link ExecutionContextFactory} instance that should be used to obtain the
- * {@link ExecutionEnvironment execution context} used by the {@link FederatedRepository federated repository}.
+ * {@link ExecutionContext execution context} used by the {@link FederatedRepository federated repository}.
* <p>
* This is a required property (unless the {@link #getRepositoryJndiName() federated repository is to be found in JDNI}).
* </p>
@@ -306,7 +306,7 @@
/**
* Set the name in JNDI of a {@link ExecutionContextFactory} instance that should be used to obtain the
- * {@link ExecutionEnvironment execution context} used by the {@link FederatedRepository federated repository}.
+ * {@link ExecutionContext execution context} used by the {@link FederatedRepository federated repository}.
* <p>
* This is a required property (unless the {@link #getRepositoryJndiName() federated repository is to be found in JDNI}).
* </p>
@@ -503,16 +503,16 @@
/**
* This method is called to signal that some aspect of the configuration has changed. If a {@link #getRepository() repository}
* instance has been created, it's configuration is
- * {@link #getRepositoryConfiguration(ExecutionEnvironment, RepositoryConnectionFactories) rebuilt} and updated. Nothing is
- * done, however, if there is currently no {@link #getRepository() repository}.
+ * {@link #getRepositoryConfiguration(ExecutionContext, RepositoryConnectionFactories) rebuilt} and updated. Nothing is done,
+ * however, if there is currently no {@link #getRepository() repository}.
*/
protected synchronized void changeRepositoryConfig() {
if (this.repository != null) {
// Find in JNDI the repository connection factories and the environment ...
- ExecutionEnvironment env = getExecutionEnvironment();
+ ExecutionContext context = getExecutionContext();
RepositoryConnectionFactories factories = getRepositoryConnectionFactories();
// Compute a new repository config and set it on the repository ...
- FederatedRepositoryConfig newConfig = getRepositoryConfiguration(env, factories);
+ FederatedRepositoryConfig newConfig = getRepositoryConfiguration(context, factories);
this.repository.setConfiguration(newConfig);
}
}
@@ -555,7 +555,7 @@
* <ol>
* <li>If a {@link FederatedRepository} already was obtained from a prior call, the same instance is returned.</li>
* <li>A {@link FederatedRepository} is created using a {@link FederatedRepositoryConfig} is created from this instance's
- * properties and {@link ExecutionEnvironment} and {@link RepositoryConnectionFactories} instances obtained from JNDI.</li>
+ * properties and {@link ExecutionContext} and {@link RepositoryConnectionFactories} instances obtained from JNDI.</li>
* <li></li>
* <li></li>
* </ol>
@@ -566,12 +566,12 @@
protected synchronized FederatedRepository getRepository() throws RepositorySourceException {
if (repository == null) {
String jndiName = this.getRepositoryJndiName();
- Context context = getContext();
+ Context jndiContext = getContext();
if (jndiName != null && jndiName.trim().length() != 0) {
// Look for an existing repository in JNDI ...
try {
- if (context == null) context = new InitialContext();
- repository = (FederatedRepository)context.lookup(jndiName);
+ if (jndiContext == null) jndiContext = new InitialContext();
+ repository = (FederatedRepository)jndiContext.lookup(jndiName);
} catch (Throwable err) {
I18n msg = FederationI18n.unableToFindFederatedRepositoryInJndi;
throw new RepositorySourceException(msg.text(this.sourceName, jndiName), err);
@@ -580,17 +580,17 @@
if (repository == null) {
// Find in JNDI the repository connection factories and the environment ...
- ExecutionEnvironment env = getExecutionEnvironment();
+ ExecutionContext context = getExecutionContext();
RepositoryConnectionFactories factories = getRepositoryConnectionFactories();
// And create the configuration and the repository ...
- FederatedRepositoryConfig config = getRepositoryConfiguration(env, factories);
- repository = new FederatedRepository(env, factories, config);
+ FederatedRepositoryConfig config = getRepositoryConfiguration(context, factories);
+ repository = new FederatedRepository(context, factories, config);
}
}
return repository;
}
- protected ExecutionEnvironment getExecutionEnvironment() {
+ protected ExecutionContext getExecutionContext() {
ExecutionContextFactory factory = null;
Context context = getContext();
String jndiName = getExecutionContextFactoryJndiName();
@@ -666,22 +666,22 @@
* Create a {@link FederatedRepositoryConfig} instance from the current properties of this instance. This method does
* <i>not</i> modify the state of this instance.
*
- * @param env the execution environment that should be used to read the configuration; may not be null
+ * @param context the execution context that should be used to read the configuration; may not be null
* @param factories the factories from which can be obtained the RepositoryConnectionFactory instances for each name source;
* may not be null
* @return a configuration reflecting the current state of this instance
*/
- protected synchronized FederatedRepositoryConfig getRepositoryConfiguration( ExecutionEnvironment env,
+ protected synchronized FederatedRepositoryConfig getRepositoryConfiguration( ExecutionContext context,
RepositoryConnectionFactories factories ) {
Problems problems = new SimpleProblems();
- ValueFactories valueFactories = env.getValueFactories();
+ ValueFactories valueFactories = context.getValueFactories();
PathFactory pathFactory = valueFactories.getPathFactory();
NameFactory nameFactory = valueFactories.getNameFactory();
ValueFactory<Long> longFactory = valueFactories.getLongFactory();
// Create the configuration projection ...
ProjectionParser projectionParser = ProjectionParser.getInstance();
- Projection.Rule[] rules = projectionParser.rulesFromStrings(env, this.getConfigurationSourceProjectionRules());
+ Projection.Rule[] rules = projectionParser.rulesFromStrings(context, this.getConfigurationSourceProjectionRules());
Projection configurationProjection = new Projection(this.getConfigurationSourceName(), rules);
// Create a federating command executor to execute the commands and merge the results into a single set of
@@ -692,13 +692,13 @@
if (configurationProjection.getRules().size() == 1) {
// There is just a single projection for the configuration repository, so just use an executor that
// translates the paths using the projection
- executor = new SingleProjectionCommandExecutor(env, configurationSourceName, configurationProjection, factories);
+ executor = new SingleProjectionCommandExecutor(context, configurationSourceName, configurationProjection, factories);
} else if (configurationProjection.getRules().size() == 0) {
// There is no projection for the configuration repository, so just use a no-op executor
- executor = new NoOpCommandExecutor(env, configurationSourceName);
+ executor = new NoOpCommandExecutor(context, configurationSourceName);
} else {
// The configuration repository has more than one projection, so we need to merge the results
- executor = new FederatingCommandExecutor(env, configurationSourceName, null, projections, factories);
+ executor = new FederatingCommandExecutor(context, configurationSourceName, null, projections, factories);
}
// Wrap the executor with a logging executor ...
executor = new LoggingCommandExecutor(executor, Logger.getLogger(getClass()), Logger.Level.INFO);
@@ -719,7 +719,7 @@
Path pathToCacheRegion = pathFactory.create(configNode, nameFactory.create("dna:cache"));
BasicGetNodeCommand getCacheRegion = new BasicGetNodeCommand(pathToCacheRegion);
executor.execute(getCacheRegion);
- Projection cacheProjection = createProjection(env,
+ Projection cacheProjection = createProjection(context,
projectionParser,
getCacheRegion.getPath(),
getCacheRegion.getProperties(),
@@ -755,7 +755,7 @@
for (GraphCommand command : commands) {
BasicGetNodeCommand getProjectionCommand = (BasicGetNodeCommand)command;
if (getProjectionCommand.hasNoError()) {
- Projection projection = createProjection(env,
+ Projection projection = createProjection(context,
projectionParser,
getProjectionCommand.getPath(),
getProjectionCommand.getProperties(),
@@ -790,19 +790,19 @@
/**
* Instantiate the {@link Projection} described by the supplied properties.
*
- * @param env the execution environment that should be used to read the configuration; may not be null
+ * @param context the execution context that should be used to read the configuration; may not be null
* @param projectionParser the projection rule parser that should be used; may not be null
* @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
*/
- protected Projection createProjection( ExecutionEnvironment env,
+ protected Projection createProjection( ExecutionContext context,
ProjectionParser projectionParser,
Path path,
Map<Name, Property> properties,
Problems problems ) {
- ValueFactories valueFactories = env.getValueFactories();
+ ValueFactories valueFactories = context.getValueFactories();
NameFactory nameFactory = valueFactories.getNameFactory();
ValueFactory<String> stringFactory = valueFactories.getStringFactory();
@@ -814,7 +814,7 @@
if (projectionRulesProperty != null && !projectionRulesProperty.isEmpty()) {
String[] projectionRuleStrs = stringFactory.create(projectionRulesProperty.getValuesAsArray());
if (projectionRuleStrs != null && projectionRuleStrs.length != 0) {
- projectionRules = projectionParser.rulesFromStrings(env, projectionRuleStrs);
+ projectionRules = projectionParser.rulesFromStrings(context, projectionRuleStrs);
}
}
if (problems.hasErrors()) return null;
Modified: trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/Projection.java
===================================================================
--- trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/Projection.java 2008-07-25 19:37:40 UTC (rev 370)
+++ trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/Projection.java 2008-07-25 20:39:42 UTC (rev 371)
@@ -38,10 +38,10 @@
import org.jboss.dna.common.util.ArgCheck;
import org.jboss.dna.common.util.HashCode;
import org.jboss.dna.common.util.Logger;
+import org.jboss.dna.spi.ExecutionContext;
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.connection.ExecutionEnvironment;
import org.jboss.dna.spi.graph.connection.RepositorySource;
/**
@@ -64,7 +64,7 @@
static {
parserMethods = new CopyOnWriteArrayList<Method>();
try {
- parserMethods.add(Projection.class.getDeclaredMethod("parsePathRule", String.class, ExecutionEnvironment.class));
+ parserMethods.add(Projection.class.getDeclaredMethod("parsePathRule", String.class, ExecutionContext.class));
} catch (Throwable err) {
Logger.getLogger(Projection.class).error(err, FederationI18n.errorAddingProjectionRuleParseMethod);
}
@@ -73,8 +73,8 @@
/**
* Add a static method that can be used to parse {@link Rule#getString(NamespaceRegistry, TextEncoder) rule definition
* strings}. These methods must be static, must accept a {@link String} definition as the first parameter and an
- * {@link ExecutionEnvironment} environment reference as the second parameter, and should return the resulting {@link Rule}
- * (or null if the definition format could not be understood by the method. Any exceptions during
+ * {@link ExecutionContext} environment reference as the second parameter, and should return the resulting {@link Rule} (or
+ * null if the definition format could not be understood by the method. Any exceptions during
* {@link Method#invoke(Object, Object...) invocation} will be logged at the
* {@link Logger#trace(Throwable, String, Object...) trace} level.
*
@@ -88,8 +88,8 @@
/**
* Add a static method that can be used to parse {@link Rule#getString(NamespaceRegistry, TextEncoder) rule definition
* strings}. These methods must be static, must accept a {@link String} definition as the first parameter and an
- * {@link ExecutionEnvironment} environment reference as the second parameter, and should return the resulting {@link Rule}
- * (or null if the definition format could not be understood by the method. Any exceptions during
+ * {@link ExecutionContext} environment reference as the second parameter, and should return the resulting {@link Rule} (or
+ * null if the definition format could not be understood by the method. Any exceptions during
* {@link Method#invoke(Object, Object...) invocation} will be logged at the
* {@link Logger#trace(Throwable, String, Object...) trace} level.
*
@@ -110,7 +110,7 @@
ArgCheck.isNotEmpty(className, "className");
ArgCheck.isNotEmpty(methodName, "methodName");
Class<?> clazz = Class.forName(className, true, classLoader);
- parserMethods.add(clazz.getMethod(className, String.class, ExecutionEnvironment.class));
+ parserMethods.add(clazz.getMethod(className, String.class, ExecutionContext.class));
}
/**
@@ -148,17 +148,17 @@
* Parse the string form of a rule definition and return the rule
*
* @param definition the definition of the rule that is to be parsed
- * @param env the environment in which this method is being executed; may not be null
+ * @param context the environment in which this method is being executed; may not be null
* @return the rule, or null if the definition could not be parsed
*/
public static Rule fromString( String definition,
- ExecutionEnvironment env ) {
- ArgCheck.isNotNull(env, "env");
+ ExecutionContext context ) {
+ ArgCheck.isNotNull(context, "env");
definition = definition != null ? definition.trim() : "";
if (definition.length() == 0) return null;
for (Method method : parserMethods) {
try {
- Rule rule = (Rule)method.invoke(null, definition, env);
+ Rule rule = (Rule)method.invoke(null, definition, context);
if (rule != null) return rule;
} catch (Throwable err) {
String msg = "Error while parsing project rule definition \"{0}\" using {1}";
@@ -201,18 +201,18 @@
* parser methods} by the static initializer of {@link Projection}.
*
* @param definition the definition
- * @param env the environment
+ * @param context the environment
* @return the path rule, or null if the definition is not in the right form
*/
public static PathRule parsePathRule( String definition,
- ExecutionEnvironment env ) {
+ ExecutionContext context ) {
definition = definition != null ? definition.trim() : "";
if (definition.length() == 0) return null;
Matcher matcher = PATH_RULE_PATTERN.matcher(definition);
if (!matcher.find()) return null;
String reposPathStr = matcher.group(1);
String sourcePathStr = matcher.group(2);
- PathFactory pathFactory = env.getValueFactories().getPathFactory();
+ PathFactory pathFactory = context.getValueFactories().getPathFactory();
Path repositoryPath = pathFactory.create(reposPathStr);
Path sourcePath = pathFactory.create(sourcePathStr);
Modified: trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/ProjectionParser.java
===================================================================
--- trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/ProjectionParser.java 2008-07-25 19:37:40 UTC (rev 370)
+++ trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/ProjectionParser.java 2008-07-25 20:39:42 UTC (rev 371)
@@ -31,8 +31,8 @@
import org.jboss.dna.common.util.Logger;
import org.jboss.dna.common.util.StringUtil;
import org.jboss.dna.connector.federation.Projection.Rule;
+import org.jboss.dna.spi.ExecutionContext;
import org.jboss.dna.spi.graph.NamespaceRegistry;
-import org.jboss.dna.spi.graph.connection.ExecutionEnvironment;
/**
* A parser library for {@link Projection projections} and {@link Projection.Rule projection rules}.
@@ -71,8 +71,8 @@
/**
* Add a static method that can be used to parse {@link Rule#getString(NamespaceRegistry, TextEncoder) rule definition
* strings}. These methods must be static, must accept a {@link String} definition as the first parameter and an
- * {@link ExecutionEnvironment} environment reference as the second parameter, and should return the resulting {@link Rule}
- * (or null if the definition format could not be understood by the method. Any exceptions during
+ * {@link ExecutionContext} environment reference as the second parameter, and should return the resulting {@link Rule} (or
+ * null if the definition format could not be understood by the method. Any exceptions during
* {@link Method#invoke(Object, Object...) invocation} will be logged at the
* {@link Logger#trace(Throwable, String, Object...) trace} level.
*
@@ -86,8 +86,8 @@
/**
* Add a static method that can be used to parse {@link Rule#getString(NamespaceRegistry, TextEncoder) rule definition
* strings}. These methods must be static, must accept a {@link String} definition as the first parameter and an
- * {@link ExecutionEnvironment} environment reference as the second parameter, and should return the resulting {@link Rule}
- * (or null if the definition format could not be understood by the method. Any exceptions during
+ * {@link ExecutionContext} environment reference as the second parameter, and should return the resulting {@link Rule} (or
+ * null if the definition format could not be understood by the method. Any exceptions during
* {@link Method#invoke(Object, Object...) invocation} will be logged at the
* {@link Logger#trace(Throwable, String, Object...) trace} level.
*
@@ -103,14 +103,14 @@
String methodName ) throws SecurityException, NoSuchMethodException {
ArgCheck.isNotNull(clazz, "clazz");
ArgCheck.isNotEmpty(methodName, "methodName");
- parserMethods.add(clazz.getMethod(methodName, String.class, ExecutionEnvironment.class));
+ parserMethods.add(clazz.getMethod(methodName, String.class, ExecutionContext.class));
}
/**
* Add a static method that can be used to parse {@link Rule#getString(NamespaceRegistry, TextEncoder) rule definition
* strings}. These methods must be static, must accept a {@link String} definition as the first parameter and an
- * {@link ExecutionEnvironment} environment reference as the second parameter, and should return the resulting {@link Rule}
- * (or null if the definition format could not be understood by the method. Any exceptions during
+ * {@link ExecutionContext} environment reference as the second parameter, and should return the resulting {@link Rule} (or
+ * null if the definition format could not be understood by the method. Any exceptions during
* {@link Method#invoke(Object, Object...) invocation} will be logged at the
* {@link Logger#trace(Throwable, String, Object...) trace} level.
*
@@ -131,7 +131,7 @@
ArgCheck.isNotEmpty(className, "className");
ArgCheck.isNotEmpty(methodName, "methodName");
Class<?> clazz = Class.forName(className, true, classLoader);
- parserMethods.add(clazz.getMethod(methodName, String.class, ExecutionEnvironment.class));
+ parserMethods.add(clazz.getMethod(methodName, String.class, ExecutionContext.class));
}
/**
@@ -176,17 +176,17 @@
* Parse the string form of a rule definition and return the rule
*
* @param definition the definition of the rule that is to be parsed
- * @param env the environment in which this method is being executed; may not be null
+ * @param context the environment in which this method is being executed; may not be null
* @return the rule, or null if the definition could not be parsed
*/
public Rule ruleFromString( String definition,
- ExecutionEnvironment env ) {
- ArgCheck.isNotNull(env, "env");
+ ExecutionContext context ) {
+ ArgCheck.isNotNull(context, "env");
definition = definition != null ? definition.trim() : "";
if (definition.length() == 0) return null;
for (Method method : parserMethods) {
try {
- Rule rule = (Rule)method.invoke(null, definition, env);
+ Rule rule = (Rule)method.invoke(null, definition, context);
if (rule != null) {
if (logger.isTraceEnabled()) {
String msg = "Success parsing project rule definition \"{0}\" using {1}";
@@ -208,15 +208,15 @@
/**
* Parse string forms of an arry of rule definitions and return the rules
*
- * @param env the environment in which this method is being executed; may not be null
+ * @param context the environment in which this method is being executed; may not be null
* @param definitions the definition of the rules that are to be parsed
* @return the rule, or null if the definition could not be parsed
*/
- public Rule[] rulesFromStrings( ExecutionEnvironment env,
+ public Rule[] rulesFromStrings( ExecutionContext context,
String... definitions ) {
List<Rule> rules = new LinkedList<Rule>();
for (String definition : definitions) {
- Rule rule = ruleFromString(definition, env);
+ Rule rule = ruleFromString(definition, context);
if (rule != null) rules.add(rule);
}
return rules.toArray(new Rule[rules.size()]);
@@ -226,16 +226,16 @@
* Parse a single string containing one or more string forms of rule definitions, and return the rules. The string contains
* each rule on a separate line.
*
- * @param env the environment in which this method is being executed; may not be null
+ * @param context the environment in which this method is being executed; may not be null
* @param definitions the definitions of the rules that are to be parsed, each definition separated by a newline character.
* @return the rule, or null if the definition could not be parsed
*/
- public Rule[] rulesFromString( ExecutionEnvironment env,
+ public Rule[] rulesFromString( ExecutionContext context,
String definitions ) {
List<String> lines = StringUtil.splitLines(definitions);
List<Rule> rules = new LinkedList<Rule>();
for (String definition : lines) {
- Rule rule = ruleFromString(definition, env);
+ Rule rule = ruleFromString(definition, context);
if (rule != null) rules.add(rule);
}
return rules.toArray(new Rule[rules.size()]);
Modified: trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/executor/FederatingCommandExecutor.java
===================================================================
--- trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/executor/FederatingCommandExecutor.java 2008-07-25 19:37:40 UTC (rev 370)
+++ trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/executor/FederatingCommandExecutor.java 2008-07-25 20:39:42 UTC (rev 371)
@@ -34,6 +34,7 @@
import org.jboss.dna.connector.federation.Projection;
import org.jboss.dna.connector.federation.contribution.Contribution;
import org.jboss.dna.connector.federation.merge.BasicMergePlan;
+import org.jboss.dna.spi.ExecutionContext;
import org.jboss.dna.spi.graph.Binary;
import org.jboss.dna.spi.graph.DateTime;
import org.jboss.dna.spi.graph.Name;
@@ -46,7 +47,6 @@
import org.jboss.dna.spi.graph.commands.executor.AbstractCommandExecutor;
import org.jboss.dna.spi.graph.commands.impl.BasicGetNodeCommand;
import org.jboss.dna.spi.graph.commands.impl.BasicGetPropertiesCommand;
-import org.jboss.dna.spi.graph.connection.ExecutionEnvironment;
import org.jboss.dna.spi.graph.connection.RepositoryConnection;
import org.jboss.dna.spi.graph.connection.RepositoryConnectionFactories;
import org.jboss.dna.spi.graph.connection.RepositoryConnectionFactory;
@@ -72,20 +72,19 @@
/**
* Create a command executor that federates (merges) the information from multiple sources described by the source
* projections. The resulting command executor does not first consult a cache for the merged information; if a cache is
- * desired, see
- * {@link #FederatingCommandExecutor(ExecutionEnvironment, String, Projection, List, RepositoryConnectionFactories)
+ * desired, see {@link #FederatingCommandExecutor(ExecutionContext, String, Projection, List, RepositoryConnectionFactories)
* constructor} that takes a {@link Projection cache projection}.
*
- * @param env the execution environment in which the executor will be run; may not be null
+ * @param context the execution context in which the executor will be run; may not be null
* @param sourceName the name of the {@link RepositorySource} that is making use of this executor; may not be null or empty
* @param sourceProjections the source projections; may not be null
* @param connectionFactories the factory for connection factory instances
*/
- public FederatingCommandExecutor( ExecutionEnvironment env,
+ public FederatingCommandExecutor( ExecutionContext context,
String sourceName,
List<Projection> sourceProjections,
RepositoryConnectionFactories connectionFactories ) {
- this(env, sourceName, null, sourceProjections, connectionFactories);
+ this(context, sourceName, null, sourceProjections, connectionFactories);
}
/**
@@ -95,25 +94,25 @@
* how the paths are mapped in the cache. This cache will be consulted first for the requested information, and will be kept
* up to date as changes are made to the federated information.
*
- * @param env the execution environment in which the executor will be run; may not be null
+ * @param context the execution context in which the executor will be run; may not be null
* @param sourceName the name of the {@link RepositorySource} that is making use of this executor; may not be null or empty
* @param cacheProjection the projection used for the cached information; may be null if there is no cache
* @param sourceProjections the source projections; may not be null
* @param connectionFactories the factory for connection factory instances
*/
- public FederatingCommandExecutor( ExecutionEnvironment env,
+ public FederatingCommandExecutor( ExecutionContext context,
String sourceName,
Projection cacheProjection,
List<Projection> sourceProjections,
RepositoryConnectionFactories connectionFactories ) {
- super(env, sourceName);
+ super(context, sourceName);
assert sourceProjections != null;
assert connectionFactories != null;
this.cacheProjection = cacheProjection;
this.sourceProjections = sourceProjections;
this.connectionFactories = connectionFactories;
this.connectionsBySourceName = new HashMap<String, RepositoryConnection>();
- this.mergePlanPropertyName = env.getValueFactories().getNameFactory().create("dna:mergePlan");
+ this.mergePlanPropertyName = context.getValueFactories().getNameFactory().create("dna:mergePlan");
this.sourceNames = new HashSet<String>();
}
Modified: trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/executor/SingleProjectionCommandExecutor.java
===================================================================
--- trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/executor/SingleProjectionCommandExecutor.java 2008-07-25 19:37:40 UTC (rev 370)
+++ trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/executor/SingleProjectionCommandExecutor.java 2008-07-25 20:39:42 UTC (rev 371)
@@ -24,6 +24,7 @@
import java.util.Set;
import net.jcip.annotations.NotThreadSafe;
import org.jboss.dna.connector.federation.Projection;
+import org.jboss.dna.spi.ExecutionContext;
import org.jboss.dna.spi.graph.DateTime;
import org.jboss.dna.spi.graph.Path;
import org.jboss.dna.spi.graph.PathFactory;
@@ -38,7 +39,6 @@
import org.jboss.dna.spi.graph.commands.RecordBranchCommand;
import org.jboss.dna.spi.graph.commands.SetPropertiesCommand;
import org.jboss.dna.spi.graph.commands.executor.AbstractCommandExecutor;
-import org.jboss.dna.spi.graph.connection.ExecutionEnvironment;
import org.jboss.dna.spi.graph.connection.RepositoryConnection;
import org.jboss.dna.spi.graph.connection.RepositoryConnectionFactories;
import org.jboss.dna.spi.graph.connection.RepositoryConnectionFactory;
@@ -57,39 +57,39 @@
private RepositoryConnection connection;
/**
- * @param env the execution environment in which the executor will be run; may not be null
+ * @param context the execution context in which the executor will be run; may not be null
* @param sourceName the name of the {@link RepositorySource} that is making use of this executor; may not be null or empty
* @param projection the projection used for the cached information; may not be null and must have exactly one
* {@link Projection#getRules() rule}
* @param connectionFactories the factory for connection factory instances
*/
- public SingleProjectionCommandExecutor( ExecutionEnvironment env,
+ public SingleProjectionCommandExecutor( ExecutionContext context,
String sourceName,
Projection projection,
RepositoryConnectionFactories connectionFactories ) {
- this(env, sourceName, null, projection, connectionFactories);
+ this(context, sourceName, null, projection, connectionFactories);
}
/**
- * @param env the execution environment in which the executor will be run; may not be null
+ * @param context the execution context in which the executor will be run; may not be null
* @param sourceName the name of the {@link RepositorySource} that is making use of this executor; may not be null or empty
* @param now the current time; may be null if the system time is to be used
* @param projection the projection used for the cached information; may not be null and must have exactly one
* {@link Projection#getRules() rule}
* @param connectionFactories the factory for connection factory instances
*/
- public SingleProjectionCommandExecutor( ExecutionEnvironment env,
+ public SingleProjectionCommandExecutor( ExecutionContext context,
String sourceName,
DateTime now,
Projection projection,
RepositoryConnectionFactories connectionFactories ) {
- super(env, sourceName, now);
+ super(context, sourceName, now);
assert connectionFactories != null;
assert projection != null;
assert projection.getRules().size() == 1;
this.projection = projection;
this.factories = connectionFactories;
- this.pathFactory = env.getValueFactories().getPathFactory();
+ this.pathFactory = context.getValueFactories().getPathFactory();
assert this.pathFactory != null;
}
Modified: trunk/connectors/dna-connector-federation/src/test/java/org/jboss/dna/connector/federation/FederatedRepositoryConnectionTest.java
===================================================================
--- trunk/connectors/dna-connector-federation/src/test/java/org/jboss/dna/connector/federation/FederatedRepositoryConnectionTest.java 2008-07-25 19:37:40 UTC (rev 370)
+++ trunk/connectors/dna-connector-federation/src/test/java/org/jboss/dna/connector/federation/FederatedRepositoryConnectionTest.java 2008-07-25 20:39:42 UTC (rev 371)
@@ -29,9 +29,9 @@
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import java.util.concurrent.TimeUnit;
+import org.jboss.dna.spi.ExecutionContext;
import org.jboss.dna.spi.graph.commands.GraphCommand;
import org.jboss.dna.spi.graph.commands.executor.CommandExecutor;
-import org.jboss.dna.spi.graph.connection.ExecutionEnvironment;
import org.jboss.dna.spi.graph.connection.RepositorySourceException;
import org.jboss.dna.spi.graph.connection.RepositorySourceListener;
import org.junit.Before;
@@ -79,28 +79,28 @@
@Test( expected = RepositorySourceException.class )
public void shouldFailExecutionIfRepositoryAdminsIsNotStarted() throws Exception {
stub(repository.isRunning()).toReturn(false);
- ExecutionEnvironment env = mock(ExecutionEnvironment.class);
+ ExecutionContext context = mock(ExecutionContext.class);
GraphCommand command = mock(GraphCommand.class);
- connection.execute(env, command);
+ connection.execute(context, command);
}
@Test
public void shouldReturnImmediatelyWhenExecutingNullOrEmptyCommandArray() throws Exception {
stub(repository.isRunning()).toReturn(true);
- ExecutionEnvironment env = mock(ExecutionEnvironment.class);
- connection.execute(env, (GraphCommand[])null);
+ ExecutionContext context = mock(ExecutionContext.class);
+ connection.execute(context, (GraphCommand[])null);
verify(repository, times(1)).isRunning();
- connection.execute(env, new GraphCommand[0]);
+ connection.execute(context, new GraphCommand[0]);
verify(repository, times(2)).isRunning();
}
@Test
public void shouldSkipNullCommandReferencesWhenExecuting() throws Exception {
stub(repository.isRunning()).toReturn(true);
- ExecutionEnvironment env = mock(ExecutionEnvironment.class);
+ ExecutionContext context = mock(ExecutionContext.class);
CommandExecutor executor = mock(CommandExecutor.class);
- stub(repository.getExecutor(env, sourceName)).toReturn(executor);
- connection.execute(env, new GraphCommand[] {null, null, null});
+ stub(repository.getExecutor(context, sourceName)).toReturn(executor);
+ connection.execute(context, new GraphCommand[] {null, null, null});
verify(repository, times(1)).isRunning();
}
Modified: trunk/connectors/dna-connector-federation/src/test/java/org/jboss/dna/connector/federation/FederatedRepositorySourceTest.java
===================================================================
--- trunk/connectors/dna-connector-federation/src/test/java/org/jboss/dna/connector/federation/FederatedRepositorySourceTest.java 2008-07-25 19:37:40 UTC (rev 370)
+++ trunk/connectors/dna-connector-federation/src/test/java/org/jboss/dna/connector/federation/FederatedRepositorySourceTest.java 2008-07-25 20:39:42 UTC (rev 371)
@@ -39,9 +39,9 @@
import javax.naming.Reference;
import javax.security.auth.callback.CallbackHandler;
import javax.security.auth.login.LoginException;
+import org.jboss.dna.spi.ExecutionContext;
import org.jboss.dna.spi.ExecutionContextFactory;
-import org.jboss.dna.spi.graph.connection.BasicExecutionEnvironment;
-import org.jboss.dna.spi.graph.connection.ExecutionEnvironment;
+import org.jboss.dna.spi.graph.connection.BasicExecutionContext;
import org.jboss.dna.spi.graph.connection.RepositoryConnection;
import org.jboss.dna.spi.graph.connection.RepositoryConnectionFactories;
import org.jboss.dna.spi.graph.connection.RepositorySourceException;
@@ -70,7 +70,7 @@
private String securityDomain;
private SimpleRepository configRepository;
private SimpleRepositorySource configRepositorySource;
- private ExecutionEnvironment env;
+ private ExecutionContext context;
@Mock
private RepositoryConnection connection;
@Mock
@@ -86,8 +86,8 @@
@Before
public void beforeEach() throws Exception {
MockitoAnnotations.initMocks(this);
- env = new BasicExecutionEnvironment();
- env.getNamespaceRegistry().register("dna", "http://www.jboss.org/dna");
+ context = new BasicExecutionContext();
+ context.getNamespaceRegistry().register("dna", "http://www.jboss.org/dna");
executionContextFactoryJndiName = "context factory jndi name";
connectionFactoriesJndiName = "connection factories jndi name";
configurationSourceName = "configuration source name";
@@ -107,14 +107,14 @@
source.setContext(jndiContext);
source.setSecurityDomain(securityDomain);
configRepository = new SimpleRepository("Configuration Repository");
- configRepository.setProperty(env, "/dna:repositories/Test Repository", "dna:timeToExpire", "100000");
- configRepository.setProperty(env, "/dna:repositories/Test Repository", "dna:timeToCache", "100000");
- configRepository.setProperty(env, "/dna:repositories/Test Repository/dna:cache", "dna:projectionRules", "/ => /");
- configRepository.setProperty(env,
+ configRepository.setProperty(context, "/dna:repositories/Test Repository", "dna:timeToExpire", "100000");
+ configRepository.setProperty(context, "/dna:repositories/Test Repository", "dna:timeToCache", "100000");
+ configRepository.setProperty(context, "/dna:repositories/Test Repository/dna:cache", "dna:projectionRules", "/ => /");
+ configRepository.setProperty(context,
"/dna:repositories/Test Repository/dna:projections/source 1/",
"dna:projectionRules",
"/ => /s1");
- configRepository.setProperty(env,
+ configRepository.setProperty(context,
"/dna:repositories/Test Repository/dna:projections/source 2/",
"dna:projectionRules",
"/ => /s1");
@@ -124,7 +124,7 @@
stub(connectionFactories.getConnectionFactory(configurationSourceName)).toReturn(configRepositorySource);
stub(jndiContext.lookup(executionContextFactoryJndiName)).toReturn(executionContextFactory);
stub(jndiContext.lookup(connectionFactoriesJndiName)).toReturn(connectionFactories);
- stub(executionContextFactory.create(eq(securityDomain), anyCallbackHandler())).toReturn(env);
+ stub(executionContextFactory.create(eq(securityDomain), anyCallbackHandler())).toReturn(context);
}
protected static CallbackHandler anyCallbackHandler() {
Modified: trunk/connectors/dna-connector-federation/src/test/java/org/jboss/dna/connector/federation/FederatedRepositoryTest.java
===================================================================
--- trunk/connectors/dna-connector-federation/src/test/java/org/jboss/dna/connector/federation/FederatedRepositoryTest.java 2008-07-25 19:37:40 UTC (rev 370)
+++ trunk/connectors/dna-connector-federation/src/test/java/org/jboss/dna/connector/federation/FederatedRepositoryTest.java 2008-07-25 20:39:42 UTC (rev 371)
@@ -27,8 +27,8 @@
import static org.hamcrest.core.IsSame.sameInstance;
import static org.junit.Assert.assertThat;
import static org.junit.matchers.JUnitMatchers.hasItems;
-import org.jboss.dna.spi.graph.connection.BasicExecutionEnvironment;
-import org.jboss.dna.spi.graph.connection.ExecutionEnvironment;
+import org.jboss.dna.spi.ExecutionContext;
+import org.jboss.dna.spi.graph.connection.BasicExecutionContext;
import org.jboss.dna.spi.graph.connection.RepositoryConnectionFactories;
import org.jboss.dna.spi.graph.connection.RepositorySourceListener;
import org.junit.Before;
@@ -41,7 +41,7 @@
*/
public class FederatedRepositoryTest {
- private ExecutionEnvironment env;
+ private ExecutionContext context;
private FederatedRepository repository;
@Mock
private FederatedRepositoryConfig config;
@@ -57,8 +57,8 @@
@Before
public void beforeEach() {
MockitoAnnotations.initMocks(this);
- env = new BasicExecutionEnvironment();
- repository = new FederatedRepository(env, connectionFactories, config);
+ context = new BasicExecutionContext();
+ repository = new FederatedRepository(context, connectionFactories, config);
}
@Test
Modified: trunk/connectors/dna-connector-federation/src/test/java/org/jboss/dna/connector/federation/ProjectionPathRuleTest.java
===================================================================
--- trunk/connectors/dna-connector-federation/src/test/java/org/jboss/dna/connector/federation/ProjectionPathRuleTest.java 2008-07-25 19:37:40 UTC (rev 370)
+++ trunk/connectors/dna-connector-federation/src/test/java/org/jboss/dna/connector/federation/ProjectionPathRuleTest.java 2008-07-25 20:39:42 UTC (rev 371)
@@ -28,11 +28,11 @@
import static org.junit.matchers.JUnitMatchers.hasItems;
import org.jboss.dna.common.text.TextEncoder;
import org.jboss.dna.common.text.UrlEncoder;
+import org.jboss.dna.spi.ExecutionContext;
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.connection.BasicExecutionEnvironment;
-import org.jboss.dna.spi.graph.connection.ExecutionEnvironment;
+import org.jboss.dna.spi.graph.connection.BasicExecutionContext;
import org.junit.Before;
import org.junit.Test;
@@ -41,7 +41,7 @@
*/
public class ProjectionPathRuleTest {
- private ExecutionEnvironment env;
+ private ExecutionContext context;
private Projection.PathRule rule;
private PathFactory pathFactory;
private Path repositoryPath;
@@ -52,9 +52,9 @@
@Before
public void beforeEach() {
- env = new BasicExecutionEnvironment();
- pathFactory = env.getValueFactories().getPathFactory();
- registry = env.getNamespaceRegistry();
+ context = new BasicExecutionContext();
+ pathFactory = context.getValueFactories().getPathFactory();
+ registry = context.getNamespaceRegistry();
encoder = new UrlEncoder();
repositoryPath = pathFactory.create("/a/b/c");
sourcePath = pathFactory.create("/x/y");
Modified: trunk/connectors/dna-connector-federation/src/test/java/org/jboss/dna/connector/federation/ProjectionTest.java
===================================================================
--- trunk/connectors/dna-connector-federation/src/test/java/org/jboss/dna/connector/federation/ProjectionTest.java 2008-07-25 19:37:40 UTC (rev 370)
+++ trunk/connectors/dna-connector-federation/src/test/java/org/jboss/dna/connector/federation/ProjectionTest.java 2008-07-25 20:39:42 UTC (rev 371)
@@ -26,11 +26,10 @@
import static org.junit.matchers.JUnitMatchers.hasItems;
import static org.mockito.Mockito.stub;
import java.util.Set;
-import org.jboss.dna.connector.federation.Projection;
+import org.jboss.dna.spi.ExecutionContext;
import org.jboss.dna.spi.graph.Path;
import org.jboss.dna.spi.graph.PathFactory;
-import org.jboss.dna.spi.graph.connection.BasicExecutionEnvironment;
-import org.jboss.dna.spi.graph.connection.ExecutionEnvironment;
+import org.jboss.dna.spi.graph.connection.BasicExecutionContext;
import org.junit.Before;
import org.junit.Test;
import org.mockito.MockitoAnnotations;
@@ -41,7 +40,7 @@
*/
public class ProjectionTest {
- private ExecutionEnvironment env;
+ private ExecutionContext context;
private String sourceName;
private Projection.Rule[] rules;
private Projection projection;
@@ -56,8 +55,8 @@
@Before
public void beforeEach() {
MockitoAnnotations.initMocks(this);
- env = new BasicExecutionEnvironment();
- pathFactory = env.getValueFactories().getPathFactory();
+ context = new BasicExecutionContext();
+ pathFactory = context.getValueFactories().getPathFactory();
sourceName = "Valid name";
rules = new Projection.Rule[] {mockRule1, mockRule2, mockRule3};
projection = new Projection(sourceName, rules);
Modified: trunk/connectors/dna-connector-inmemory/src/main/java/org/jboss/dna/connector/inmemory/InMemoryRepository.java
===================================================================
--- trunk/connectors/dna-connector-inmemory/src/main/java/org/jboss/dna/connector/inmemory/InMemoryRepository.java 2008-07-25 19:37:40 UTC (rev 370)
+++ trunk/connectors/dna-connector-inmemory/src/main/java/org/jboss/dna/connector/inmemory/InMemoryRepository.java 2008-07-25 20:39:42 UTC (rev 371)
@@ -31,6 +31,7 @@
import java.util.concurrent.locks.ReentrantReadWriteLock;
import net.jcip.annotations.NotThreadSafe;
import org.jboss.dna.common.util.ArgCheck;
+import org.jboss.dna.spi.ExecutionContext;
import org.jboss.dna.spi.graph.Name;
import org.jboss.dna.spi.graph.Path;
import org.jboss.dna.spi.graph.PathNotFoundException;
@@ -48,7 +49,6 @@
import org.jboss.dna.spi.graph.commands.SetPropertiesCommand;
import org.jboss.dna.spi.graph.commands.executor.AbstractCommandExecutor;
import org.jboss.dna.spi.graph.commands.executor.CommandExecutor;
-import org.jboss.dna.spi.graph.connection.ExecutionEnvironment;
/**
* @author Randall Hauch
@@ -99,11 +99,11 @@
return nodesByUuid;
}
- public Node getNode( ExecutionEnvironment env,
+ public Node getNode( ExecutionContext context,
String path ) {
- assert env != null;
+ assert context != null;
assert path != null;
- return getNode(env.getValueFactories().getPathFactory().create(path));
+ return getNode(context.getValueFactories().getPathFactory().create(path));
}
/**
@@ -139,15 +139,15 @@
return UUID.randomUUID();
}
- public void removeNode( ExecutionEnvironment env,
+ public void removeNode( ExecutionContext context,
Node node ) {
- assert env != null;
+ assert context != null;
assert node != null;
assert getRoot().equals(node) != true;
Node parent = node.getParent();
assert parent != null;
parent.getChildren().remove(node);
- correctSameNameSiblingIndexes(env, parent, node.getName().getName());
+ correctSameNameSiblingIndexes(context, parent, node.getName().getName());
removeUuidReference(node);
}
@@ -161,47 +161,47 @@
/**
* Create a node at the supplied path. The parent of the new node must already exist.
*
- * @param env the environment; may not be null
+ * @param context the environment; may not be null
* @param pathToNewNode the path to the new node; may not be null
* @return the new node (or root if the path specified the root)
*/
- public Node createNode( ExecutionEnvironment env,
+ public Node createNode( ExecutionContext context,
String pathToNewNode ) {
- assert env != null;
+ assert context != null;
assert pathToNewNode != null;
- Path path = env.getValueFactories().getPathFactory().create(pathToNewNode);
+ Path path = context.getValueFactories().getPathFactory().create(pathToNewNode);
if (path.isRoot()) return getRoot();
Path parentPath = path.getAncestor();
Node parentNode = getNode(parentPath);
Name name = path.getLastSegment().getName();
- return createNode(env, parentNode, name);
+ return createNode(context, parentNode, name);
}
/**
* Create a new node with the supplied name, as a child of the supplied parent.
*
- * @param env the execution environment
+ * @param context the execution context
* @param parentNode the parent node; may not be null
* @param name the name; may not be null
* @return the new node
*/
- public Node createNode( ExecutionEnvironment env,
+ public Node createNode( ExecutionContext context,
Node parentNode,
Name name ) {
- assert env != null;
+ assert context != null;
assert name != null;
if (parentNode == null) parentNode = getRoot();
Node node = new Node(generateUuid());
nodesByUuid.put(node.getUuid(), node);
node.setParent(parentNode);
- Path.Segment newName = env.getValueFactories().getPathFactory().createSegment(name);
+ Path.Segment newName = context.getValueFactories().getPathFactory().createSegment(name);
node.setName(newName);
parentNode.getChildren().add(node);
- correctSameNameSiblingIndexes(env, parentNode, name);
+ correctSameNameSiblingIndexes(context, parentNode, name);
return node;
}
- protected void correctSameNameSiblingIndexes( ExecutionEnvironment env,
+ protected void correctSameNameSiblingIndexes( ExecutionContext context,
Node parentNode,
Name name ) {
if (parentNode == null) return;
@@ -213,7 +213,7 @@
if (childrenWithSameNames.size() == 0) return;
if (childrenWithSameNames.size() == 1) {
Node childWithSameName = childrenWithSameNames.get(0);
- Path.Segment newName = env.getValueFactories().getPathFactory().createSegment(name, Path.NO_INDEX);
+ Path.Segment newName = context.getValueFactories().getPathFactory().createSegment(name, Path.NO_INDEX);
childWithSameName.setName(newName);
return;
}
@@ -221,7 +221,7 @@
for (Node childWithSameName : childrenWithSameNames) {
Path.Segment segment = childWithSameName.getName();
if (segment.getIndex() != index) {
- Path.Segment newName = env.getValueFactories().getPathFactory().createSegment(name, index);
+ Path.Segment newName = context.getValueFactories().getPathFactory().createSegment(name, index);
childWithSameName.setName(newName);
}
++index;
@@ -232,14 +232,14 @@
* Move the supplied node to the new parent. This method automatically removes the node from its existing parent, and also
* correctly adjusts the {@link Path.Segment#getIndex() index} to be correct in the new parent.
*
- * @param env
+ * @param context
* @param node the node to be moved; may not be the {@link #getRoot() root}
* @param newParent the new parent; may not be the {@link #getRoot() root}
*/
- public void moveNode( ExecutionEnvironment env,
+ public void moveNode( ExecutionContext context,
Node node,
Node newParent ) {
- assert env != null;
+ assert context != null;
assert newParent != null;
assert node != null;
assert getRoot().equals(newParent) != true;
@@ -250,22 +250,22 @@
boolean removed = oldParent.getChildren().remove(node);
assert removed == true;
node.setParent(null);
- correctSameNameSiblingIndexes(env, oldParent, node.getName().getName());
+ correctSameNameSiblingIndexes(context, oldParent, node.getName().getName());
}
node.setParent(newParent);
newParent.getChildren().add(node);
- correctSameNameSiblingIndexes(env, newParent, node.getName().getName());
+ correctSameNameSiblingIndexes(context, newParent, node.getName().getName());
}
- public int copyNode( ExecutionEnvironment env,
+ public int copyNode( ExecutionContext context,
Node original,
Node newParent,
boolean recursive ) {
- assert env != null;
+ assert context != null;
assert original != null;
assert newParent != null;
// Get or create the new node ...
- Node copy = createNode(env, newParent, original.getName().getName());
+ Node copy = createNode(context, newParent, original.getName().getName());
// Copy the properties ...
copy.getProperties().clear();
@@ -274,7 +274,7 @@
if (recursive) {
// Loop over each child and call this method ...
for (Node child : original.getChildren()) {
- numNodesCopied += copyNode(env, child, copy, true);
+ numNodesCopied += copyNode(context, child, copy, true);
}
}
return numNodesCopied;
@@ -283,20 +283,20 @@
/**
* Get a command executor given the supplied environment and source name.
*
- * @param env the environment in which the commands are to be executed
+ * @param context the environment in which the commands are to be executed
* @param sourceName the name of the repository source
* @return the executor; never null
*/
- public CommandExecutor getCommandExecutor( ExecutionEnvironment env,
+ public CommandExecutor getCommandExecutor( ExecutionContext context,
String sourceName ) {
- return new Executor(env, sourceName);
+ return new Executor(context, sourceName);
}
protected class Executor extends AbstractCommandExecutor {
- protected Executor( ExecutionEnvironment env,
+ protected Executor( ExecutionContext context,
String sourceName ) {
- super(env, sourceName);
+ super(context, sourceName);
}
@Override
Modified: trunk/connectors/dna-connector-inmemory/src/main/java/org/jboss/dna/connector/inmemory/InMemoryRepositoryConnection.java
===================================================================
--- trunk/connectors/dna-connector-inmemory/src/main/java/org/jboss/dna/connector/inmemory/InMemoryRepositoryConnection.java 2008-07-25 19:37:40 UTC (rev 370)
+++ trunk/connectors/dna-connector-inmemory/src/main/java/org/jboss/dna/connector/inmemory/InMemoryRepositoryConnection.java 2008-07-25 20:39:42 UTC (rev 371)
@@ -24,11 +24,11 @@
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;
import javax.transaction.xa.XAResource;
+import org.jboss.dna.spi.ExecutionContext;
import org.jboss.dna.spi.cache.CachePolicy;
import org.jboss.dna.spi.graph.commands.ActsAsUpdate;
import org.jboss.dna.spi.graph.commands.GraphCommand;
import org.jboss.dna.spi.graph.commands.executor.CommandExecutor;
-import org.jboss.dna.spi.graph.connection.ExecutionEnvironment;
import org.jboss.dna.spi.graph.connection.RepositoryConnection;
import org.jboss.dna.spi.graph.connection.RepositorySourceException;
import org.jboss.dna.spi.graph.connection.RepositorySourceListener;
@@ -111,7 +111,7 @@
* @throws InterruptedException
* @throws RepositorySourceException
*/
- public void execute( ExecutionEnvironment env,
+ public void execute( ExecutionContext context,
GraphCommand... commands ) throws RepositorySourceException, InterruptedException {
// Do any commands update/write?
Lock lock = this.content.getLock().readLock();
@@ -124,7 +124,7 @@
try {
// Obtain the lock and execute the commands ...
- CommandExecutor executor = this.content.getCommandExecutor(env, this.getSourceName());
+ CommandExecutor executor = this.content.getCommandExecutor(context, this.getSourceName());
lock.lock();
for (GraphCommand command : commands) {
executor.execute(command);
Modified: trunk/connectors/dna-connector-inmemory/src/main/java/org/jboss/dna/connector/inmemory/Node.java
===================================================================
--- trunk/connectors/dna-connector-inmemory/src/main/java/org/jboss/dna/connector/inmemory/Node.java 2008-07-25 19:37:40 UTC (rev 370)
+++ trunk/connectors/dna-connector-inmemory/src/main/java/org/jboss/dna/connector/inmemory/Node.java 2008-07-25 20:39:42 UTC (rev 371)
@@ -27,11 +27,11 @@
import java.util.Map;
import java.util.UUID;
import net.jcip.annotations.NotThreadSafe;
+import org.jboss.dna.spi.ExecutionContext;
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.PropertyFactory;
-import org.jboss.dna.spi.graph.connection.ExecutionEnvironment;
/**
* @author Randall Hauch
@@ -106,17 +106,17 @@
return this;
}
- public Node setProperty( ExecutionEnvironment env,
+ public Node setProperty( ExecutionContext context,
String name,
Object... values ) {
- PropertyFactory propertyFactory = env.getPropertyFactory();
- Name propertyName = env.getValueFactories().getNameFactory().create(name);
+ PropertyFactory propertyFactory = context.getPropertyFactory();
+ Name propertyName = context.getValueFactories().getNameFactory().create(name);
return setProperty(propertyFactory.create(propertyName, values));
}
- public Property getProperty( ExecutionEnvironment env,
+ public Property getProperty( ExecutionContext context,
String name ) {
- Name propertyName = env.getValueFactories().getNameFactory().create(name);
+ Name propertyName = context.getValueFactories().getNameFactory().create(name);
return getProperty(propertyName);
}
Modified: trunk/connectors/dna-connector-inmemory/src/test/java/org/jboss/dna/connector/inmemory/InMemoryRepositoryTest.java
===================================================================
--- trunk/connectors/dna-connector-inmemory/src/test/java/org/jboss/dna/connector/inmemory/InMemoryRepositoryTest.java 2008-07-25 19:37:40 UTC (rev 370)
+++ trunk/connectors/dna-connector-inmemory/src/test/java/org/jboss/dna/connector/inmemory/InMemoryRepositoryTest.java 2008-07-25 20:39:42 UTC (rev 371)
@@ -32,6 +32,7 @@
import java.util.HashSet;
import java.util.Set;
import java.util.UUID;
+import org.jboss.dna.spi.ExecutionContext;
import org.jboss.dna.spi.graph.Name;
import org.jboss.dna.spi.graph.NameFactory;
import org.jboss.dna.spi.graph.PathFactory;
@@ -39,7 +40,6 @@
import org.jboss.dna.spi.graph.PropertyFactory;
import org.jboss.dna.spi.graph.ValueFactories;
import org.jboss.dna.spi.graph.ValueFactory;
-import org.jboss.dna.spi.graph.connection.ExecutionEnvironment;
import org.jboss.dna.spi.graph.impl.BasicNamespaceRegistry;
import org.jboss.dna.spi.graph.impl.BasicPropertyFactory;
import org.jboss.dna.spi.graph.impl.StandardValueFactories;
@@ -61,7 +61,7 @@
private NameFactory nameFactory;
private PropertyFactory propertyFactory;
@Mock
- private ExecutionEnvironment env;
+ private ExecutionContext context;
@Before
public void beforeEach() throws Exception {
@@ -73,8 +73,8 @@
name = "Test repository";
rootUuid = UUID.randomUUID();
repository = new InMemoryRepository(name, rootUuid);
- stub(env.getValueFactories()).toReturn(valueFactories);
- stub(env.getPropertyFactory()).toReturn(propertyFactory);
+ stub(context.getValueFactories()).toReturn(valueFactories);
+ stub(context.getPropertyFactory()).toReturn(propertyFactory);
}
@Test( expected = IllegalArgumentException.class )
@@ -117,13 +117,13 @@
@Test( expected = AssertionError.class )
public void shouldNotAllowRootToBeRemoved() {
- repository.removeNode(env, repository.getRoot());
+ repository.removeNode(context, repository.getRoot());
}
@Test( expected = AssertionError.class )
public void shouldNotAllowRootToBeMoved() {
Node node = mock(Node.class);
- repository.moveNode(env, repository.getRoot(), node);
+ repository.moveNode(context, repository.getRoot(), node);
}
@Test( expected = AssertionError.class )
@@ -136,7 +136,7 @@
@Test( expected = AssertionError.class )
public void shouldNotAllowNullNodeToBeMoved() {
Node newParent = mock(Node.class);
- repository.moveNode(env, null, newParent);
+ repository.moveNode(context, null, newParent);
}
@Test( expected = AssertionError.class )
@@ -147,27 +147,27 @@
@Test( expected = AssertionError.class )
public void shouldNotAllowNullNodeToBeRemoved() {
- repository.removeNode(env, null);
+ repository.removeNode(context, null);
}
@Test
public void shouldCreateNodesByPath() {
Name name_a = nameFactory.create("a");
- Node node_a = repository.createNode(env, repository.getRoot(), name_a);
+ Node node_a = repository.createNode(context, repository.getRoot(), name_a);
assertThat(node_a, is(notNullValue()));
assertThat(node_a.getParent(), is(repository.getRoot()));
assertThat(node_a.getName().getName(), is(name_a));
assertThat(node_a.getName().hasIndex(), is(false));
Name name_b = nameFactory.create("b");
- Node node_b = repository.createNode(env, node_a, name_b);
+ Node node_b = repository.createNode(context, node_a, name_b);
assertThat(node_b, is(notNullValue()));
assertThat(node_b.getParent(), is(node_a));
assertThat(node_b.getName().getName(), is(name_b));
assertThat(node_b.getName().hasIndex(), is(false));
Name name_c = nameFactory.create("c");
- Node node_c = repository.createNode(env, node_b, name_c);
+ Node node_c = repository.createNode(context, node_b, name_c);
assertThat(node_c, is(notNullValue()));
assertThat(node_c.getParent(), is(node_b));
assertThat(node_c.getName().getName(), is(name_c));
@@ -182,9 +182,9 @@
@Test
public void shouldNotFindNodesThatDoNotExist() {
- Node node_a = repository.createNode(env, repository.getRoot(), nameFactory.create("a"));
- Node node_b = repository.createNode(env, node_a, nameFactory.create("b"));
- /*Node node_c =*/repository.createNode(env, node_b, nameFactory.create("c"));
+ Node node_a = repository.createNode(context, repository.getRoot(), nameFactory.create("a"));
+ Node node_b = repository.createNode(context, node_a, nameFactory.create("b"));
+ /*Node node_c =*/repository.createNode(context, node_b, nameFactory.create("c"));
assertThat(repository.getNodesByUuid().size(), is(4));
assertThat(repository.getNode(pathFactory.create("/a[1]")), is(nullValue()));
@@ -194,14 +194,14 @@
@Test
public void shouldCorrectlyManageIndexesOfSiblingsWithSameNames() {
Name name_a1 = nameFactory.create("a");
- Node node_a1 = repository.createNode(env, repository.getRoot(), name_a1);
+ Node node_a1 = repository.createNode(context, repository.getRoot(), name_a1);
assertThat(node_a1, is(notNullValue()));
assertThat(node_a1.getParent(), is(repository.getRoot()));
assertThat(node_a1.getName().getName(), is(name_a1));
assertThat(node_a1.getName().hasIndex(), is(false));
Name name_a2 = nameFactory.create("a");
- Node node_a2 = repository.createNode(env, repository.getRoot(), name_a2);
+ Node node_a2 = repository.createNode(context, repository.getRoot(), name_a2);
assertThat(node_a2, is(notNullValue()));
assertThat(node_a2.getParent(), is(repository.getRoot()));
assertThat(node_a2.getName().getName(), is(name_a2));
@@ -213,7 +213,7 @@
// Add another node without the same name ...
Name name_b = nameFactory.create("b");
- Node node_b = repository.createNode(env, repository.getRoot(), name_b);
+ Node node_b = repository.createNode(context, repository.getRoot(), name_b);
assertThat(node_b, is(notNullValue()));
assertThat(node_b.getParent(), is(repository.getRoot()));
assertThat(node_b.getName().getName(), is(name_b));
@@ -221,7 +221,7 @@
// Add a third node with the same name ...
Name name_a3 = nameFactory.create("a");
- Node node_a3 = repository.createNode(env, repository.getRoot(), name_a3);
+ Node node_a3 = repository.createNode(context, repository.getRoot(), name_a3);
assertThat(node_a3, is(notNullValue()));
assertThat(node_a3.getParent(), is(repository.getRoot()));
assertThat(node_a3.getName().getName(), is(name_a3));
@@ -238,7 +238,7 @@
assertThat(repository.getNode(pathFactory.create("/b")), is(sameInstance(node_b)));
// Removing a node with the same name will reduce the index ...
- repository.removeNode(env, node_a2);
+ repository.removeNode(context, node_a2);
assertThat(repository.getRoot().getChildren().size(), is(3));
assertThat(repository.getRoot().getChildren(), hasItems(node_a1, node_b, node_a3));
assertThat(node_a1.getName().getIndex(), is(1));
@@ -246,7 +246,7 @@
assertThat(node_a3.getName().getIndex(), is(2));
// Removing a node with the same name will reduce the index ...
- repository.removeNode(env, node_a1);
+ repository.removeNode(context, node_a1);
assertThat(repository.getRoot().getChildren().size(), is(2));
assertThat(repository.getRoot().getChildren(), hasItems(node_b, node_a3));
assertThat(node_b.getName().hasIndex(), is(false));
@@ -257,12 +257,12 @@
@Test
public void shouldMoveNodes() {
Node root = repository.getRoot();
- Node node_a = repository.createNode(env, root, nameFactory.create("a"));
- Node node_b = repository.createNode(env, node_a, nameFactory.create("b"));
- Node node_c = repository.createNode(env, node_b, nameFactory.create("c"));
- Node node_d = repository.createNode(env, root, nameFactory.create("d"));
- Node node_e = repository.createNode(env, node_d, nameFactory.create("e"));
- Node node_b2 = repository.createNode(env, node_d, nameFactory.create("b"));
+ Node node_a = repository.createNode(context, root, nameFactory.create("a"));
+ Node node_b = repository.createNode(context, node_a, nameFactory.create("b"));
+ Node node_c = repository.createNode(context, node_b, nameFactory.create("c"));
+ Node node_d = repository.createNode(context, root, nameFactory.create("d"));
+ Node node_e = repository.createNode(context, node_d, nameFactory.create("e"));
+ Node node_b2 = repository.createNode(context, node_d, nameFactory.create("b"));
assertThat(repository.getNodesByUuid().size(), is(7));
assertThat(repository.getNode(pathFactory.create("/")), is(sameInstance(repository.getRoot())));
@@ -273,7 +273,7 @@
assertThat(repository.getNode(pathFactory.create("/d/e")), is(sameInstance(node_e)));
assertThat(repository.getNode(pathFactory.create("/d/b")), is(sameInstance(node_b2)));
- repository.moveNode(env, node_b, node_d);
+ repository.moveNode(context, node_b, node_d);
assertThat(repository.getNode(pathFactory.create("/")), is(sameInstance(repository.getRoot())));
assertThat(repository.getNode(pathFactory.create("/a")), is(sameInstance(node_a)));
@@ -283,7 +283,7 @@
assertThat(repository.getNode(pathFactory.create("/d/b[2]")), is(sameInstance(node_b)));
assertThat(repository.getNode(pathFactory.create("/d/b[2]/c")), is(sameInstance(node_c)));
- repository.moveNode(env, node_b, node_e);
+ repository.moveNode(context, node_b, node_e);
assertThat(repository.getNode(pathFactory.create("/")), is(sameInstance(repository.getRoot())));
assertThat(repository.getNode(pathFactory.create("/a")), is(sameInstance(node_a)));
@@ -297,12 +297,12 @@
@Test
public void shouldCopyNodes() {
Node root = repository.getRoot();
- Node node_a = repository.createNode(env, root, nameFactory.create("a"));
- Node node_b = repository.createNode(env, node_a, nameFactory.create("b"));
- Node node_c = repository.createNode(env, node_b, nameFactory.create("c"));
- Node node_d = repository.createNode(env, root, nameFactory.create("d"));
- Node node_e = repository.createNode(env, node_d, nameFactory.create("e"));
- Node node_b2 = repository.createNode(env, node_d, nameFactory.create("b"));
+ Node node_a = repository.createNode(context, root, nameFactory.create("a"));
+ Node node_b = repository.createNode(context, node_a, nameFactory.create("b"));
+ Node node_c = repository.createNode(context, node_b, nameFactory.create("c"));
+ Node node_d = repository.createNode(context, root, nameFactory.create("d"));
+ Node node_e = repository.createNode(context, node_d, nameFactory.create("e"));
+ Node node_b2 = repository.createNode(context, node_d, nameFactory.create("b"));
ValueFactory<String> stringFactory = valueFactories.getStringFactory();
Name propertyName = nameFactory.create("something");
@@ -320,7 +320,7 @@
assertThat(repository.getNode(pathFactory.create("/a/b")).getProperties().get(propertyName), is(property));
- repository.copyNode(env, node_b, node_d, true);
+ repository.copyNode(context, node_b, node_d, true);
assertThat(repository.getNodesByUuid().size(), is(9));
assertThat(repository.getNode(pathFactory.create("/")), is(sameInstance(repository.getRoot())));
@@ -339,13 +339,18 @@
@Test
public void shouldCreateRepositoryStructure() {
- repository.createNode(env, "/a").setProperty(env, "name", "value").setProperty(env, "desc", "Some description");
- repository.createNode(env, "/a/b").setProperty(env, "name", "value2").setProperty(env, "desc", "Some description 2");
- assertThat(repository.getNode(env, "/a").getProperty(env, "name").getValuesAsArray(), is(new Object[] {"value"}));
- assertThat(repository.getNode(env, "/a").getProperty(env, "desc").getValuesAsArray(),
+ repository.createNode(context, "/a").setProperty(context, "name", "value").setProperty(context,
+ "desc",
+ "Some description");
+ repository.createNode(context, "/a/b").setProperty(context, "name", "value2").setProperty(context,
+ "desc",
+ "Some description 2");
+ assertThat(repository.getNode(context, "/a").getProperty(context, "name").getValuesAsArray(), is(new Object[] {"value"}));
+ assertThat(repository.getNode(context, "/a").getProperty(context, "desc").getValuesAsArray(),
is(new Object[] {"Some description"}));
- assertThat(repository.getNode(env, "/a/b").getProperty(env, "name").getValuesAsArray(), is(new Object[] {"value2"}));
- assertThat(repository.getNode(env, "/a/b").getProperty(env, "desc").getValuesAsArray(),
+ assertThat(repository.getNode(context, "/a/b").getProperty(context, "name").getValuesAsArray(),
+ is(new Object[] {"value2"}));
+ assertThat(repository.getNode(context, "/a/b").getProperty(context, "desc").getValuesAsArray(),
is(new Object[] {"Some description 2"}));
}
}
Modified: trunk/connectors/dna-connector-jbosscache/src/main/java/org/jboss/dna/connector/jbosscache/JBossCacheConnection.java
===================================================================
--- trunk/connectors/dna-connector-jbosscache/src/main/java/org/jboss/dna/connector/jbosscache/JBossCacheConnection.java 2008-07-25 19:37:40 UTC (rev 370)
+++ trunk/connectors/dna-connector-jbosscache/src/main/java/org/jboss/dna/connector/jbosscache/JBossCacheConnection.java 2008-07-25 20:39:42 UTC (rev 371)
@@ -31,6 +31,7 @@
import org.jboss.cache.Cache;
import org.jboss.cache.Fqn;
import org.jboss.cache.Node;
+import org.jboss.dna.spi.ExecutionContext;
import org.jboss.dna.spi.cache.CachePolicy;
import org.jboss.dna.spi.graph.Name;
import org.jboss.dna.spi.graph.Path;
@@ -50,7 +51,6 @@
import org.jboss.dna.spi.graph.commands.SetPropertiesCommand;
import org.jboss.dna.spi.graph.commands.executor.AbstractCommandExecutor;
import org.jboss.dna.spi.graph.commands.executor.CommandExecutor;
-import org.jboss.dna.spi.graph.connection.ExecutionEnvironment;
import org.jboss.dna.spi.graph.connection.RepositoryConnection;
import org.jboss.dna.spi.graph.connection.RepositorySourceException;
import org.jboss.dna.spi.graph.connection.RepositorySourceListener;
@@ -139,10 +139,10 @@
/**
* {@inheritDoc}
*/
- public void execute( ExecutionEnvironment env,
+ public void execute( ExecutionContext context,
GraphCommand... commands ) throws RepositorySourceException, InterruptedException {
// Now execute the commands ...
- CommandExecutor executor = new Executor(env, this.getSourceName());
+ CommandExecutor executor = new Executor(context, this.getSourceName());
for (GraphCommand command : commands) {
executor.execute(command);
}
@@ -160,12 +160,12 @@
* This method may be called without regard to synchronization, since it should return the same value if it happens to be
* called concurrently while not yet initialized.
*
- * @param env the environment
+ * @param context the execution context
* @return the name, or null if the UUID should not be stored
*/
- protected Name getUuidProperty( ExecutionEnvironment env ) {
+ protected Name getUuidProperty( ExecutionContext context ) {
if (!initializedUuidPropertyName) {
- this.uuidPropertyName = this.source.getUuidPropertyName(env.getValueFactories().getNameFactory());
+ this.uuidPropertyName = this.source.getUuidPropertyName(context.getValueFactories().getNameFactory());
initializedUuidPropertyName = true;
}
return this.uuidPropertyName;
@@ -185,13 +185,13 @@
return Fqn.fromElements(pathSegment);
}
- protected Node<Name, Object> getNode( ExecutionEnvironment env,
+ protected Node<Name, Object> getNode( ExecutionContext context,
Path path ) {
// Look up the node with the supplied path ...
Fqn<Segment> fqn = getFullyQualifiedName(path);
Node<Name, Object> node = cache.getNode(fqn);
if (node == null) {
- String nodePath = path.getString(env.getNamespaceRegistry());
+ String nodePath = path.getString(context.getNamespaceRegistry());
throw new PathNotFoundException(path, JBossCacheConnectorI18n.nodeDoesNotExist.text(nodePath));
}
return node;
@@ -230,10 +230,10 @@
private final PropertyFactory propertyFactory;
- protected Executor( ExecutionEnvironment env,
+ protected Executor( ExecutionContext context,
String sourceName ) {
- super(env, sourceName);
- this.propertyFactory = env.getPropertyFactory();
+ super(context, sourceName);
+ this.propertyFactory = context.getPropertyFactory();
}
@Override
Modified: trunk/dna-repository/src/main/java/org/jboss/dna/repository/RepositoryService.java
===================================================================
--- trunk/dna-repository/src/main/java/org/jboss/dna/repository/RepositoryService.java 2008-07-25 19:37:40 UTC (rev 370)
+++ trunk/dna-repository/src/main/java/org/jboss/dna/repository/RepositoryService.java 2008-07-25 20:39:42 UTC (rev 371)
@@ -44,6 +44,7 @@
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.ExecutionContext;
import org.jboss.dna.spi.graph.Name;
import org.jboss.dna.spi.graph.NameFactory;
import org.jboss.dna.spi.graph.Path;
@@ -57,7 +58,6 @@
import org.jboss.dna.spi.graph.commands.impl.BasicCompositeCommand;
import org.jboss.dna.spi.graph.commands.impl.BasicGetChildrenCommand;
import org.jboss.dna.spi.graph.commands.impl.BasicGetNodeCommand;
-import org.jboss.dna.spi.graph.connection.ExecutionEnvironment;
import org.jboss.dna.spi.graph.connection.RepositoryConnectionFactory;
import org.jboss.dna.spi.graph.connection.RepositorySource;
@@ -113,7 +113,7 @@
}
private final ClassLoaderFactory classLoaderFactory;
- private final ExecutionEnvironment env;
+ private final ExecutionContext context;
private final RepositorySourceManager sources;
private final Projection configurationProjection;
private final Administrator administrator = new Administrator();
@@ -125,7 +125,7 @@
* @param sources the source manager
* @param configurationProjection the projection defining where the service can find configuration information for the
* different repositories that it is to manage
- * @param env the execution environment in which this service should run
+ * @param context the execution context in which this service should run
* @param classLoaderFactory the class loader factory used to instantiate {@link RepositorySource} instances; may be null if
* this instance should use a default factory that attempts to load classes first from the
* {@link Thread#getContextClassLoader() thread's current context class loader} and then from the class loader that
@@ -134,14 +134,14 @@
*/
public RepositoryService( RepositorySourceManager sources,
Projection configurationProjection,
- ExecutionEnvironment env,
+ ExecutionContext context,
ClassLoaderFactory classLoaderFactory ) {
ArgCheck.isNotNull(configurationProjection, "configurationProjection");
ArgCheck.isNotNull(sources, "sources");
- ArgCheck.isNotNull(env, "env");
+ ArgCheck.isNotNull(context, "context");
this.sources = sources;
this.configurationProjection = configurationProjection;
- this.env = env;
+ this.context = context;
this.classLoaderFactory = classLoaderFactory != null ? classLoaderFactory : new StandardClassLoaderFactory();
}
@@ -169,8 +169,8 @@
/**
* @return env
*/
- public ExecutionEnvironment getExecutionEnvironment() {
- return env;
+ public ExecutionContext getExecutionEnvironment() {
+ return context;
}
/**
@@ -192,7 +192,7 @@
// ------------------------------------------------------------------------------------
// Read the configuration ...
// ------------------------------------------------------------------------------------
- ValueFactories valueFactories = env.getValueFactories();
+ ValueFactories valueFactories = context.getValueFactories();
PathFactory pathFactory = valueFactories.getPathFactory();
NameFactory nameFactory = valueFactories.getNameFactory();
@@ -209,13 +209,13 @@
if (configurationProjection.getRules().size() == 1) {
// There is just a single projection for the configuration repository, so just use an executor that
// translates the paths using the projection
- executor = new SingleProjectionCommandExecutor(env, configurationSourceName, configurationProjection, sources);
+ executor = new SingleProjectionCommandExecutor(context, configurationSourceName, configurationProjection, sources);
} else if (configurationProjection.getRules().size() == 0) {
// There is no projection for the configuration repository, so just use a no-op executor
- executor = new NoOpCommandExecutor(env, configurationSourceName);
+ executor = new NoOpCommandExecutor(context, configurationSourceName);
} else {
// The configuration repository has more than one projection, so we need to merge the results
- executor = new FederatingCommandExecutor(env, configurationSourceName, null, projections, sources);
+ executor = new FederatingCommandExecutor(context, configurationSourceName, null, projections, sources);
}
// Read the configuration and the repository sources, located as child nodes/branches under "/dna:sources",
@@ -268,7 +268,7 @@
protected RepositorySource createRepositorySource( Path path,
Map<Name, Property> properties,
Problems problems ) {
- ValueFactories valueFactories = env.getValueFactories();
+ ValueFactories valueFactories = context.getValueFactories();
NameFactory nameFactory = valueFactories.getNameFactory();
ValueFactory<String> stringFactory = valueFactories.getStringFactory();
Modified: trunk/dna-repository/src/main/java/org/jboss/dna/repository/rules/RuleSetRepositoryMonitor.java
===================================================================
--- trunk/dna-repository/src/main/java/org/jboss/dna/repository/rules/RuleSetRepositoryMonitor.java 2008-07-25 19:37:40 UTC (rev 370)
+++ trunk/dna-repository/src/main/java/org/jboss/dna/repository/rules/RuleSetRepositoryMonitor.java 2008-07-25 20:39:42 UTC (rev 371)
@@ -42,7 +42,7 @@
import org.jboss.dna.repository.observation.NodeChangeListener;
import org.jboss.dna.repository.observation.NodeChanges;
import org.jboss.dna.repository.observation.ObservationService;
-import org.jboss.dna.repository.util.ExecutionContext;
+import org.jboss.dna.repository.util.JcrExecutionContext;
import org.jboss.dna.repository.util.JcrTools;
/**
@@ -64,7 +64,7 @@
protected static final String JCR_PATH_DELIM = "/";
- private final ExecutionContext executionContext;
+ private final JcrExecutionContext executionContext;
private final RuleService ruleService;
private final String jcrAbsolutePath;
private final Pattern ruleSetNamePattern;
@@ -84,7 +84,7 @@
*/
public RuleSetRepositoryMonitor( RuleService ruleService,
String jcrAbsolutePath,
- ExecutionContext executionContext ) {
+ JcrExecutionContext executionContext ) {
ArgCheck.isNotNull(ruleService, "rule service");
ArgCheck.isNotNull(executionContext, "execution context");
this.ruleService = ruleService;
Modified: trunk/dna-repository/src/main/java/org/jboss/dna/repository/sequencers/Sequencer.java
===================================================================
--- trunk/dna-repository/src/main/java/org/jboss/dna/repository/sequencers/Sequencer.java 2008-07-25 19:37:40 UTC (rev 370)
+++ trunk/dna-repository/src/main/java/org/jboss/dna/repository/sequencers/Sequencer.java 2008-07-25 20:39:42 UTC (rev 371)
@@ -32,7 +32,7 @@
import org.jboss.dna.repository.observation.NodeChangeListener;
import org.jboss.dna.repository.observation.NodeChanges;
import org.jboss.dna.repository.observation.ObservationService;
-import org.jboss.dna.repository.util.ExecutionContext;
+import org.jboss.dna.repository.util.JcrExecutionContext;
import org.jboss.dna.repository.util.RepositoryNodePath;
/**
@@ -48,7 +48,7 @@
/**
* Execute the sequencing operation on the supplied node, which has recently been created or changed. The implementation of
- * this method is responsible for {@link ExecutionContext#getSessionFactory() getting sessions}, modifying the appropriate
+ * this method is responsible for {@link JcrExecutionContext#getSessionFactory() getting sessions}, modifying the appropriate
* nodes, {@link Session#save() saving} any changes made by this sequencer, and {@link Session#logout() closing} all sessions
* (and any other acquired resources), even in the case of {@link ProgressMonitor#isCancelled() cancellation} or exceptions.
* <p>
@@ -94,7 +94,7 @@
* @throws RepositoryException if there is a problem while working with the repository
* @throws SequencerException if there is an error in this sequencer
*/
- void execute( Node input, String sequencedPropertyName, NodeChange changes, Set<RepositoryNodePath> outputPaths, ExecutionContext context, ProgressMonitor progress )
+ void execute( Node input, String sequencedPropertyName, NodeChange changes, Set<RepositoryNodePath> outputPaths, JcrExecutionContext context, ProgressMonitor progress )
throws RepositoryException, SequencerException;
}
Modified: trunk/dna-repository/src/main/java/org/jboss/dna/repository/sequencers/SequencerNodeContext.java
===================================================================
--- trunk/dna-repository/src/main/java/org/jboss/dna/repository/sequencers/SequencerNodeContext.java 2008-07-25 19:37:40 UTC (rev 370)
+++ trunk/dna-repository/src/main/java/org/jboss/dna/repository/sequencers/SequencerNodeContext.java 2008-07-25 20:39:42 UTC (rev 371)
@@ -35,7 +35,7 @@
import org.jboss.dna.common.util.ArgCheck;
import org.jboss.dna.repository.RepositoryI18n;
import org.jboss.dna.repository.mimetype.MimeType;
-import org.jboss.dna.repository.util.ExecutionContext;
+import org.jboss.dna.repository.util.JcrExecutionContext;
import org.jboss.dna.spi.graph.Name;
import org.jboss.dna.spi.graph.NamespaceRegistry;
import org.jboss.dna.spi.graph.Path;
@@ -60,7 +60,7 @@
SequencerNodeContext( Node input,
javax.jcr.Property sequencedProperty,
- ExecutionContext context ) throws RepositoryException {
+ JcrExecutionContext context ) throws RepositoryException {
assert input != null;
assert sequencedProperty != null;
assert context != null;
Modified: trunk/dna-repository/src/main/java/org/jboss/dna/repository/sequencers/SequencingService.java
===================================================================
--- trunk/dna-repository/src/main/java/org/jboss/dna/repository/sequencers/SequencingService.java 2008-07-25 19:37:40 UTC (rev 370)
+++ trunk/dna-repository/src/main/java/org/jboss/dna/repository/sequencers/SequencingService.java 2008-07-25 20:39:42 UTC (rev 371)
@@ -38,6 +38,7 @@
import javax.jcr.RepositoryException;
import javax.jcr.Session;
import javax.jcr.observation.Event;
+import javax.security.auth.Subject;
import net.jcip.annotations.Immutable;
import net.jcip.annotations.ThreadSafe;
import org.jboss.dna.common.component.ClassLoaderFactory;
@@ -56,7 +57,7 @@
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.repository.util.ExecutionContext;
+import org.jboss.dna.repository.util.JcrExecutionContext;
import org.jboss.dna.repository.util.JcrTools;
import org.jboss.dna.repository.util.RepositoryNodePath;
import org.jboss.dna.repository.util.SessionFactory;
@@ -150,9 +151,8 @@
public static final NodeFilter DEFAULT_NODE_FILTER = new DefaultNodeFilter();
/**
- * Class loader factory instance that always returns the
- * {@link Thread#getContextClassLoader() current thread's context class loader} (if not null) or component library's class
- * loader.
+ * Class loader factory instance that always returns the {@link Thread#getContextClassLoader() current thread's context class
+ * loader} (if not null) or component library's class loader.
*/
protected static final ClassLoaderFactory DEFAULT_CLASSLOADER_FACTORY = new StandardClassLoaderFactory(
SequencingService.class.getClassLoader());
@@ -204,7 +204,7 @@
}
- private ExecutionContext executionContext;
+ private JcrExecutionContext executionContext;
private SequencerLibrary sequencerLibrary = new SequencerLibrary();
private Selector sequencerSelector = DEFAULT_SEQUENCER_SELECTOR;
private NodeFilter nodeFilter = DEFAULT_NODE_FILTER;
@@ -287,8 +287,8 @@
}
/**
- * Update the configuration for a sequencer, or add it if there is no
- * {@link SequencerConfig#equals(Object) matching configuration}.
+ * Update the configuration for a sequencer, or add it if there is no {@link SequencerConfig#equals(Object) matching
+ * configuration}.
*
* @param config the updated (or new) configuration
* @return true if the sequencer was updated, or false if there already was an existing and
@@ -335,14 +335,14 @@
/**
* @return executionContext
*/
- public ExecutionContext getExecutionContext() {
+ public JcrExecutionContext getExecutionContext() {
return this.executionContext;
}
/**
* @param executionContext Sets executionContext to the specified value.
*/
- public void setExecutionContext( ExecutionContext executionContext ) {
+ public void setExecutionContext( JcrExecutionContext executionContext ) {
ArgCheck.isNotNull(executionContext, "execution context");
if (this.getAdministrator().isStarted()) {
throw new IllegalStateException(RepositoryI18n.unableToChangeExecutionContextWhileRunning.text());
@@ -615,9 +615,9 @@
}
}
- protected class Context implements ExecutionContext {
+ protected class Context implements JcrExecutionContext {
- protected final ExecutionContext delegate;
+ protected final JcrExecutionContext delegate;
protected final SessionFactory factory;
private final Set<Session> sessions = new HashSet<Session>();
protected final AtomicBoolean closed = new AtomicBoolean(false);
@@ -675,6 +675,15 @@
return SequencingService.this.getExecutionContext().getTools();
}
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.jboss.dna.spi.ExecutionContext#getSubject()
+ */
+ public Subject getSubject() {
+ return this.delegate.getSubject();
+ }
+
public synchronized void close() {
if (this.closed.get()) return;
this.closed.set(true);
Modified: trunk/dna-repository/src/main/java/org/jboss/dna/repository/sequencers/StreamSequencerAdapter.java
===================================================================
--- trunk/dna-repository/src/main/java/org/jboss/dna/repository/sequencers/StreamSequencerAdapter.java 2008-07-25 19:37:40 UTC (rev 370)
+++ trunk/dna-repository/src/main/java/org/jboss/dna/repository/sequencers/StreamSequencerAdapter.java 2008-07-25 20:39:42 UTC (rev 371)
@@ -35,7 +35,7 @@
import org.jboss.dna.common.util.Logger;
import org.jboss.dna.repository.RepositoryI18n;
import org.jboss.dna.repository.observation.NodeChange;
-import org.jboss.dna.repository.util.ExecutionContext;
+import org.jboss.dna.repository.util.JcrExecutionContext;
import org.jboss.dna.repository.util.RepositoryNodePath;
import org.jboss.dna.spi.graph.Binary;
import org.jboss.dna.spi.graph.DateTime;
@@ -80,7 +80,7 @@
String sequencedPropertyName,
NodeChange changes,
Set<RepositoryNodePath> outputPaths,
- ExecutionContext execContext,
+ JcrExecutionContext execContext,
ProgressMonitor progressMonitor ) throws RepositoryException, SequencerException {
// 'sequencedPropertyName' contains the name of the modified property on 'input' that resulted in the call to this
// sequencer.
@@ -178,7 +178,7 @@
*/
protected boolean saveOutput( Node outputNode,
SequencerOutputMap output,
- ExecutionContext context ) throws RepositoryException {
+ JcrExecutionContext context ) throws RepositoryException {
if (output.isEmpty()) return false;
final PathFactory pathFactory = context.getValueFactories().getPathFactory();
final NamespaceRegistry namespaceRegistry = context.getNamespaceRegistry();
Copied: trunk/dna-repository/src/main/java/org/jboss/dna/repository/util/BasicJcrExecutionContext.java (from rev 368, trunk/dna-repository/src/main/java/org/jboss/dna/repository/util/SimpleExecutionContext.java)
===================================================================
--- trunk/dna-repository/src/main/java/org/jboss/dna/repository/util/BasicJcrExecutionContext.java (rev 0)
+++ trunk/dna-repository/src/main/java/org/jboss/dna/repository/util/BasicJcrExecutionContext.java 2008-07-25 20:39:42 UTC (rev 371)
@@ -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.repository.util;
+
+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.connection.BasicExecutionContext;
+
+/**
+ * @author Randall Hauch
+ */
+public class BasicJcrExecutionContext extends BasicExecutionContext implements JcrExecutionContext {
+
+ private final JcrTools tools = new JcrTools();
+ private final SessionFactory sessionFactory;
+
+ public BasicJcrExecutionContext( SessionFactory sessionFactory,
+ String repositoryWorkspaceForNamespaceRegistry ) {
+ this(sessionFactory, new JcrNamespaceRegistry(sessionFactory, repositoryWorkspaceForNamespaceRegistry), null, null);
+ }
+
+ public BasicJcrExecutionContext( SessionFactory sessionFactory,
+ NamespaceRegistry namespaceRegistry ) {
+ this(sessionFactory, namespaceRegistry, null, null);
+ }
+
+ public BasicJcrExecutionContext( SessionFactory sessionFactory,
+ NamespaceRegistry namespaceRegistry,
+ ValueFactories valueFactories,
+ PropertyFactory propertyFactory ) {
+ super(namespaceRegistry, valueFactories, propertyFactory);
+ ArgCheck.isNotNull(sessionFactory, "session factory");
+ this.sessionFactory = sessionFactory;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public SessionFactory getSessionFactory() {
+ return this.sessionFactory;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public JcrTools getTools() {
+ return this.tools;
+ }
+
+}
Deleted: trunk/dna-repository/src/main/java/org/jboss/dna/repository/util/ExecutionContext.java
===================================================================
--- trunk/dna-repository/src/main/java/org/jboss/dna/repository/util/ExecutionContext.java 2008-07-25 19:37:40 UTC (rev 370)
+++ trunk/dna-repository/src/main/java/org/jboss/dna/repository/util/ExecutionContext.java 2008-07-25 20:39:42 UTC (rev 371)
@@ -1,49 +0,0 @@
-/*
- * 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.util;
-
-import javax.jcr.Session;
-import org.jboss.dna.spi.graph.connection.ExecutionEnvironment;
-
-/**
- * The context of an execution.
- *
- * @author Randall Hauch
- */
-public interface ExecutionContext extends ExecutionEnvironment {
-
- /**
- * Get the session factory, which can be used to obtain sessions temporarily for this context. Any session obtained from this
- * factory should be {@link Session#logout() closed} before the execution finishes.
- *
- * @return the session factory
- */
- SessionFactory getSessionFactory();
-
- /**
- * Get a set of utilities for working with JCR.
- *
- * @return the tools
- */
- JcrTools getTools();
-
-}
Copied: trunk/dna-repository/src/main/java/org/jboss/dna/repository/util/JcrExecutionContext.java (from rev 368, trunk/dna-repository/src/main/java/org/jboss/dna/repository/util/ExecutionContext.java)
===================================================================
--- trunk/dna-repository/src/main/java/org/jboss/dna/repository/util/JcrExecutionContext.java (rev 0)
+++ trunk/dna-repository/src/main/java/org/jboss/dna/repository/util/JcrExecutionContext.java 2008-07-25 20:39:42 UTC (rev 371)
@@ -0,0 +1,49 @@
+/*
+ * 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.util;
+
+import javax.jcr.Session;
+import org.jboss.dna.spi.ExecutionContext;
+
+/**
+ * The context of an execution within a JCR environment.
+ *
+ * @author Randall Hauch
+ */
+public interface JcrExecutionContext extends ExecutionContext {
+
+ /**
+ * Get the session factory, which can be used to obtain sessions temporarily for this context. Any session obtained from this
+ * factory should be {@link Session#logout() closed} before the execution finishes.
+ *
+ * @return the session factory
+ */
+ SessionFactory getSessionFactory();
+
+ /**
+ * Get a set of utilities for working with JCR.
+ *
+ * @return the tools
+ */
+ JcrTools getTools();
+
+}
Property changes on: trunk/dna-repository/src/main/java/org/jboss/dna/repository/util/JcrExecutionContext.java
___________________________________________________________________
Name: svn:mime-type
+ text/plain
Deleted: trunk/dna-repository/src/main/java/org/jboss/dna/repository/util/SimpleExecutionContext.java
===================================================================
--- trunk/dna-repository/src/main/java/org/jboss/dna/repository/util/SimpleExecutionContext.java 2008-07-25 19:37:40 UTC (rev 370)
+++ trunk/dna-repository/src/main/java/org/jboss/dna/repository/util/SimpleExecutionContext.java 2008-07-25 20:39:42 UTC (rev 371)
@@ -1,71 +0,0 @@
-/*
- * 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.util;
-
-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.connection.BasicExecutionEnvironment;
-
-/**
- * @author Randall Hauch
- */
-public class SimpleExecutionContext extends BasicExecutionEnvironment implements ExecutionContext {
-
- private final JcrTools tools = new JcrTools();
- private final SessionFactory sessionFactory;
-
- public SimpleExecutionContext( SessionFactory sessionFactory,
- String repositoryWorkspaceForNamespaceRegistry ) {
- this(sessionFactory, new JcrNamespaceRegistry(sessionFactory, repositoryWorkspaceForNamespaceRegistry), null, null);
- }
-
- public SimpleExecutionContext( SessionFactory sessionFactory,
- NamespaceRegistry namespaceRegistry ) {
- this(sessionFactory, namespaceRegistry, null, null);
- }
-
- public SimpleExecutionContext( SessionFactory sessionFactory,
- NamespaceRegistry namespaceRegistry,
- ValueFactories valueFactories,
- PropertyFactory propertyFactory ) {
- super(namespaceRegistry, valueFactories, propertyFactory);
- ArgCheck.isNotNull(sessionFactory, "session factory");
- this.sessionFactory = sessionFactory;
- }
-
- /**
- * {@inheritDoc}
- */
- public SessionFactory getSessionFactory() {
- return this.sessionFactory;
- }
-
- /**
- * {@inheritDoc}
- */
- public JcrTools getTools() {
- return this.tools;
- }
-
-}
Modified: trunk/dna-repository/src/test/java/org/jboss/dna/repository/RepositoryServiceTest.java
===================================================================
--- trunk/dna-repository/src/test/java/org/jboss/dna/repository/RepositoryServiceTest.java 2008-07-25 19:37:40 UTC (rev 370)
+++ trunk/dna-repository/src/test/java/org/jboss/dna/repository/RepositoryServiceTest.java 2008-07-25 20:39:42 UTC (rev 371)
@@ -39,11 +39,11 @@
import org.jboss.dna.connector.federation.FederationException;
import org.jboss.dna.connector.federation.Projection;
import org.jboss.dna.repository.services.ServiceAdministrator;
+import org.jboss.dna.spi.ExecutionContext;
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.connection.SimpleRepository;
import org.jboss.dna.spi.graph.connection.SimpleRepositorySource;
@@ -76,7 +76,7 @@
private SimpleRepository configRepository;
private SimpleRepositorySource configRepositorySource;
@Mock
- private ExecutionEnvironment env;
+ private ExecutionContext context;
@Mock
private RepositorySourceManager sources;
@@ -98,10 +98,10 @@
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 RepositoryService(sources, configProjection, env, null);
+ stub(context.getValueFactories()).toReturn(valueFactories);
+ stub(context.getPropertyFactory()).toReturn(propertyFactory);
+ stub(context.getNamespaceRegistry()).toReturn(registry);
+ service = new RepositoryService(sources, configProjection, context, null);
}
@After
@@ -126,7 +126,7 @@
@Test
public void shouldHaveAnExecutionEnvironmentAfterInstantiation() {
assertThat(service.getExecutionEnvironment(), is(notNullValue()));
- assertThat(service.getExecutionEnvironment(), is(sameInstance(env)));
+ assertThat(service.getExecutionEnvironment(), is(sameInstance(context)));
}
@Test
@@ -137,7 +137,7 @@
@Test
public void shouldHaveNonNullClassLoaderFactoryAfterInstantiatingWithClassLoaderFactoryReference() {
ClassLoaderFactory classLoaderFactory = mock(ClassLoaderFactory.class);
- service = new RepositoryService(sources, configProjection, env, classLoaderFactory);
+ service = new RepositoryService(sources, configProjection, context, classLoaderFactory);
assertThat(service.getClassLoaderFactory(), is(notNullValue()));
assertThat(service.getClassLoaderFactory(), is(sameInstance(classLoaderFactory)));
}
@@ -184,22 +184,22 @@
sources.addSource(configRepositorySource, true);
assertThat(sources.getSources(), hasItems((RepositorySource)configRepositorySource));
assertThat(sources.getSources().size(), is(1));
- service = new RepositoryService(sources, configProjection, env, null);
+ service = new RepositoryService(sources, configProjection, context, 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.create(context, "/reposX/dna:sources");
+ configRepository.setProperty(context, "/reposX/dna:sources/source A", CLASSNAME, SimpleRepositorySource.class.getName());
+ configRepository.setProperty(context, "/reposX/dna:sources/source A", CLASSPATH, "");
+ configRepository.setProperty(context, "/reposX/dna:sources/source A", "repositoryName", "sourceReposA");
+ configRepository.setProperty(context, "/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(context, "/reposX/dna:sources/source B", CLASSNAME, SimpleRepositorySource.class.getName());
+ configRepository.setProperty(context, "/reposX/dna:sources/source B", CLASSPATH, "");
+ configRepository.setProperty(context, "/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");
+ configRepository.setProperty(context, "/reposX/dna:sources/source C", CLASSNAME, SimpleRepositorySource.class.getName());
+ configRepository.setProperty(context, "/reposX/dna:sources/source C", CLASSPATH, "");
+ configRepository.setProperty(context, "/reposX/dna:sources/source C", "repositoryName", "sourceReposC");
// Now, start up the service ...
service.getAdministrator().start();
@@ -229,7 +229,7 @@
@Test
public void shouldStartUpUsingConfigurationRepositoryThatContainsNoSources() {
// Set up the configuration repository to contain NO sources ...
- configRepository.create(env, "/reposX/dna:sources");
+ configRepository.create(context, "/reposX/dna:sources");
// Now, start up the service ...
service.getAdministrator().start();
@@ -244,19 +244,19 @@
@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);
+ configRepository.create(context, "/reposX/dna:sources");
+ configRepository.setProperty(context, "/reposX/dna:sources/source A", CLASSNAME, SimpleRepositorySource.class.getName());
+ configRepository.setProperty(context, "/reposX/dna:sources/source A", CLASSPATH, "");
+ configRepository.setProperty(context, "/reposX/dna:sources/source A", "repositoryName", "sourceReposA");
+ configRepository.setProperty(context, "/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/source A", PROJECTION_RULES, "/a/b/c => /sx/sy");
- configRepository.setProperty(env, fedReposPath + "dna:regions/source B", PROJECTION_RULES, "/ => /");
- configRepository.setProperty(env, fedReposPath + "dna:regions/source C", PROJECTION_RULES, "/d/e/f => /");
- configRepository.setProperty(env, fedReposPath + "dna:regions/source D", PROJECTION_RULES, "/ => /x/y/z");
+ configRepository.setProperty(context, fedReposPath, TIME_TO_CACHE, "10000");
+ configRepository.setProperty(context, fedReposPath, TIME_TO_EXPIRE, "20000");
+ configRepository.setProperty(context, fedReposPath + "dna:regions/source A", PROJECTION_RULES, "/a/b/c => /sx/sy");
+ configRepository.setProperty(context, fedReposPath + "dna:regions/source B", PROJECTION_RULES, "/ => /");
+ configRepository.setProperty(context, fedReposPath + "dna:regions/source C", PROJECTION_RULES, "/d/e/f => /");
+ configRepository.setProperty(context, fedReposPath + "dna:regions/source D", PROJECTION_RULES, "/ => /x/y/z");
// Now, start up the service ...
service.getAdministrator().start();
Modified: trunk/dna-repository/src/test/java/org/jboss/dna/repository/sequencers/MockSequencerA.java
===================================================================
--- trunk/dna-repository/src/test/java/org/jboss/dna/repository/sequencers/MockSequencerA.java 2008-07-25 19:37:40 UTC (rev 370)
+++ trunk/dna-repository/src/test/java/org/jboss/dna/repository/sequencers/MockSequencerA.java 2008-07-25 20:39:42 UTC (rev 371)
@@ -31,7 +31,7 @@
import org.jboss.dna.common.i18n.MockI18n;
import org.jboss.dna.common.monitor.ProgressMonitor;
import org.jboss.dna.repository.observation.NodeChange;
-import org.jboss.dna.repository.util.ExecutionContext;
+import org.jboss.dna.repository.util.JcrExecutionContext;
import org.jboss.dna.repository.util.RepositoryNodePath;
/**
@@ -63,7 +63,7 @@
/**
* {@inheritDoc}
*/
- public void execute( Node input, String sequencedPropertyName, NodeChange changes, Set<RepositoryNodePath> outputPaths, ExecutionContext context, ProgressMonitor progress ) {
+ public void execute( Node input, String sequencedPropertyName, NodeChange changes, Set<RepositoryNodePath> outputPaths, JcrExecutionContext context, ProgressMonitor progress ) {
try {
progress.beginTask(1, MockI18n.passthrough, "Incrementing counter");
// increment the counter and record the progress ...
Modified: trunk/dna-repository/src/test/java/org/jboss/dna/repository/sequencers/MockSequencerB.java
===================================================================
--- trunk/dna-repository/src/test/java/org/jboss/dna/repository/sequencers/MockSequencerB.java 2008-07-25 19:37:40 UTC (rev 370)
+++ trunk/dna-repository/src/test/java/org/jboss/dna/repository/sequencers/MockSequencerB.java 2008-07-25 20:39:42 UTC (rev 371)
@@ -31,7 +31,7 @@
import org.jboss.dna.common.i18n.MockI18n;
import org.jboss.dna.common.monitor.ProgressMonitor;
import org.jboss.dna.repository.observation.NodeChange;
-import org.jboss.dna.repository.util.ExecutionContext;
+import org.jboss.dna.repository.util.JcrExecutionContext;
import org.jboss.dna.repository.util.RepositoryNodePath;
/**
@@ -63,7 +63,7 @@
/**
* {@inheritDoc}
*/
- public void execute( Node input, String sequencedPropertyName, NodeChange changes, Set<RepositoryNodePath> outputPaths, ExecutionContext context, ProgressMonitor progress ) {
+ public void execute( Node input, String sequencedPropertyName, NodeChange changes, Set<RepositoryNodePath> outputPaths, JcrExecutionContext context, ProgressMonitor progress ) {
try {
progress.beginTask(1, MockI18n.passthrough, "Incrementing counter");
// increment the counter and record the progress ...
Modified: trunk/dna-repository/src/test/java/org/jboss/dna/repository/sequencers/SequencerNodeContextTest.java
===================================================================
--- trunk/dna-repository/src/test/java/org/jboss/dna/repository/sequencers/SequencerNodeContextTest.java 2008-07-25 19:37:40 UTC (rev 370)
+++ trunk/dna-repository/src/test/java/org/jboss/dna/repository/sequencers/SequencerNodeContextTest.java 2008-07-25 20:39:42 UTC (rev 371)
@@ -30,11 +30,11 @@
import javax.jcr.RepositoryException;
import javax.jcr.Session;
import org.jboss.dna.common.jcr.AbstractJcrRepositoryTest;
-import org.jboss.dna.repository.util.ExecutionContext;
+import org.jboss.dna.repository.util.JcrExecutionContext;
import org.jboss.dna.repository.util.JcrNamespaceRegistry;
import org.jboss.dna.repository.util.JcrTools;
import org.jboss.dna.repository.util.SessionFactory;
-import org.jboss.dna.repository.util.SimpleExecutionContext;
+import org.jboss.dna.repository.util.BasicJcrExecutionContext;
import org.jboss.dna.spi.graph.NameFactory;
import org.jboss.dna.spi.graph.NamespaceRegistry;
import org.jboss.dna.spi.graph.Property;
@@ -50,7 +50,7 @@
*/
public class SequencerNodeContextTest extends AbstractJcrRepositoryTest {
- private ExecutionContext execContext;
+ private JcrExecutionContext execContext;
private Session session;
private JcrTools tools;
@Mock
@@ -70,7 +70,7 @@
}
};
NamespaceRegistry registry = new JcrNamespaceRegistry(sessionFactory, "doesn't matter");
- execContext = new SimpleExecutionContext(sessionFactory, registry, null, null);
+ execContext = new BasicJcrExecutionContext(sessionFactory, registry, null, null);
startRepository();
session = getRepository().login(getTestCredentials());
tools = new JcrTools();
Modified: trunk/dna-repository/src/test/java/org/jboss/dna/repository/sequencers/SequencingServiceTest.java
===================================================================
--- trunk/dna-repository/src/test/java/org/jboss/dna/repository/sequencers/SequencingServiceTest.java 2008-07-25 19:37:40 UTC (rev 370)
+++ trunk/dna-repository/src/test/java/org/jboss/dna/repository/sequencers/SequencingServiceTest.java 2008-07-25 20:39:42 UTC (rev 371)
@@ -35,8 +35,8 @@
import org.jboss.dna.common.jcr.AbstractJcrRepositoryTest;
import org.jboss.dna.repository.observation.ObservationService;
import org.jboss.dna.repository.services.ServiceAdministrator;
-import org.jboss.dna.repository.util.ExecutionContext;
-import org.jboss.dna.repository.util.MockExecutionContext;
+import org.jboss.dna.repository.util.JcrExecutionContext;
+import org.jboss.dna.repository.util.MockJcrExecutionContext;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
@@ -52,11 +52,11 @@
private ObservationService observationService;
private SequencingService sequencingService;
- private ExecutionContext executionContext;
+ private JcrExecutionContext executionContext;
@Before
public void beforeEach() {
- this.executionContext = new MockExecutionContext(this, REPOSITORY_WORKSPACE_NAME);
+ this.executionContext = new MockJcrExecutionContext(this, REPOSITORY_WORKSPACE_NAME);
this.sequencingService = new SequencingService();
this.sequencingService.setExecutionContext(this.executionContext);
this.observationService = new ObservationService(this.executionContext.getSessionFactory());
Modified: trunk/dna-repository/src/test/java/org/jboss/dna/repository/sequencers/StreamSequencerAdapterTest.java
===================================================================
--- trunk/dna-repository/src/test/java/org/jboss/dna/repository/sequencers/StreamSequencerAdapterTest.java 2008-07-25 19:37:40 UTC (rev 370)
+++ trunk/dna-repository/src/test/java/org/jboss/dna/repository/sequencers/StreamSequencerAdapterTest.java 2008-07-25 20:39:42 UTC (rev 371)
@@ -40,12 +40,12 @@
import org.jboss.dna.common.monitor.ProgressMonitor;
import org.jboss.dna.common.monitor.RecordingProgressMonitor;
import org.jboss.dna.repository.observation.NodeChange;
-import org.jboss.dna.repository.util.ExecutionContext;
+import org.jboss.dna.repository.util.JcrExecutionContext;
import org.jboss.dna.repository.util.JcrNamespaceRegistry;
import org.jboss.dna.repository.util.JcrTools;
import org.jboss.dna.repository.util.RepositoryNodePath;
import org.jboss.dna.repository.util.SessionFactory;
-import org.jboss.dna.repository.util.SimpleExecutionContext;
+import org.jboss.dna.repository.util.BasicJcrExecutionContext;
import org.jboss.dna.spi.graph.NamespaceRegistry;
import org.jboss.dna.spi.graph.Path;
import org.jboss.dna.spi.sequencers.SequencerContext;
@@ -68,7 +68,7 @@
private Session session;
private SequencerOutputMap sequencerOutput;
private String sampleData = "The little brown fox didn't something bad.";
- private ExecutionContext context;
+ private JcrExecutionContext context;
private RecordingProgressMonitor progressMonitor;
private String repositoryWorkspaceName = "something";
@@ -83,7 +83,7 @@
}
};
NamespaceRegistry registry = new JcrNamespaceRegistry(sessionFactory, "doesn't matter");
- this.context = new SimpleExecutionContext(sessionFactory, registry, null, null);
+ this.context = new BasicJcrExecutionContext(sessionFactory, registry, null, null);
this.sequencerOutput = new SequencerOutputMap(this.context.getValueFactories());
this.progressMonitor = new RecordingProgressMonitor(StreamSequencerAdapterTest.class.getName());
final SequencerOutputMap finalOutput = sequencerOutput;
Deleted: trunk/dna-repository/src/test/java/org/jboss/dna/repository/util/MockExecutionContext.java
===================================================================
--- trunk/dna-repository/src/test/java/org/jboss/dna/repository/util/MockExecutionContext.java 2008-07-25 19:37:40 UTC (rev 370)
+++ trunk/dna-repository/src/test/java/org/jboss/dna/repository/util/MockExecutionContext.java 2008-07-25 20:39:42 UTC (rev 371)
@@ -1,51 +0,0 @@
-/*
- * 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.util;
-
-import static org.hamcrest.core.Is.is;
-import static org.junit.Assert.assertThat;
-import java.io.IOException;
-import javax.jcr.RepositoryException;
-import javax.jcr.Session;
-import org.jboss.dna.common.SystemFailureException;
-import org.jboss.dna.common.jcr.AbstractJcrRepositoryTest;
-
-/**
- * @author Randall Hauch
- */
-public class MockExecutionContext extends SimpleExecutionContext {
-
- public MockExecutionContext( final AbstractJcrRepositoryTest test, final String repositoryName ) {
- super(new SessionFactory() {
-
- public Session createSession( String name ) throws RepositoryException {
- assertThat(name, is(repositoryName));
- try {
- return test.getRepository().login(test.getTestCredentials());
- } catch (IOException e) {
- throw new SystemFailureException(e);
- }
- }
- }, repositoryName);
- }
-
-}
Copied: trunk/dna-repository/src/test/java/org/jboss/dna/repository/util/MockJcrExecutionContext.java (from rev 368, trunk/dna-repository/src/test/java/org/jboss/dna/repository/util/MockExecutionContext.java)
===================================================================
--- trunk/dna-repository/src/test/java/org/jboss/dna/repository/util/MockJcrExecutionContext.java (rev 0)
+++ trunk/dna-repository/src/test/java/org/jboss/dna/repository/util/MockJcrExecutionContext.java 2008-07-25 20:39:42 UTC (rev 371)
@@ -0,0 +1,51 @@
+/*
+ * 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.util;
+
+import static org.hamcrest.core.Is.is;
+import static org.junit.Assert.assertThat;
+import java.io.IOException;
+import javax.jcr.RepositoryException;
+import javax.jcr.Session;
+import org.jboss.dna.common.SystemFailureException;
+import org.jboss.dna.common.jcr.AbstractJcrRepositoryTest;
+
+/**
+ * @author Randall Hauch
+ */
+public class MockJcrExecutionContext extends BasicJcrExecutionContext {
+
+ public MockJcrExecutionContext( final AbstractJcrRepositoryTest test, final String repositoryName ) {
+ super(new SessionFactory() {
+
+ public Session createSession( String name ) throws RepositoryException {
+ assertThat(name, is(repositoryName));
+ try {
+ return test.getRepository().login(test.getTestCredentials());
+ } catch (IOException e) {
+ throw new SystemFailureException(e);
+ }
+ }
+ }, repositoryName);
+ }
+
+}
Property changes on: trunk/dna-repository/src/test/java/org/jboss/dna/repository/util/MockJcrExecutionContext.java
___________________________________________________________________
Name: svn:mime-type
+ text/plain
Copied: trunk/dna-spi/src/main/java/org/jboss/dna/spi/ExecutionContext.java (from rev 368, trunk/dna-spi/src/main/java/org/jboss/dna/spi/graph/connection/ExecutionEnvironment.java)
===================================================================
--- trunk/dna-spi/src/main/java/org/jboss/dna/spi/ExecutionContext.java (rev 0)
+++ trunk/dna-spi/src/main/java/org/jboss/dna/spi/ExecutionContext.java 2008-07-25 20:39:42 UTC (rev 371)
@@ -0,0 +1,63 @@
+/*
+ * 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;
+
+import javax.security.auth.Subject;
+import org.jboss.dna.spi.graph.NamespaceRegistry;
+import org.jboss.dna.spi.graph.Property;
+import org.jboss.dna.spi.graph.PropertyFactory;
+import org.jboss.dna.spi.graph.ValueFactories;
+
+/**
+ * @author Randall Hauch
+ */
+public interface ExecutionContext {
+
+ /**
+ * Get the factories that should be used to create values for {@link Property properties}.
+ *
+ * @return the property value factory; never null
+ */
+ ValueFactories getValueFactories();
+
+ /**
+ * Get the namespace registry for this context.
+ *
+ * @return the namespace registry; never null
+ */
+ NamespaceRegistry getNamespaceRegistry();
+
+ /**
+ * Get the factory for creating {@link Property} objects.
+ *
+ * @return the property factory; never null
+ */
+ PropertyFactory getPropertyFactory();
+
+ /**
+ * Get the JAAS subject for which this context was created.
+ *
+ * @return the subject; never null
+ */
+ Subject getSubject();
+
+}
Property changes on: trunk/dna-spi/src/main/java/org/jboss/dna/spi/ExecutionContext.java
___________________________________________________________________
Name: svn:mime-type
+ text/plain
Modified: trunk/dna-spi/src/main/java/org/jboss/dna/spi/ExecutionContextFactory.java
===================================================================
--- trunk/dna-spi/src/main/java/org/jboss/dna/spi/ExecutionContextFactory.java 2008-07-25 19:37:40 UTC (rev 370)
+++ trunk/dna-spi/src/main/java/org/jboss/dna/spi/ExecutionContextFactory.java 2008-07-25 20:39:42 UTC (rev 371)
@@ -26,10 +26,9 @@
import javax.security.auth.login.LoginContext;
import javax.security.auth.login.LoginException;
import javax.security.auth.spi.LoginModule;
-import org.jboss.dna.spi.graph.connection.ExecutionEnvironment;
/**
- * A factory for creating {@link ExecutionEnvironment} instances. Each execution environment is affiliated with a JAAS
+ * A factory for creating {@link ExecutionContext} instances. Each execution context is affiliated with a JAAS
* {@link Subject}, and thus the factory methods take the same parameters that the JAAS {@link LoginContext} take.
*
* @author Randall Hauch
@@ -37,13 +36,13 @@
public interface ExecutionContextFactory {
/**
- * Create an {@link ExecutionEnvironment} for the supplied {@link LoginContext}.
+ * Create an {@link ExecutionContext} for the supplied {@link LoginContext}.
*
* @param loginContext the JAAS login context
* @return the execution context
* @throws IllegalArgumentException if the <code>loginContext</code> is null
*/
- ExecutionEnvironment create( LoginContext loginContext );
+ ExecutionContext create( LoginContext loginContext );
/**
* @param name the name of the JAAS login context
@@ -52,7 +51,7 @@
* @throws LoginException if there <code>name</code> is invalid (or there is no login context named "other"), or if the
* default callback handler JAAS property was not set or could not be loaded
*/
- ExecutionEnvironment create( String name ) throws LoginException;
+ ExecutionContext create( String name ) throws LoginException;
/**
* @param name the name of the JAAS login context
@@ -62,7 +61,7 @@
* callback handler JAAS property was not set or could not be loaded, or if the <code>subject</code> is null or
* unknown
*/
- ExecutionEnvironment create( String name,
+ ExecutionContext create( String name,
Subject subject ) throws LoginException;
/**
@@ -72,7 +71,7 @@
* @throws LoginException if there <code>name</code> is invalid (or there is no login context named "other"), or if the
* <code>callbackHandler</code> is null
*/
- ExecutionEnvironment create( String name,
+ ExecutionContext create( String name,
CallbackHandler callbackHandler ) throws LoginException;
/**
@@ -84,7 +83,7 @@
* callback handler JAAS property was not set or could not be loaded, if the <code>subject</code> is null or unknown,
* or if the <code>callbackHandler</code> is null
*/
- ExecutionEnvironment create( String name,
+ ExecutionContext create( String name,
Subject subject,
CallbackHandler callbackHandler ) throws LoginException;
Copied: trunk/dna-spi/src/main/java/org/jboss/dna/spi/ExecutionContexts.java (from rev 368, trunk/dna-spi/src/main/java/org/jboss/dna/spi/graph/connection/ExecutionEnvironments.java)
===================================================================
--- trunk/dna-spi/src/main/java/org/jboss/dna/spi/ExecutionContexts.java (rev 0)
+++ trunk/dna-spi/src/main/java/org/jboss/dna/spi/ExecutionContexts.java 2008-07-25 20:39:42 UTC (rev 371)
@@ -0,0 +1,193 @@
+/*
+ * 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;
+
+import javax.security.auth.Subject;
+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 contexts with replacement factories or components.
+ *
+ * @author Randall Hauch
+ */
+public class ExecutionContexts {
+
+ /**
+ * Create an context that can be used to replace the supplied context but that uses the supplied path factory.
+ *
+ * @param context the base context
+ * @param pathFactory the new path factory
+ * @return the new execution context
+ * @throws IllegalArgumentException if the context or factory references are null
+ */
+ public static ExecutionContext replace( ExecutionContext context,
+ PathFactory pathFactory ) {
+ ArgCheck.isNotNull(context, "context");
+ ArgCheck.isNotNull(pathFactory, "pathFactory");
+ return new DelegatingExecutionEnvironment(context, null, null, null, pathFactory);
+ }
+
+ /**
+ * Create an context that can be used to replace the supplied context but that uses the supplied name factory.
+ *
+ * @param context the base context
+ * @param nameFactory the new name factory
+ * @return the new execution context
+ * @throws IllegalArgumentException if the context or factory references are null
+ */
+ public static ExecutionContext replace( ExecutionContext context,
+ NameFactory nameFactory ) {
+ ArgCheck.isNotNull(context, "context");
+ ArgCheck.isNotNull(nameFactory, "nameFactory");
+ return new DelegatingExecutionEnvironment(context, null, null, nameFactory, null);
+ }
+
+ /**
+ * Create an context that can be used to replace the supplied context but that uses the supplied name and path factories.
+ *
+ * @param context the base context
+ * @param nameFactory the new name factory
+ * @param pathFactory the new path factory
+ * @return the new execution context
+ * @throws IllegalArgumentException if the context or factory references are null
+ */
+ public static ExecutionContext replace( ExecutionContext context,
+ NameFactory nameFactory,
+ PathFactory pathFactory ) {
+ ArgCheck.isNotNull(context, "context");
+ ArgCheck.isNotNull(nameFactory, "nameFactory");
+ ArgCheck.isNotNull(pathFactory, "pathFactory");
+ return new DelegatingExecutionEnvironment(context, null, null, nameFactory, pathFactory);
+ }
+
+ /**
+ * Create an context that can be used to replace the supplied context but that uses the supplied namespace registry.
+ *
+ * @param context the base context
+ * @param namespaceRegistry the new namespace registry
+ * @return the new execution context
+ * @throws IllegalArgumentException if the context or registry references are null
+ */
+ public static ExecutionContext replace( ExecutionContext context,
+ NamespaceRegistry namespaceRegistry ) {
+ ArgCheck.isNotNull(context, "context");
+ ArgCheck.isNotNull(namespaceRegistry, "namespaceRegistry");
+ return new DelegatingExecutionEnvironment(context, namespaceRegistry, null, null, null);
+ }
+
+ protected static class DelegatingExecutionEnvironment implements ExecutionContext {
+
+ private final ExecutionContext delegate;
+ private final NamespaceRegistry newNamespaceRegistry;
+ private final PropertyFactory newPropertyFactory;
+ private final ValueFactories newValueFactories;
+
+ public DelegatingExecutionEnvironment( ExecutionContext delegate,
+ NamespaceRegistry newRegistry,
+ PropertyFactory newPropertyFactory,
+ ValueFactories newValueFactories ) {
+ assert delegate != null;
+ this.delegate = delegate;
+ this.newNamespaceRegistry = newRegistry;
+ this.newPropertyFactory = newPropertyFactory;
+ this.newValueFactories = newValueFactories;
+ }
+
+ public DelegatingExecutionEnvironment( ExecutionContext 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.ExecutionContext#getNamespaceRegistry()
+ */
+ public NamespaceRegistry getNamespaceRegistry() {
+ if (newNamespaceRegistry != null) return newNamespaceRegistry;
+ return delegate.getNamespaceRegistry();
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.jboss.dna.spi.ExecutionContext#getPropertyFactory()
+ */
+ public PropertyFactory getPropertyFactory() {
+ if (newPropertyFactory != null) return newPropertyFactory;
+ return delegate.getPropertyFactory();
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.jboss.dna.spi.ExecutionContext#getValueFactories()
+ */
+ public ValueFactories getValueFactories() {
+ if (newValueFactories != null) return newValueFactories;
+ return delegate.getValueFactories();
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.jboss.dna.spi.ExecutionContext#getSubject()
+ */
+ public Subject getSubject() {
+ return delegate.getSubject();
+ }
+
+ /**
+ * @return delegate
+ */
+ protected ExecutionContext getDelegate() {
+ return delegate;
+ }
+
+ }
+}
Modified: trunk/dna-spi/src/main/java/org/jboss/dna/spi/graph/commands/executor/AbstractCommandExecutor.java
===================================================================
--- trunk/dna-spi/src/main/java/org/jboss/dna/spi/graph/commands/executor/AbstractCommandExecutor.java 2008-07-25 19:37:40 UTC (rev 370)
+++ trunk/dna-spi/src/main/java/org/jboss/dna/spi/graph/commands/executor/AbstractCommandExecutor.java 2008-07-25 20:39:42 UTC (rev 371)
@@ -21,6 +21,7 @@
*/
package org.jboss.dna.spi.graph.commands.executor;
+import org.jboss.dna.spi.ExecutionContext;
import org.jboss.dna.spi.graph.DateTime;
import org.jboss.dna.spi.graph.commands.CompositeCommand;
import org.jboss.dna.spi.graph.commands.CopyBranchCommand;
@@ -34,7 +35,6 @@
import org.jboss.dna.spi.graph.commands.MoveBranchCommand;
import org.jboss.dna.spi.graph.commands.RecordBranchCommand;
import org.jboss.dna.spi.graph.commands.SetPropertiesCommand;
-import org.jboss.dna.spi.graph.connection.ExecutionEnvironment;
import org.jboss.dna.spi.graph.connection.RepositoryConnection;
import org.jboss.dna.spi.graph.connection.RepositorySourceException;
@@ -47,42 +47,42 @@
* {@link DeleteBranchCommand}), the methods do nothing and should be overridden if the command is to be processed.
* <p>
* The implementation is also designed to be instantated as needed. This may be once per call to
- * {@link RepositoryConnection#execute(ExecutionEnvironment, GraphCommand...)}, or may be once per transaction. Either way, this
- * class is designed to allow subclasses to store additional state that may otherwise be expensive or undesirable to obtain
- * repeatedly. However, this state should be independent of the commands that are processed, meaning that implementations should
- * generally not change state as a result of processing specific commands.
+ * {@link RepositoryConnection#execute(ExecutionContext, GraphCommand...)}, or may be once per transaction. Either way, this class
+ * is designed to allow subclasses to store additional state that may otherwise be expensive or undesirable to obtain repeatedly.
+ * However, this state should be independent of the commands that are processed, meaning that implementations should generally not
+ * change state as a result of processing specific commands.
* </p>
*
* @author Randall Hauch
*/
public abstract class AbstractCommandExecutor implements CommandExecutor {
- private final ExecutionEnvironment env;
+ private final ExecutionContext context;
private final String sourceName;
private final DateTime nowInUtc;
- protected AbstractCommandExecutor( ExecutionEnvironment env,
+ protected AbstractCommandExecutor( ExecutionContext context,
String sourceName ) {
- this(env, sourceName, null);
+ this(context, sourceName, null);
}
- protected AbstractCommandExecutor( ExecutionEnvironment env,
+ protected AbstractCommandExecutor( ExecutionContext context,
String sourceName,
DateTime now ) {
- assert env != null;
+ assert context != null;
assert sourceName != null && sourceName.trim().length() != 0;
- this.env = env;
+ this.context = context;
this.sourceName = sourceName;
- this.nowInUtc = now != null ? now.toUtcTimeZone() : env.getValueFactories().getDateFactory().createUtc();
+ this.nowInUtc = now != null ? now.toUtcTimeZone() : context.getValueFactories().getDateFactory().createUtc();
}
/**
* Get the environment in which these commands are being executed.
*
- * @return the execution environment; never null
+ * @return the execution context; never null
*/
- public ExecutionEnvironment getEnvironment() {
- return env;
+ public ExecutionContext getEnvironment() {
+ return context;
}
/**
Modified: trunk/dna-spi/src/main/java/org/jboss/dna/spi/graph/commands/executor/NoOpCommandExecutor.java
===================================================================
--- trunk/dna-spi/src/main/java/org/jboss/dna/spi/graph/commands/executor/NoOpCommandExecutor.java 2008-07-25 19:37:40 UTC (rev 370)
+++ trunk/dna-spi/src/main/java/org/jboss/dna/spi/graph/commands/executor/NoOpCommandExecutor.java 2008-07-25 20:39:42 UTC (rev 371)
@@ -21,6 +21,7 @@
*/
package org.jboss.dna.spi.graph.commands.executor;
+import org.jboss.dna.spi.ExecutionContext;
import org.jboss.dna.spi.graph.DateTime;
import org.jboss.dna.spi.graph.commands.CompositeCommand;
import org.jboss.dna.spi.graph.commands.CopyBranchCommand;
@@ -34,7 +35,6 @@
import org.jboss.dna.spi.graph.commands.MoveBranchCommand;
import org.jboss.dna.spi.graph.commands.RecordBranchCommand;
import org.jboss.dna.spi.graph.commands.SetPropertiesCommand;
-import org.jboss.dna.spi.graph.connection.ExecutionEnvironment;
import org.jboss.dna.spi.graph.connection.RepositorySource;
import org.jboss.dna.spi.graph.connection.RepositorySourceException;
@@ -46,25 +46,25 @@
/**
* Create a command executor that does nothing.
*
- * @param env the execution environment in which the executor will be run; may not be null
+ * @param context the execution context in which the executor will be run; may not be null
* @param sourceName the name of the {@link RepositorySource} that is making use of this executor; may not be null or empty
*/
- public NoOpCommandExecutor( ExecutionEnvironment env,
+ public NoOpCommandExecutor( ExecutionContext context,
String sourceName ) {
- super(env, sourceName);
+ super(context, sourceName);
}
/**
* Create a command executor that does nothing.
*
- * @param env the execution environment in which the executor will be run; may not be null
+ * @param context the execution context in which the executor will be run; may not be null
* @param sourceName the name of the {@link RepositorySource} that is making use of this executor; may not be null or empty
* @param now the current time; may be null if the system time is to be used
*/
- public NoOpCommandExecutor( ExecutionEnvironment env,
+ public NoOpCommandExecutor( ExecutionContext context,
String sourceName,
DateTime now ) {
- super(env, sourceName, now);
+ super(context, sourceName, now);
}
/**
Copied: trunk/dna-spi/src/main/java/org/jboss/dna/spi/graph/connection/BasicExecutionContext.java (from rev 368, 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/BasicExecutionContext.java (rev 0)
+++ trunk/dna-spi/src/main/java/org/jboss/dna/spi/graph/connection/BasicExecutionContext.java 2008-07-25 20:39:42 UTC (rev 371)
@@ -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.spi.graph.connection;
+
+import javax.security.auth.Subject;
+import org.jboss.dna.common.util.ArgCheck;
+import org.jboss.dna.spi.ExecutionContext;
+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 BasicExecutionContext implements ExecutionContext {
+
+ private final Subject subject;
+ private final PropertyFactory propertyFactory;
+ private final ValueFactories valueFactories;
+ private final NamespaceRegistry namespaceRegistry;
+
+ public BasicExecutionContext() {
+ this(new Subject(), new BasicNamespaceRegistry());
+ }
+
+ public BasicExecutionContext( NamespaceRegistry namespaceRegistry ) {
+ this(new Subject(), namespaceRegistry, null, null);
+ }
+
+ public BasicExecutionContext( NamespaceRegistry namespaceRegistry,
+ ValueFactories valueFactories,
+ PropertyFactory propertyFactory ) {
+ this(new Subject(), namespaceRegistry, valueFactories, propertyFactory);
+ }
+
+ public BasicExecutionContext( Subject subject ) {
+ this(subject, new BasicNamespaceRegistry());
+ }
+
+ public BasicExecutionContext( Subject subject,
+ NamespaceRegistry namespaceRegistry ) {
+ this(subject, namespaceRegistry, null, null);
+ }
+
+ public BasicExecutionContext( Subject subject,
+ NamespaceRegistry namespaceRegistry,
+ ValueFactories valueFactories,
+ PropertyFactory propertyFactory ) {
+ ArgCheck.isNotNull(subject, "subject");
+ ArgCheck.isNotNull(namespaceRegistry, "namespace registry");
+ this.subject = subject;
+ 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;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.jboss.dna.spi.ExecutionContext#getSubject()
+ */
+ public Subject getSubject() {
+ return this.subject;
+ }
+}
Deleted: 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 2008-07-25 19:37:40 UTC (rev 370)
+++ trunk/dna-spi/src/main/java/org/jboss/dna/spi/graph/connection/BasicExecutionEnvironment.java 2008-07-25 20:39:42 UTC (rev 371)
@@ -1,78 +0,0 @@
-/*
- * 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;
- }
-}
Deleted: trunk/dna-spi/src/main/java/org/jboss/dna/spi/graph/connection/ExecutionEnvironment.java
===================================================================
--- trunk/dna-spi/src/main/java/org/jboss/dna/spi/graph/connection/ExecutionEnvironment.java 2008-07-25 19:37:40 UTC (rev 370)
+++ trunk/dna-spi/src/main/java/org/jboss/dna/spi/graph/connection/ExecutionEnvironment.java 2008-07-25 20:39:42 UTC (rev 371)
@@ -1,55 +0,0 @@
-/*
- * 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.spi.graph.NamespaceRegistry;
-import org.jboss.dna.spi.graph.Property;
-import org.jboss.dna.spi.graph.PropertyFactory;
-import org.jboss.dna.spi.graph.ValueFactories;
-
-/**
- * @author Randall Hauch
- */
-public interface ExecutionEnvironment {
-
- /**
- * Get the factories that should be used to create values for {@link Property properties}.
- *
- * @return the property value factory; never null
- */
- ValueFactories getValueFactories();
-
- /**
- * Get the namespace registry for this environment.
- *
- * @return the namespace registry; never null
- */
- NamespaceRegistry getNamespaceRegistry();
-
- /**
- * Get the factory for creating {@link Property} objects.
- *
- * @return the property factory; never null
- */
- PropertyFactory getPropertyFactory();
-
-}
Deleted: 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 2008-07-25 19:37:40 UTC (rev 370)
+++ trunk/dna-spi/src/main/java/org/jboss/dna/spi/graph/connection/ExecutionEnvironments.java 2008-07-25 20:39:42 UTC (rev 371)
@@ -1,184 +0,0 @@
-/*
- * 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;
- }
-
- }
-}
Modified: trunk/dna-spi/src/main/java/org/jboss/dna/spi/graph/connection/RepositoryConnection.java
===================================================================
--- trunk/dna-spi/src/main/java/org/jboss/dna/spi/graph/connection/RepositoryConnection.java 2008-07-25 19:37:40 UTC (rev 370)
+++ trunk/dna-spi/src/main/java/org/jboss/dna/spi/graph/connection/RepositoryConnection.java 2008-07-25 20:39:42 UTC (rev 371)
@@ -23,6 +23,7 @@
import java.util.concurrent.TimeUnit;
import javax.transaction.xa.XAResource;
+import org.jboss.dna.spi.ExecutionContext;
import org.jboss.dna.spi.cache.CachePolicy;
import org.jboss.dna.spi.graph.commands.GraphCommand;
@@ -61,7 +62,8 @@
* @return true if this connection is still valid and can still be used, or false otherwise
* @throws InterruptedException if the thread has been interrupted during the operation
*/
- boolean ping( long time, TimeUnit unit ) throws InterruptedException;
+ boolean ping( long time,
+ TimeUnit unit ) throws InterruptedException;
/**
* Set the listener that is to receive notifications to changes to content within this source.
@@ -80,12 +82,13 @@
/**
* Execute the supplied commands against this repository source.
*
- * @param env the environment in which the commands are being executed; never null
+ * @param context the environment in which the commands are being executed; never null
* @param commands the commands to be executed; never null
* @throws RepositorySourceException if there is a problem loading the node data
* @throws InterruptedException if the thread has been interrupted during the operation
*/
- void execute( ExecutionEnvironment env, GraphCommand... commands ) throws RepositorySourceException, InterruptedException;
+ void execute( ExecutionContext context,
+ GraphCommand... commands ) throws RepositorySourceException, InterruptedException;
/**
* Close this connection to signal that it is no longer needed and that any accumulated resources are to be released.
Modified: 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 2008-07-25 19:37:40 UTC (rev 370)
+++ trunk/dna-spi/src/main/java/org/jboss/dna/spi/graph/connection/RepositoryConnectionPool.java 2008-07-25 20:39:42 UTC (rev 371)
@@ -38,6 +38,7 @@
import net.jcip.annotations.ThreadSafe;
import org.jboss.dna.common.util.ArgCheck;
import org.jboss.dna.common.util.Logger;
+import org.jboss.dna.spi.ExecutionContext;
import org.jboss.dna.spi.SpiI18n;
import org.jboss.dna.spi.cache.CachePolicy;
import org.jboss.dna.spi.graph.commands.GraphCommand;
@@ -182,10 +183,10 @@
* @throws IllegalArgumentException if the connection factory is null or any of the supplied arguments are invalid
*/
public RepositoryConnectionPool( RepositoryConnectionFactory connectionFactory,
- int corePoolSize,
- int maximumPoolSize,
- long keepAliveTime,
- TimeUnit unit ) {
+ int corePoolSize,
+ int maximumPoolSize,
+ long keepAliveTime,
+ TimeUnit unit ) {
ArgCheck.isNonNegative(corePoolSize, "corePoolSize");
ArgCheck.isPositive(maximumPoolSize, "maximumPoolSize");
ArgCheck.isNonNegative(keepAliveTime, "keepAliveTime");
@@ -596,7 +597,8 @@
/**
* {@inheritDoc}
*
- * @see org.jboss.dna.spi.graph.connection.ManagedRepositoryConnectionFactory#awaitTermination(long, java.util.concurrent.TimeUnit)
+ * @see org.jboss.dna.spi.graph.connection.ManagedRepositoryConnectionFactory#awaitTermination(long,
+ * java.util.concurrent.TimeUnit)
*/
public boolean awaitTermination( long timeout,
TimeUnit unit ) throws InterruptedException {
@@ -928,10 +930,10 @@
/**
* {@inheritDoc}
*/
- public void execute( ExecutionEnvironment env,
+ public void execute( ExecutionContext context,
GraphCommand... commands ) throws RepositorySourceException, InterruptedException {
if (closed) throw new IllegalStateException(SpiI18n.closedConnectionMayNotBeUsed.text());
- this.original.execute(env, commands);
+ this.original.execute(context, commands);
}
/**
Modified: trunk/dna-spi/src/main/java/org/jboss/dna/spi/graph/connection/RepositoryOperation.java
===================================================================
--- trunk/dna-spi/src/main/java/org/jboss/dna/spi/graph/connection/RepositoryOperation.java 2008-07-25 19:37:40 UTC (rev 370)
+++ trunk/dna-spi/src/main/java/org/jboss/dna/spi/graph/connection/RepositoryOperation.java 2008-07-25 20:39:42 UTC (rev 371)
@@ -21,6 +21,8 @@
*/
package org.jboss.dna.spi.graph.connection;
+import org.jboss.dna.spi.ExecutionContext;
+
/**
* An operation that runs against a repository connection.
*
@@ -39,13 +41,13 @@
/**
* Run the operation using the supplied connection.
*
- * @param env the environment in which this operation is executing; may not be null
+ * @param context the environment in which this operation is executing; may not be null
* @param connection the connection; may not be null
* @return the result of the operation
* @throws RepositorySourceException if there is a problem with the connection
* @throws InterruptedException if this thread was interrupted
*/
- T run( ExecutionEnvironment env,
+ T run( ExecutionContext context,
RepositoryConnection connection ) throws RepositorySourceException, InterruptedException;
/**
Modified: trunk/dna-spi/src/main/java/org/jboss/dna/spi/graph/connection/RepositoryOperations.java
===================================================================
--- trunk/dna-spi/src/main/java/org/jboss/dna/spi/graph/connection/RepositoryOperations.java 2008-07-25 19:37:40 UTC (rev 370)
+++ trunk/dna-spi/src/main/java/org/jboss/dna/spi/graph/connection/RepositoryOperations.java 2008-07-25 20:39:42 UTC (rev 371)
@@ -27,6 +27,7 @@
import java.util.concurrent.Callable;
import org.jboss.dna.common.util.ArgCheck;
import org.jboss.dna.common.util.LogContext;
+import org.jboss.dna.spi.ExecutionContext;
/**
* @author Randall Hauch
@@ -37,18 +38,18 @@
* Call the supplied operation, using a connection from this pool.
*
* @param <T> the return type for the operation
- * @param env the environment in which the operation is to execute; may not be null
+ * @param context the context in which the operation is to execute; may not be null
* @param connectionFactory the factory for the connection to use
* @param operation the operation to be run using a new connection obtained from the factory
* @return the results from the operation
* @throws RepositorySourceException if there was an error obtaining the new connection
* @throws InterruptedException if the thread was interrupted during the operation
* @throws IllegalArgumentException if the operation is null
- * @see #createCallable(ExecutionEnvironment, RepositoryConnectionFactory, RepositoryOperation)
- * @see #createCallables(ExecutionEnvironment, RepositoryConnectionFactory, Iterable)
- * @see #createCallables(ExecutionEnvironment, RepositoryConnectionFactory, RepositoryOperation...)
+ * @see #createCallable(ExecutionContext, RepositoryConnectionFactory, RepositoryOperation)
+ * @see #createCallables(ExecutionContext, RepositoryConnectionFactory, Iterable)
+ * @see #createCallables(ExecutionContext, RepositoryConnectionFactory, RepositoryOperation...)
*/
- public static <T> T call( ExecutionEnvironment env,
+ public static <T> T call( ExecutionContext context,
RepositoryConnectionFactory connectionFactory,
RepositoryOperation<T> operation ) throws RepositorySourceException, InterruptedException {
ArgCheck.isNotNull(operation, "repository operation");
@@ -58,7 +59,7 @@
RepositoryConnection conn = connectionFactory.getConnection();
try {
// And run the client with the connection ...
- result = operation.run(env, conn);
+ result = operation.run(context, conn);
} finally {
conn.close();
}
@@ -71,15 +72,15 @@
* supplied factory.
*
* @param <T> the return type for the operation
- * @param env the environment in which the operation is to execute; may not be null
+ * @param context the context in which the operation is to execute; may not be null
* @param connectionFactory the factory for the connection to use
* @param operation the operation to be run using a new connection obtained from the factory
* @return the callable
- * @see #call(ExecutionEnvironment, RepositoryConnectionFactory, RepositoryOperation)
- * @see #createCallables(ExecutionEnvironment, RepositoryConnectionFactory, Iterable)
- * @see #createCallables(ExecutionEnvironment, RepositoryConnectionFactory, RepositoryOperation...)
+ * @see #call(ExecutionContext, RepositoryConnectionFactory, RepositoryOperation)
+ * @see #createCallables(ExecutionContext, RepositoryConnectionFactory, Iterable)
+ * @see #createCallables(ExecutionContext, RepositoryConnectionFactory, RepositoryOperation...)
*/
- public static <T> Callable<T> createCallable( final ExecutionEnvironment env,
+ public static <T> Callable<T> createCallable( final ExecutionContext context,
final RepositoryConnectionFactory connectionFactory,
final RepositoryOperation<T> operation ) {
ArgCheck.isNotNull(operation, "repository operation");
@@ -92,7 +93,7 @@
* @throws Exception
*/
public T call() throws Exception {
- return RepositoryOperations.call(env, connectionFactory, operation);
+ return RepositoryOperations.call(context, connectionFactory, operation);
}
};
}
@@ -102,20 +103,20 @@
* this pool.
*
* @param <T> the return type for the operations
- * @param env the environment in which the operation is to execute; may not be null
+ * @param context the context in which the operation is to execute; may not be null
* @param connectionFactory the factory for the connection to use
* @param operations the operations to be run using connections from the factory
* @return the collection of callables
- * @see #call(ExecutionEnvironment, RepositoryConnectionFactory, RepositoryOperation)
- * @see #createCallable(ExecutionEnvironment, RepositoryConnectionFactory, RepositoryOperation)
- * @see #createCallables(ExecutionEnvironment, RepositoryConnectionFactory, Iterable)
+ * @see #call(ExecutionContext, RepositoryConnectionFactory, RepositoryOperation)
+ * @see #createCallable(ExecutionContext, RepositoryConnectionFactory, RepositoryOperation)
+ * @see #createCallables(ExecutionContext, RepositoryConnectionFactory, Iterable)
*/
- public static <T> List<Callable<T>> createCallables( final ExecutionEnvironment env,
+ public static <T> List<Callable<T>> createCallables( final ExecutionContext context,
final RepositoryConnectionFactory connectionFactory,
final RepositoryOperation<T>... operations ) {
List<Callable<T>> callables = new ArrayList<Callable<T>>();
for (final RepositoryOperation<T> operation : operations) {
- callables.add(createCallable(env, connectionFactory, operation));
+ callables.add(createCallable(context, connectionFactory, operation));
}
return callables;
}
@@ -125,20 +126,20 @@
* this pool.
*
* @param <T> the return type for the operations
- * @param env the environment in which the operation is to execute; may not be null
+ * @param context the context in which the operation is to execute; may not be null
* @param connectionFactory the factory for the connection to use
* @param operations the operations to be run using connections from the factory
* @return the collection of callables
- * @see #call(ExecutionEnvironment, RepositoryConnectionFactory, RepositoryOperation)
- * @see #createCallable(ExecutionEnvironment, RepositoryConnectionFactory, RepositoryOperation)
- * @see #createCallables(ExecutionEnvironment, RepositoryConnectionFactory, RepositoryOperation...)
+ * @see #call(ExecutionContext, RepositoryConnectionFactory, RepositoryOperation)
+ * @see #createCallable(ExecutionContext, RepositoryConnectionFactory, RepositoryOperation)
+ * @see #createCallables(ExecutionContext, RepositoryConnectionFactory, RepositoryOperation...)
*/
- public static <T> List<Callable<T>> createCallables( final ExecutionEnvironment env,
+ public static <T> List<Callable<T>> createCallables( final ExecutionContext context,
final RepositoryConnectionFactory connectionFactory,
Iterable<RepositoryOperation<T>> operations ) {
List<Callable<T>> callables = new ArrayList<Callable<T>>();
for (final RepositoryOperation<T> operation : operations) {
- callables.add(createCallable(env, connectionFactory, operation));
+ callables.add(createCallable(context, connectionFactory, operation));
}
return callables;
}
@@ -148,21 +149,21 @@
* this pool.
*
* @param <T> the return type for the operations
- * @param env the environment in which the operation is to execute; may not be null
+ * @param context the context in which the operation is to execute; may not be null
* @param connectionFactory the factory for the connection to use
* @param operations the operations to be run using connections from the factory
* @return the collection of callables
- * @see #call(ExecutionEnvironment, RepositoryConnectionFactory, RepositoryOperation)
- * @see #createCallable(ExecutionEnvironment, RepositoryConnectionFactory, RepositoryOperation)
- * @see #createCallables(ExecutionEnvironment, RepositoryConnectionFactory, RepositoryOperation...)
+ * @see #call(ExecutionContext, RepositoryConnectionFactory, RepositoryOperation)
+ * @see #createCallable(ExecutionContext, RepositoryConnectionFactory, RepositoryOperation)
+ * @see #createCallables(ExecutionContext, RepositoryConnectionFactory, RepositoryOperation...)
*/
- public static <T> List<Callable<T>> createCallables( final ExecutionEnvironment env,
+ public static <T> List<Callable<T>> createCallables( final ExecutionContext context,
final RepositoryConnectionFactory connectionFactory,
Iterator<RepositoryOperation<T>> operations ) {
List<Callable<T>> callables = new ArrayList<Callable<T>>();
while (operations.hasNext()) {
final RepositoryOperation<T> operation = operations.next();
- callables.add(createCallable(env, connectionFactory, operation));
+ callables.add(createCallable(context, connectionFactory, operation));
}
return callables;
}
Modified: trunk/dna-spi/src/test/java/org/jboss/dna/spi/graph/commands/executor/AbstractCommandExecutorTest.java
===================================================================
--- trunk/dna-spi/src/test/java/org/jboss/dna/spi/graph/commands/executor/AbstractCommandExecutorTest.java 2008-07-25 19:37:40 UTC (rev 370)
+++ trunk/dna-spi/src/test/java/org/jboss/dna/spi/graph/commands/executor/AbstractCommandExecutorTest.java 2008-07-25 20:39:42 UTC (rev 371)
@@ -32,6 +32,7 @@
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
+import org.jboss.dna.spi.ExecutionContext;
import org.jboss.dna.spi.graph.commands.CompositeCommand;
import org.jboss.dna.spi.graph.commands.CopyBranchCommand;
import org.jboss.dna.spi.graph.commands.CopyNodeCommand;
@@ -44,8 +45,7 @@
import org.jboss.dna.spi.graph.commands.MoveBranchCommand;
import org.jboss.dna.spi.graph.commands.RecordBranchCommand;
import org.jboss.dna.spi.graph.commands.SetPropertiesCommand;
-import org.jboss.dna.spi.graph.connection.BasicExecutionEnvironment;
-import org.jboss.dna.spi.graph.connection.ExecutionEnvironment;
+import org.jboss.dna.spi.graph.connection.BasicExecutionContext;
import org.jboss.dna.spi.graph.connection.RepositorySourceException;
import org.junit.Before;
import org.junit.Test;
@@ -62,20 +62,20 @@
private AbstractCommandExecutor executor;
private GraphCommand command;
- private ExecutionEnvironment env;
+ private ExecutionContext context;
@Mock
protected CommandExecutor validator;
@Before
public void beforeEach() throws Exception {
MockitoAnnotations.initMocks(this);
- env = new BasicExecutionEnvironment();
- executor = new ExecutorImpl(env, "Source X", validator);
+ context = new BasicExecutionContext();
+ executor = new ExecutorImpl(context, "Source X", validator);
}
@Test
public void shouldHaveEnvironment() {
- assertThat(executor.getEnvironment(), is(sameInstance(env)));
+ assertThat(executor.getEnvironment(), is(sameInstance(context)));
}
@Test
@@ -214,10 +214,10 @@
private final CommandExecutor validator;
- protected ExecutorImpl( ExecutionEnvironment env,
+ protected ExecutorImpl( ExecutionContext context,
String name,
CommandExecutor validator ) {
- super(env, name);
+ super(context, name);
this.validator = validator;
}
Modified: trunk/dna-spi/src/test/java/org/jboss/dna/spi/graph/connection/RepositoryConnectionPoolTest.java
===================================================================
--- trunk/dna-spi/src/test/java/org/jboss/dna/spi/graph/connection/RepositoryConnectionPoolTest.java 2008-07-25 19:37:40 UTC (rev 370)
+++ trunk/dna-spi/src/test/java/org/jboss/dna/spi/graph/connection/RepositoryConnectionPoolTest.java 2008-07-25 20:39:42 UTC (rev 371)
@@ -28,6 +28,7 @@
import java.util.List;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
+import org.jboss.dna.spi.ExecutionContext;
import org.junit.After;
import org.junit.Before;
import org.junit.Ignore;
@@ -40,13 +41,13 @@
private RepositoryConnectionPool pool;
private TimeDelayingRepositorySource repositorySource;
- private ExecutionEnvironment env;
+ private ExecutionContext context;
@Before
public void beforeEach() {
this.repositorySource = new TimeDelayingRepositorySource("source 1");
this.pool = new RepositoryConnectionPool(this.repositorySource, 1, 1, 100, TimeUnit.SECONDS);
- this.env = null;
+ this.context = null;
}
@After
@@ -164,7 +165,7 @@
pool.setCorePoolSize(numConnectionsInPool);
pool.setMaximumPoolSize(numConnectionsInPool);
RepositoryOperation.Factory<Integer> operationFactory = RepositorySourceLoadHarness.createMultipleLoadOperationFactory(10);
- runLoadTest(env, pool, numClients, 100, TimeUnit.MILLISECONDS, operationFactory);
+ runLoadTest(context, pool, numClients, 100, TimeUnit.MILLISECONDS, operationFactory);
pool.shutdown();
pool.awaitTermination(4, TimeUnit.SECONDS);
}
@@ -177,7 +178,7 @@
pool.setCorePoolSize(numConnectionsInPool);
pool.setMaximumPoolSize(numConnectionsInPool);
RepositoryOperation.Factory<Integer> operationFactory = RepositorySourceLoadHarness.createMultipleLoadOperationFactory(10);
- runLoadTest(env, pool, numClients, 100, TimeUnit.MILLISECONDS, operationFactory);
+ runLoadTest(context, pool, numClients, 100, TimeUnit.MILLISECONDS, operationFactory);
pool.shutdown();
pool.awaitTermination(4, TimeUnit.SECONDS);
}
@@ -190,7 +191,7 @@
pool.setCorePoolSize(numConnectionsInPool);
pool.setMaximumPoolSize(numConnectionsInPool);
RepositoryOperation.Factory<Integer> operationFactory = RepositorySourceLoadHarness.createMultipleLoadOperationFactory(10);
- runLoadTest(env, pool, numClients, 100, TimeUnit.MILLISECONDS, operationFactory);
+ runLoadTest(context, pool, numClients, 100, TimeUnit.MILLISECONDS, operationFactory);
pool.shutdown();
pool.awaitTermination(4, TimeUnit.SECONDS);
}
@@ -204,7 +205,7 @@
pool.setCorePoolSize(numConnectionsInPool);
pool.setMaximumPoolSize(numConnectionsInPool);
RepositoryOperation.Factory<Integer> operationFactory = RepositorySourceLoadHarness.createMultipleLoadOperationFactory(20);
- List<Future<Integer>> results = runLoadTest(env, pool, numClients, 200, TimeUnit.MILLISECONDS, operationFactory);
+ List<Future<Integer>> results = runLoadTest(context, pool, numClients, 200, TimeUnit.MILLISECONDS, operationFactory);
int total = 0;
for (Future<Integer> result : results) {
assertThat(result.isDone(), is(true));
Modified: trunk/dna-spi/src/test/java/org/jboss/dna/spi/graph/connection/RepositorySourceLoadHarness.java
===================================================================
--- trunk/dna-spi/src/test/java/org/jboss/dna/spi/graph/connection/RepositorySourceLoadHarness.java 2008-07-25 19:37:40 UTC (rev 370)
+++ trunk/dna-spi/src/test/java/org/jboss/dna/spi/graph/connection/RepositorySourceLoadHarness.java 2008-07-25 20:39:42 UTC (rev 371)
@@ -33,6 +33,7 @@
import java.util.concurrent.TimeUnit;
import org.jboss.dna.common.i18n.MockI18n;
import org.jboss.dna.common.util.Logger;
+import org.jboss.dna.spi.ExecutionContext;
/**
* A test harness for using repository connections under load.
@@ -42,17 +43,22 @@
public class RepositorySourceLoadHarness {
public static Future<Integer> execute( RepositoryConnectionFactory connectionFactory,
- ExecutionEnvironment env,
+ ExecutionContext context,
long maxTime,
TimeUnit maxTimeUnit ) throws InterruptedException {
int numTimes = 1;
int numClients = 1;
RepositoryOperation.Factory<Integer> operationFactory = RepositorySourceLoadHarness.createMultipleLoadOperationFactory(numTimes);
- List<Future<Integer>> results = runLoadTest(env, connectionFactory, numClients, maxTime, maxTimeUnit, operationFactory);
+ List<Future<Integer>> results = runLoadTest(context,
+ connectionFactory,
+ numClients,
+ maxTime,
+ maxTimeUnit,
+ operationFactory);
return results.get(0);
}
- public static <T> List<Future<T>> runLoadTest( ExecutionEnvironment env,
+ public static <T> List<Future<T>> runLoadTest( ExecutionContext context,
RepositoryConnectionFactory connectionFactory,
int numClients,
long maxTime,
@@ -65,10 +71,10 @@
}
// and run the test ...
- return runLoadTest(env, connectionFactory, maxTime, maxTimeUnit, clients);
+ return runLoadTest(context, connectionFactory, maxTime, maxTimeUnit, clients);
}
- public static <T> List<Future<T>> runLoadTest( ExecutionEnvironment env,
+ public static <T> List<Future<T>> runLoadTest( ExecutionContext context,
RepositoryConnectionFactory connectionFactory,
long maxTime,
TimeUnit maxTimeUnit,
@@ -79,10 +85,10 @@
if (client != null) clientCollection.add(client);
}
// and run the test ...
- return runLoadTest(env, connectionFactory, maxTime, maxTimeUnit, clientCollection);
+ return runLoadTest(context, connectionFactory, maxTime, maxTimeUnit, clientCollection);
}
- public static <T> List<Future<T>> runLoadTest( ExecutionEnvironment env,
+ public static <T> List<Future<T>> runLoadTest( ExecutionContext context,
RepositoryConnectionFactory connectionFactory,
long maxTime,
TimeUnit maxTimeUnit,
@@ -102,7 +108,7 @@
try {
// Wrap each client by a callable and by another that uses a latch ...
- List<Callable<T>> callables = RepositoryOperations.createCallables(env, connectionFactory, clients);
+ List<Callable<T>> callables = RepositoryOperations.createCallables(context, connectionFactory, clients);
// Run the tests ...
List<Future<T>> futures = clientPool.invokeAll(callables, maxTime, maxTimeUnit);
@@ -164,7 +170,7 @@
/**
* Return an operation factory that produces {@link RepositoryOperation} instances that each call
- * {@link RepositoryConnection#execute(ExecutionEnvironment, org.jboss.dna.spi.graph.commands.GraphCommand...)} the supplied
+ * {@link RepositoryConnection#execute(ExecutionContext, org.jboss.dna.spi.graph.commands.GraphCommand...)} the supplied
* number of times, intermixed with random math operations and {@link Thread#yield() yielding}.
*
* @param callsPerOperation the number of <code>load</code> calls per RepositoryOperation
@@ -198,10 +204,10 @@
/**
* {@inheritDoc}
*
- * @see org.jboss.dna.spi.graph.connection.RepositoryOperation#run(org.jboss.dna.spi.graph.connection.ExecutionEnvironment,
+ * @see org.jboss.dna.spi.graph.connection.RepositoryOperation#run(org.jboss.dna.spi.ExecutionContext,
* org.jboss.dna.spi.graph.connection.RepositoryConnection)
*/
- public Integer run( ExecutionEnvironment env,
+ public Integer run( ExecutionContext context,
RepositoryConnection connection ) throws RepositorySourceException, InterruptedException {
Logger.getLogger(RepositorySourceLoadHarness.class).debug("Running {0} operation", this.getClass().getSimpleName());
int total = count;
@@ -211,7 +217,7 @@
if (i % 2 == 0) {
Thread.yield();
}
- connection.execute(env);
+ connection.execute(context);
int int2 = random(this.hashCode() ^ (int)System.nanoTime() + i);
total += Math.min(Math.abs(Math.max(int1, int2) + int1 * int2 / 3), count);
}
Modified: trunk/dna-spi/src/test/java/org/jboss/dna/spi/graph/connection/SimpleRepository.java
===================================================================
--- trunk/dna-spi/src/test/java/org/jboss/dna/spi/graph/connection/SimpleRepository.java 2008-07-25 19:37:40 UTC (rev 370)
+++ trunk/dna-spi/src/test/java/org/jboss/dna/spi/graph/connection/SimpleRepository.java 2008-07-25 20:39:42 UTC (rev 371)
@@ -28,21 +28,21 @@
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import net.jcip.annotations.ThreadSafe;
+import org.jboss.dna.spi.ExecutionContext;
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.
+ * {@link #delete(ExecutionContext, String) deleted} or {@link #create(ExecutionContext, String) explicitly} or
+ * {@link #setProperty(ExecutionContext, String, String, Object...) implicitly} created.
* </p>
*
* @author Randall Hauch
@@ -93,21 +93,21 @@
* 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 context the execution context; 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,
+ public SimpleRepository setProperty( ExecutionContext context,
String path,
String propertyName,
Object... values ) {
- PathFactory pathFactory = env.getValueFactories().getPathFactory();
- NameFactory nameFactory = env.getValueFactories().getNameFactory();
- PropertyFactory propertyFactory = env.getPropertyFactory();
+ PathFactory pathFactory = context.getValueFactories().getPathFactory();
+ NameFactory nameFactory = context.getValueFactories().getNameFactory();
+ PropertyFactory propertyFactory = context.getPropertyFactory();
Path pathObj = pathFactory.create(path);
- create(env, pathObj.getAncestor().getString(env.getNamespaceRegistry()));
+ create(context, pathObj.getAncestor().getString(context.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);
@@ -119,13 +119,13 @@
/**
* Create the node if it does not exist.
*
- * @param env the environment; may not be null
+ * @param context the execution context; 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,
+ public SimpleRepository create( ExecutionContext context,
String path ) {
- PathFactory pathFactory = env.getValueFactories().getPathFactory();
+ PathFactory pathFactory = context.getValueFactories().getPathFactory();
Path pathObj = pathFactory.create(path);
Path ancestorPath = pathObj.getAncestor();
while (!ancestorPath.isRoot()) {
@@ -139,13 +139,13 @@
/**
* Delete the branch rooted at the supplied path, if it exists.
*
- * @param env the environment; may not be null
+ * @param context the execution context; 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,
+ public SimpleRepository delete( ExecutionContext context,
String path ) {
- PathFactory pathFactory = env.getValueFactories().getPathFactory();
+ PathFactory pathFactory = context.getValueFactories().getPathFactory();
Path pathObj = pathFactory.create(path);
List<Path> pathsToRemove = new LinkedList<Path>();
for (Path nodePath : data.keySet()) {
Modified: trunk/dna-spi/src/test/java/org/jboss/dna/spi/graph/connection/SimpleRepositorySource.java
===================================================================
--- trunk/dna-spi/src/test/java/org/jboss/dna/spi/graph/connection/SimpleRepositorySource.java 2008-07-25 19:37:40 UTC (rev 370)
+++ trunk/dna-spi/src/test/java/org/jboss/dna/spi/graph/connection/SimpleRepositorySource.java 2008-07-25 20:39:42 UTC (rev 371)
@@ -29,6 +29,7 @@
import javax.naming.Reference;
import javax.transaction.xa.XAResource;
import net.jcip.annotations.ThreadSafe;
+import org.jboss.dna.spi.ExecutionContext;
import org.jboss.dna.spi.cache.CachePolicy;
import org.jboss.dna.spi.graph.InvalidPathException;
import org.jboss.dna.spi.graph.Name;
@@ -158,28 +159,28 @@
/**
* {@inheritDoc}
*
- * @see org.jboss.dna.spi.graph.connection.RepositoryConnection#execute(org.jboss.dna.spi.graph.connection.ExecutionEnvironment,
+ * @see org.jboss.dna.spi.graph.connection.RepositoryConnection#execute(org.jboss.dna.spi.ExecutionContext,
* org.jboss.dna.spi.graph.commands.GraphCommand[])
*/
- public void execute( ExecutionEnvironment env,
+ public void execute( ExecutionContext context,
GraphCommand... commands ) throws RepositorySourceException {
- assert env != null;
+ assert context != null;
if (repository.isShutdown()) {
throw new RepositorySourceException(getName(), "The repository \"" + repository.getRepositoryName()
+ "\" is no longer available");
}
for (GraphCommand command : commands) {
- executeCommand(env, command);
+ executeCommand(context, command);
}
}
- protected void executeCommand( ExecutionEnvironment env,
+ protected void executeCommand( ExecutionContext context,
GraphCommand command ) {
if (command == null) return;
if (command instanceof CompositeCommand) {
CompositeCommand composite = (CompositeCommand)command;
for (GraphCommand nestedCommand : composite) {
- executeCommand(env, nestedCommand);
+ executeCommand(context, nestedCommand);
}
}
Map<Path, Map<Name, Property>> data = repository.getData();
Modified: trunk/dna-spi/src/test/java/org/jboss/dna/spi/graph/connection/TimeDelayingRepositorySource.java
===================================================================
--- trunk/dna-spi/src/test/java/org/jboss/dna/spi/graph/connection/TimeDelayingRepositorySource.java 2008-07-25 19:37:40 UTC (rev 370)
+++ trunk/dna-spi/src/test/java/org/jboss/dna/spi/graph/connection/TimeDelayingRepositorySource.java 2008-07-25 20:39:42 UTC (rev 371)
@@ -32,6 +32,7 @@
import javax.naming.Reference;
import javax.transaction.xa.XAResource;
import net.jcip.annotations.ThreadSafe;
+import org.jboss.dna.spi.ExecutionContext;
import org.jboss.dna.spi.cache.CachePolicy;
import org.jboss.dna.spi.graph.commands.GraphCommand;
@@ -252,7 +253,7 @@
/**
* {@inheritDoc}
*/
- public void execute( ExecutionEnvironment env,
+ public void execute( ExecutionContext context,
GraphCommand... commands ) throws InterruptedException {
long delay = this.loadDelay.get();
if (delay > 0l) Thread.sleep(delay);
Modified: trunk/docs/examples/gettingstarted/sequencers/src/main/java/org/jboss/example/dna/sequencers/SequencingClient.java
===================================================================
--- trunk/docs/examples/gettingstarted/sequencers/src/main/java/org/jboss/example/dna/sequencers/SequencingClient.java 2008-07-25 19:37:40 UTC (rev 370)
+++ trunk/docs/examples/gettingstarted/sequencers/src/main/java/org/jboss/example/dna/sequencers/SequencingClient.java 2008-07-25 20:39:42 UTC (rev 371)
@@ -47,10 +47,10 @@
import org.jboss.dna.repository.observation.ObservationService;
import org.jboss.dna.repository.sequencers.SequencerConfig;
import org.jboss.dna.repository.sequencers.SequencingService;
-import org.jboss.dna.repository.util.ExecutionContext;
+import org.jboss.dna.repository.util.JcrExecutionContext;
import org.jboss.dna.repository.util.JcrTools;
import org.jboss.dna.repository.util.SessionFactory;
-import org.jboss.dna.repository.util.SimpleExecutionContext;
+import org.jboss.dna.repository.util.BasicJcrExecutionContext;
import org.jboss.dna.repository.util.SimpleSessionFactory;
/**
@@ -82,7 +82,7 @@
private SequencingService sequencingService;
private ObservationService observationService;
private UserInterface userInterface;
- private ExecutionContext executionContext;
+ private JcrExecutionContext executionContext;
public SequencingClient() {
setJackrabbitConfigPath(DEFAULT_JACKRABBIT_CONFIG_PATH);
@@ -208,7 +208,7 @@
// Create an execution context for the sequencing service. This execution context provides an environment
// for the DNA services which knows about the JCR repositories, workspaces, and credentials used to
- // establish sessions to these workspaces. This example uses the SimpleExecutionContext, but there is
+ // establish sessions to these workspaces. This example uses the BasicJcrExecutionContext, but there is
// implementation for use with JCR repositories registered in JNDI.
final String repositoryWorkspaceName = this.repositoryName + "/" + this.workspaceName;
SimpleSessionFactory sessionFactory = new SimpleSessionFactory();
@@ -217,7 +217,7 @@
Credentials credentials = new SimpleCredentials(this.username, this.password);
sessionFactory.registerCredentials(repositoryWorkspaceName, credentials);
}
- this.executionContext = new SimpleExecutionContext(sessionFactory, repositoryWorkspaceName);
+ this.executionContext = new BasicJcrExecutionContext(sessionFactory, repositoryWorkspaceName);
// Create the sequencing service, passing in the execution context ...
this.sequencingService = new SequencingService();
15 years, 9 months
DNA SVN: r370 - in trunk: connectors/dna-connector-federation/src/test/java/org/jboss/dna/connector/federation and 5 other directories.
by dna-commits@lists.jboss.org
Author: rhauch
Date: 2008-07-25 15:37:40 -0400 (Fri, 25 Jul 2008)
New Revision: 370
Added:
trunk/dna-spi/src/main/java/org/jboss/dna/spi/graph/connection/AbstractRepositorySource.java
trunk/dna-spi/src/main/java/org/jboss/dna/spi/graph/connection/ManagedRepositoryConnectionFactory.java
trunk/dna-spi/src/main/java/org/jboss/dna/spi/graph/connection/RepositoryConnectionPool.java
trunk/dna-spi/src/test/java/org/jboss/dna/spi/graph/connection/RepositoryConnectionPoolTest.java
Removed:
trunk/dna-spi/src/main/java/org/jboss/dna/spi/graph/connection/BasicRepositoryConnectionPool.java
trunk/dna-spi/src/main/java/org/jboss/dna/spi/graph/connection/RepositoryConnectionPool.java
trunk/dna-spi/src/test/java/org/jboss/dna/spi/graph/connection/BasicRepositoryConnectionPoolTest.java
Modified:
trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/FederatedRepositorySource.java
trunk/connectors/dna-connector-federation/src/test/java/org/jboss/dna/connector/federation/FederatedRepositorySourceTest.java
trunk/connectors/dna-connector-federation/src/test/java/org/jboss/dna/connector/federation/FederatedRepositoryTest.java
trunk/connectors/dna-connector-inmemory/src/main/java/org/jboss/dna/connector/inmemory/InMemoryRepositorySource.java
trunk/connectors/dna-connector-jbosscache/src/main/java/org/jboss/dna/connector/jbosscache/JBossCacheSource.java
trunk/dna-repository/src/main/java/org/jboss/dna/repository/RepositorySourceManager.java
trunk/dna-spi/src/main/java/org/jboss/dna/spi/graph/connection/RepositorySource.java
trunk/dna-spi/src/test/java/org/jboss/dna/spi/graph/connection/SimpleRepositorySource.java
trunk/dna-spi/src/test/java/org/jboss/dna/spi/graph/connection/TimeDelayingRepositorySource.java
Log:
DNA-189 - Change RepositorySource to extend the ManagedRepositoryConnectionFactory interface, so it has management methods
http://jira.jboss.com/jira/browse/DNA-189
The RepositorySource only has methods for getting/setting properties and creating connections. This means that managing the set of connections is not part of the interface, and this results in the RepositorySource instances needing to be wrapped by RepositoryConnectionPools. This makes it more difficult (and less consistent) to manage the instances.
Change name of RepositoryConnectionPool interface to ManagedRepositoryConnectionFactory
Change RepositorySource to extend the ManagedRepositoryConnectionFactory interface (rather than RepositoryConnectionFactory)
Change name of BasicRepositoryConnectionPool to RepositoryConnectionPool (since there is no "pool" interface anymore)
Create an AbstractRepositorySource implementation that uses a pool to manage the instances
Change the existing RepositorySource implementations to extend AbstractRepositorySource (this is not required, but it does encapsulate the management of the connections)
Clean up RepositorySourceManager, since it no longer needs to distinguish between RepositorySource and pools (since all RepositorySource are now manageable)
Modified: trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/FederatedRepositorySource.java
===================================================================
--- trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/FederatedRepositorySource.java 2008-07-24 19:52:13 UTC (rev 369)
+++ trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/FederatedRepositorySource.java 2008-07-25 19:37:40 UTC (rev 370)
@@ -66,6 +66,7 @@
import org.jboss.dna.spi.graph.commands.impl.BasicCompositeCommand;
import org.jboss.dna.spi.graph.commands.impl.BasicGetChildrenCommand;
import org.jboss.dna.spi.graph.commands.impl.BasicGetNodeCommand;
+import org.jboss.dna.spi.graph.connection.AbstractRepositorySource;
import org.jboss.dna.spi.graph.connection.ExecutionEnvironment;
import org.jboss.dna.spi.graph.connection.RepositoryConnection;
import org.jboss.dna.spi.graph.connection.RepositoryConnectionFactories;
@@ -76,13 +77,12 @@
* @author Randall Hauch
*/
@ThreadSafe
-public class FederatedRepositorySource implements RepositorySource {
+public class FederatedRepositorySource extends AbstractRepositorySource {
/**
*/
private static final long serialVersionUID = 7587346948013486977L;
- public static final int DEFAULT_RETRY_LIMIT = 0;
public static final String[] DEFAULT_CONFIGURATION_SOURCE_PROJECTION_RULES = {"/dna:system => /"};
protected static final String REPOSITORY_NAME = "repositoryName";
@@ -111,7 +111,6 @@
private String executionContextFactoryJndiName;
private String securityDomain;
private String repositoryJndiName;
- private int retryLimit = DEFAULT_RETRY_LIMIT;
private transient FederatedRepository repository;
private transient Context jndiContext;
@@ -120,6 +119,7 @@
* repository name}.
*/
public FederatedRepositorySource() {
+ super();
}
/**
@@ -129,6 +129,7 @@
* @throws IllegalArgumentException if the federation service is null or the repository name is null or blank
*/
public FederatedRepositorySource( String repositoryName ) {
+ super();
ArgCheck.isNotNull(repositoryName, "repositoryName");
this.repositoryName = repositoryName;
}
@@ -136,323 +137,6 @@
/**
* {@inheritDoc}
*/
- public int getRetryLimit() {
- return this.retryLimit;
- }
-
- /**
- * {@inheritDoc}
- */
- public void setRetryLimit( int limit ) {
- this.retryLimit = limit > 0 ? limit : 0;
- }
-
- /**
- * {@inheritDoc}
- */
- public synchronized RepositoryConnection getConnection() throws RepositorySourceException {
- if (getName() == null) {
- throw new RepositorySourceException(FederationI18n.propertyIsRequired.text("name"));
- }
- if (getExecutionContextFactoryJndiName() == null) {
- throw new RepositorySourceException(FederationI18n.propertyIsRequired.text("execution context factory JNDI name"));
- }
- if (getSecurityDomain() == null) {
- throw new RepositorySourceException(FederationI18n.propertyIsRequired.text("security domain"));
- }
- if (getConnectionFactoriesJndiName() == null) {
- throw new RepositorySourceException(FederationI18n.propertyIsRequired.text("connection factories JNDI name"));
- }
- // Find the repository ...
- FederatedRepository repository = getRepository();
- // Authenticate the user ...
- String username = this.username;
- Object credentials = this.password;
- RepositoryConnection connection = repository.createConnection(this, username, credentials);
- if (connection == null) {
- I18n msg = FederationI18n.unableToAuthenticateConnectionToFederatedRepository;
- throw new RepositorySourceException(msg.text(this.repositoryName, username));
- }
- // Return the new connection ...
- return connection;
- }
-
- /**
- * Get the {@link FederatedRepository} instance that this source is using. This method uses the following logic:
- * <ol>
- * <li>If a {@link FederatedRepository} already was obtained from a prior call, the same instance is returned.</li>
- * <li>A {@link FederatedRepository} is created using a {@link FederatedRepositoryConfig} is created from this instance's
- * properties and {@link ExecutionEnvironment} and {@link RepositoryConnectionFactories} instances obtained from JNDI.</li>
- * <li></li>
- * <li></li>
- * </ol>
- *
- * @return the federated repository instance
- * @throws RepositorySourceException
- */
- protected synchronized FederatedRepository getRepository() throws RepositorySourceException {
- if (repository == null) {
- String jndiName = this.getRepositoryJndiName();
- Context context = getContext();
- if (jndiName != null && jndiName.trim().length() != 0) {
- // Look for an existing repository in JNDI ...
- try {
- if (context == null) context = new InitialContext();
- repository = (FederatedRepository)context.lookup(jndiName);
- } catch (Throwable err) {
- I18n msg = FederationI18n.unableToFindFederatedRepositoryInJndi;
- throw new RepositorySourceException(msg.text(this.sourceName, jndiName), err);
- }
- }
-
- if (repository == null) {
- // Find in JNDI the repository connection factories and the environment ...
- ExecutionEnvironment env = getExecutionEnvironment();
- RepositoryConnectionFactories factories = getRepositoryConnectionFactories();
- // And create the configuration and the repository ...
- FederatedRepositoryConfig config = getRepositoryConfiguration(env, factories);
- repository = new FederatedRepository(env, factories, config);
- }
- }
- return repository;
- }
-
- protected ExecutionEnvironment getExecutionEnvironment() {
- ExecutionContextFactory factory = null;
- Context context = getContext();
- String jndiName = getExecutionContextFactoryJndiName();
- if (jndiName != null && jndiName.trim().length() != 0) {
- try {
- if (context == null) context = new InitialContext();
- factory = (ExecutionContextFactory)context.lookup(jndiName);
- } catch (Throwable err) {
- I18n msg = FederationI18n.unableToFindExecutionContextFactoryInJndi;
- throw new RepositorySourceException(msg.text(this.sourceName, jndiName), err);
- }
- }
- if (factory == null) {
- I18n msg = FederationI18n.unableToFindExecutionContextFactoryInJndi;
- throw new RepositorySourceException(msg.text(this.sourceName, jndiName));
- }
- String securityDomain = getSecurityDomain();
- CallbackHandler handler = createCallbackHandler();
- try {
- return factory.create(securityDomain, handler);
- } catch (LoginException e) {
- I18n msg = FederationI18n.unableToCreateExecutionContext;
- throw new RepositorySourceException(msg.text(this.sourceName, jndiName, securityDomain), e);
- }
- }
-
- protected RepositoryConnectionFactories getRepositoryConnectionFactories() {
- RepositoryConnectionFactories factories = null;
- Context context = getContext();
- String jndiName = getConnectionFactoriesJndiName();
- if (jndiName != null && jndiName.trim().length() != 0) {
- try {
- if (context == null) context = new InitialContext();
- factories = (RepositoryConnectionFactories)context.lookup(jndiName);
- } catch (Throwable err) {
- I18n msg = FederationI18n.unableToFindRepositoryConnectionFactoriesInJndi;
- throw new RepositorySourceException(msg.text(this.sourceName, jndiName), err);
- }
- }
- if (factories == null) {
- I18n msg = FederationI18n.noRepositoryConnectionFactories;
- throw new RepositorySourceException(msg.text(this.repositoryName));
- }
- return factories;
- }
-
- protected CallbackHandler createCallbackHandler() {
- return new CallbackHandler() {
- public void handle( Callback[] callbacks ) {
- for (Callback callback : callbacks) {
- if (callback instanceof NameCallback) {
- NameCallback nameCallback = (NameCallback)callback;
- nameCallback.setName(FederatedRepositorySource.this.getUsername());
- }
- if (callback instanceof PasswordCallback) {
- PasswordCallback passwordCallback = (PasswordCallback)callback;
- passwordCallback.setPassword(FederatedRepositorySource.this.getPassword().toCharArray());
- }
- }
- }
- };
- }
-
- protected Context getContext() {
- return this.jndiContext;
- }
-
- protected synchronized void setContext( Context context ) {
- this.jndiContext = context;
- }
-
- /**
- * Create a {@link FederatedRepositoryConfig} instance from the current properties of this instance. This method does
- * <i>not</i> modify the state of this instance.
- *
- * @param env the execution environment that should be used to read the configuration; may not be null
- * @param factories the factories from which can be obtained the RepositoryConnectionFactory instances for each name source;
- * may not be null
- * @return a configuration reflecting the current state of this instance
- */
- protected synchronized FederatedRepositoryConfig getRepositoryConfiguration( ExecutionEnvironment env,
- RepositoryConnectionFactories factories ) {
- Problems problems = new SimpleProblems();
- ValueFactories valueFactories = env.getValueFactories();
- PathFactory pathFactory = valueFactories.getPathFactory();
- NameFactory nameFactory = valueFactories.getNameFactory();
- ValueFactory<Long> longFactory = valueFactories.getLongFactory();
-
- // Create the configuration projection ...
- ProjectionParser projectionParser = ProjectionParser.getInstance();
- Projection.Rule[] rules = projectionParser.rulesFromStrings(env, this.getConfigurationSourceProjectionRules());
- Projection configurationProjection = new Projection(this.getConfigurationSourceName(), rules);
-
- // Create a federating command executor to execute the commands and merge the results into a single set of
- // commands.
- final String configurationSourceName = configurationProjection.getSourceName();
- List<Projection> projections = Collections.singletonList(configurationProjection);
- CommandExecutor executor = null;
- if (configurationProjection.getRules().size() == 1) {
- // There is just a single projection for the configuration repository, so just use an executor that
- // translates the paths using the projection
- executor = new SingleProjectionCommandExecutor(env, configurationSourceName, configurationProjection, factories);
- } else if (configurationProjection.getRules().size() == 0) {
- // There is no projection for the configuration repository, so just use a no-op executor
- executor = new NoOpCommandExecutor(env, configurationSourceName);
- } else {
- // The configuration repository has more than one projection, so we need to merge the results
- executor = new FederatingCommandExecutor(env, configurationSourceName, null, projections, factories);
- }
- // Wrap the executor with a logging executor ...
- executor = new LoggingCommandExecutor(executor, Logger.getLogger(getClass()), Logger.Level.INFO);
-
- // The configuration projection (via "executor") will convert this path into a path that exists in the configuration
- // repository
- Path configNode = pathFactory.create("/dna:system/dna:federation");
-
- try {
- // Get the repository node ...
- BasicGetNodeCommand getRepository = new BasicGetNodeCommand(configNode);
- executor.execute(getRepository);
- if (getRepository.hasError()) {
- throw new FederationException(FederationI18n.federatedRepositoryCannotBeFound.text(repositoryName));
- }
-
- // Add a command to get the projection defining the cache ...
- Path pathToCacheRegion = pathFactory.create(configNode, nameFactory.create("dna:cache"));
- BasicGetNodeCommand getCacheRegion = new BasicGetNodeCommand(pathToCacheRegion);
- executor.execute(getCacheRegion);
- Projection cacheProjection = createProjection(env,
- projectionParser,
- getCacheRegion.getPath(),
- getCacheRegion.getProperties(),
- problems);
-
- if (getCacheRegion.hasError()) {
- I18n msg = FederationI18n.requiredNodeDoesNotExistRelativeToNode;
- throw new FederationException(msg.text("dna:cache", configNode));
- }
-
- // Get the source projections for the repository ...
- Path projectionsNode = pathFactory.create(configNode, nameFactory.create("dna:projections"));
- BasicGetChildrenCommand getProjections = new BasicGetChildrenCommand(projectionsNode);
-
- executor.execute(getProjections);
- if (getProjections.hasError()) {
- I18n msg = FederationI18n.requiredNodeDoesNotExistRelativeToNode;
- throw new FederationException(msg.text("dna:projections", configNode));
- }
-
- // Build the commands to get each of the projections (children of the "dna:projections" node) ...
- List<Projection> sourceProjections = new LinkedList<Projection>();
- if (getProjections.hasNoError() && !getProjections.getChildren().isEmpty()) {
- BasicCompositeCommand commands = new BasicCompositeCommand();
- for (Path.Segment child : getProjections.getChildren()) {
- final Path pathToSource = pathFactory.create(projectionsNode, child);
- commands.add(new BasicGetNodeCommand(pathToSource));
- }
- // Now execute these commands ...
- executor.execute(commands);
-
- // Iterate over each region node obtained ...
- for (GraphCommand command : commands) {
- BasicGetNodeCommand getProjectionCommand = (BasicGetNodeCommand)command;
- if (getProjectionCommand.hasNoError()) {
- Projection projection = createProjection(env,
- projectionParser,
- getProjectionCommand.getPath(),
- getProjectionCommand.getProperties(),
- problems);
- if (projection != null) sourceProjections.add(projection);
- }
- }
- }
-
- // Look for the default cache policy ...
- BasicCachePolicy cachePolicy = new BasicCachePolicy();
- Property timeToExpireProperty = getRepository.getProperties().get(nameFactory.create(CACHE_POLICY_TIME_TO_EXPIRE_CONFIG_PROPERTY_NAME));
- Property timeToCacheProperty = getRepository.getProperties().get(nameFactory.create(CACHE_POLICY_TIME_TO_CACHE_CONFIG_PROPERTY_NAME));
- 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, cacheProjection, sourceProjections, defaultCachePolicy);
- } catch (InvalidPathException err) {
- I18n msg = FederationI18n.federatedRepositoryCannotBeFound;
- throw new FederationException(msg.text(repositoryName));
- } catch (InterruptedException err) {
- I18n msg = FederationI18n.interruptedWhileUsingFederationConfigurationRepository;
- throw new FederationException(msg.text(repositoryName));
- }
-
- }
-
- /**
- * Instantiate the {@link Projection} described by the supplied properties.
- *
- * @param env the execution environment that should be used to read the configuration; may not be null
- * @param projectionParser the projection rule parser that should be used; may not be null
- * @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
- */
- protected Projection createProjection( ExecutionEnvironment env,
- ProjectionParser projectionParser,
- Path path,
- Map<Name, Property> properties,
- Problems problems ) {
- ValueFactories valueFactories = env.getValueFactories();
- NameFactory nameFactory = valueFactories.getNameFactory();
- ValueFactory<String> stringFactory = valueFactories.getStringFactory();
-
- String sourceName = path.getLastSegment().getName().getLocalName();
-
- // Get the rules ...
- Projection.Rule[] projectionRules = null;
- Property projectionRulesProperty = properties.get(nameFactory.create(PROJECTION_RULES_CONFIG_PROPERTY_NAME));
- if (projectionRulesProperty != null && !projectionRulesProperty.isEmpty()) {
- String[] projectionRuleStrs = stringFactory.create(projectionRulesProperty.getValuesAsArray());
- if (projectionRuleStrs != null && projectionRuleStrs.length != 0) {
- projectionRules = projectionParser.rulesFromStrings(env, projectionRuleStrs);
- }
- }
- if (problems.hasErrors()) return null;
-
- Projection region = new Projection(sourceName, projectionRules);
- return region;
- }
-
- /**
- * {@inheritDoc}
- */
public synchronized String getName() {
return sourceName;
}
@@ -476,7 +160,7 @@
* @see #setName(String)
*/
public synchronized void setName( String sourceName ) {
- if (this.sourceName == sourceName || this.sourceName != null && this.sourceName.equals(sourceName)) return;
+ if (this.sourceName == sourceName || this.sourceName != null && this.sourceName.equals(sourceName)) return; // unchanged
this.sourceName = sourceName;
changeRepositoryConfig();
}
@@ -513,7 +197,7 @@
* @see #setName(String)
*/
public void setRepositoryJndiName( String jndiName ) {
- if (this.repositoryJndiName == jndiName || this.repositoryJndiName != null && this.repositoryJndiName.equals(jndiName)) return;
+ if (this.repositoryJndiName == jndiName || this.repositoryJndiName != null && this.repositoryJndiName.equals(jndiName)) return; // unchanged
this.repositoryJndiName = jndiName;
changeRepositoryConfig();
}
@@ -554,7 +238,7 @@
*/
public void setConfigurationSourceName( String sourceName ) {
if (this.configurationSourceName == sourceName || this.configurationSourceName != null
- && this.configurationSourceName.equals(sourceName)) return;
+ && this.configurationSourceName.equals(sourceName)) return; // unchanged
this.configurationSourceName = sourceName;
changeRepositoryConfig();
}
@@ -640,7 +324,7 @@
*/
public synchronized void setExecutionContextFactoryJndiName( String jndiName ) {
if (this.repositoryJndiName == jndiName || this.repositoryJndiName != null && this.repositoryJndiName.equals(jndiName)) return;
- this.executionContextFactoryJndiName = jndiName;
+ this.executionContextFactoryJndiName = jndiName; // unchanged
changeRepositoryConfig();
}
@@ -681,12 +365,15 @@
*/
public synchronized void setConnectionFactoriesJndiName( String jndiName ) {
if (this.connectionFactoriesJndiName == jndiName || this.connectionFactoriesJndiName != null
- && this.connectionFactoriesJndiName.equals(jndiName)) return;
+ && this.connectionFactoriesJndiName.equals(jndiName)) return; // unchanged
this.connectionFactoriesJndiName = jndiName;
changeRepositoryConfig();
}
/**
+ * Get the name of the security domain that should be used by JAAS to identify the application or security context. This
+ * should correspond to the JAAS login configuration located within the JAAS login configuration file.
+ *
* @return securityDomain
*/
public String getSecurityDomain() {
@@ -694,10 +381,15 @@
}
/**
+ * Set the name of the security domain that should be used by JAAS to identify the application or security context. This
+ * should correspond to the JAAS login configuration located within the JAAS login configuration file.
+ *
* @param securityDomain Sets securityDomain to the specified value.
*/
public void setSecurityDomain( String securityDomain ) {
+ if (this.securityDomain != null && this.securityDomain.equals(securityDomain)) return; // unchanged
this.securityDomain = securityDomain;
+ changeRepositoryConfig();
}
/**
@@ -732,29 +424,12 @@
*/
public synchronized void setRepositoryName( String repositoryName ) {
ArgCheck.isNotEmpty(repositoryName, "repositoryName");
- if (this.repositoryName != null && this.repositoryName.equals(repositoryName)) return;
+ if (this.repositoryName != null && this.repositoryName.equals(repositoryName)) return; // unchanged
this.repositoryName = repositoryName;
changeRepositoryConfig();
}
/**
- * This method is called to signal that some aspect of the configuration has changed. If a {@link #getRepository() repository}
- * instance has been created, it's configuration is
- * {@link #getRepositoryConfiguration(ExecutionEnvironment, RepositoryConnectionFactories) rebuilt} and updated. Nothing is
- * done, however, if there is currently no {@link #getRepository() repository}.
- */
- protected synchronized void changeRepositoryConfig() {
- if (this.repository != null) {
- // Find in JNDI the repository connection factories and the environment ...
- ExecutionEnvironment env = getExecutionEnvironment();
- RepositoryConnectionFactories factories = getRepositoryConnectionFactories();
- // Compute a new repository config and set it on the repository ...
- FederatedRepositoryConfig newConfig = getRepositoryConfiguration(env, factories);
- this.repository.setConfiguration(newConfig);
- }
- }
-
- /**
* Get the username that should be used when authenticating and {@link #getConnection() creating connections}.
* <p>
* This is an optional property, required only when authentication is to be used.
@@ -785,7 +460,9 @@
* @see #setName(String)
*/
public void setUsername( String username ) {
+ if (this.username != null && this.username.equals(username)) return; // unchanged
this.username = username;
+ changeRepositoryConfig();
}
/**
@@ -818,12 +495,337 @@
* @see #setName(String)
*/
public void setPassword( String password ) {
+ if (this.password != null && this.password.equals(password)) return; // unchanged
this.password = password;
+ changeRepositoryConfig();
}
/**
+ * This method is called to signal that some aspect of the configuration has changed. If a {@link #getRepository() repository}
+ * instance has been created, it's configuration is
+ * {@link #getRepositoryConfiguration(ExecutionEnvironment, RepositoryConnectionFactories) rebuilt} and updated. Nothing is
+ * done, however, if there is currently no {@link #getRepository() repository}.
+ */
+ protected synchronized void changeRepositoryConfig() {
+ if (this.repository != null) {
+ // Find in JNDI the repository connection factories and the environment ...
+ ExecutionEnvironment env = getExecutionEnvironment();
+ RepositoryConnectionFactories factories = getRepositoryConnectionFactories();
+ // Compute a new repository config and set it on the repository ...
+ FederatedRepositoryConfig newConfig = getRepositoryConfiguration(env, factories);
+ this.repository.setConfiguration(newConfig);
+ }
+ }
+
+ /**
* {@inheritDoc}
+ *
+ * @see org.jboss.dna.spi.graph.connection.AbstractRepositorySource#createConnection()
*/
+ @Override
+ protected synchronized RepositoryConnection createConnection() throws RepositorySourceException {
+ if (getName() == null) {
+ throw new RepositorySourceException(FederationI18n.propertyIsRequired.text("name"));
+ }
+ if (getExecutionContextFactoryJndiName() == null) {
+ throw new RepositorySourceException(FederationI18n.propertyIsRequired.text("execution context factory JNDI name"));
+ }
+ if (getSecurityDomain() == null) {
+ throw new RepositorySourceException(FederationI18n.propertyIsRequired.text("security domain"));
+ }
+ if (getConnectionFactoriesJndiName() == null) {
+ throw new RepositorySourceException(FederationI18n.propertyIsRequired.text("connection factories JNDI name"));
+ }
+ // Find the repository ...
+ FederatedRepository repository = getRepository();
+ // Authenticate the user ...
+ String username = this.username;
+ Object credentials = this.password;
+ RepositoryConnection connection = repository.createConnection(this, username, credentials);
+ if (connection == null) {
+ I18n msg = FederationI18n.unableToAuthenticateConnectionToFederatedRepository;
+ throw new RepositorySourceException(msg.text(this.repositoryName, username));
+ }
+ // Return the new connection ...
+ return connection;
+ }
+
+ /**
+ * Get the {@link FederatedRepository} instance that this source is using. This method uses the following logic:
+ * <ol>
+ * <li>If a {@link FederatedRepository} already was obtained from a prior call, the same instance is returned.</li>
+ * <li>A {@link FederatedRepository} is created using a {@link FederatedRepositoryConfig} is created from this instance's
+ * properties and {@link ExecutionEnvironment} and {@link RepositoryConnectionFactories} instances obtained from JNDI.</li>
+ * <li></li>
+ * <li></li>
+ * </ol>
+ *
+ * @return the federated repository instance
+ * @throws RepositorySourceException
+ */
+ protected synchronized FederatedRepository getRepository() throws RepositorySourceException {
+ if (repository == null) {
+ String jndiName = this.getRepositoryJndiName();
+ Context context = getContext();
+ if (jndiName != null && jndiName.trim().length() != 0) {
+ // Look for an existing repository in JNDI ...
+ try {
+ if (context == null) context = new InitialContext();
+ repository = (FederatedRepository)context.lookup(jndiName);
+ } catch (Throwable err) {
+ I18n msg = FederationI18n.unableToFindFederatedRepositoryInJndi;
+ throw new RepositorySourceException(msg.text(this.sourceName, jndiName), err);
+ }
+ }
+
+ if (repository == null) {
+ // Find in JNDI the repository connection factories and the environment ...
+ ExecutionEnvironment env = getExecutionEnvironment();
+ RepositoryConnectionFactories factories = getRepositoryConnectionFactories();
+ // And create the configuration and the repository ...
+ FederatedRepositoryConfig config = getRepositoryConfiguration(env, factories);
+ repository = new FederatedRepository(env, factories, config);
+ }
+ }
+ return repository;
+ }
+
+ protected ExecutionEnvironment getExecutionEnvironment() {
+ ExecutionContextFactory factory = null;
+ Context context = getContext();
+ String jndiName = getExecutionContextFactoryJndiName();
+ if (jndiName != null && jndiName.trim().length() != 0) {
+ try {
+ if (context == null) context = new InitialContext();
+ factory = (ExecutionContextFactory)context.lookup(jndiName);
+ } catch (Throwable err) {
+ I18n msg = FederationI18n.unableToFindExecutionContextFactoryInJndi;
+ throw new RepositorySourceException(msg.text(this.sourceName, jndiName), err);
+ }
+ }
+ if (factory == null) {
+ I18n msg = FederationI18n.unableToFindExecutionContextFactoryInJndi;
+ throw new RepositorySourceException(msg.text(this.sourceName, jndiName));
+ }
+ String securityDomain = getSecurityDomain();
+ CallbackHandler handler = createCallbackHandler();
+ try {
+ return factory.create(securityDomain, handler);
+ } catch (LoginException e) {
+ I18n msg = FederationI18n.unableToCreateExecutionContext;
+ throw new RepositorySourceException(msg.text(this.sourceName, jndiName, securityDomain), e);
+ }
+ }
+
+ protected RepositoryConnectionFactories getRepositoryConnectionFactories() {
+ RepositoryConnectionFactories factories = null;
+ Context context = getContext();
+ String jndiName = getConnectionFactoriesJndiName();
+ if (jndiName != null && jndiName.trim().length() != 0) {
+ try {
+ if (context == null) context = new InitialContext();
+ factories = (RepositoryConnectionFactories)context.lookup(jndiName);
+ } catch (Throwable err) {
+ I18n msg = FederationI18n.unableToFindRepositoryConnectionFactoriesInJndi;
+ throw new RepositorySourceException(msg.text(this.sourceName, jndiName), err);
+ }
+ }
+ if (factories == null) {
+ I18n msg = FederationI18n.noRepositoryConnectionFactories;
+ throw new RepositorySourceException(msg.text(this.repositoryName));
+ }
+ return factories;
+ }
+
+ protected CallbackHandler createCallbackHandler() {
+ return new CallbackHandler() {
+ public void handle( Callback[] callbacks ) {
+ for (Callback callback : callbacks) {
+ if (callback instanceof NameCallback) {
+ NameCallback nameCallback = (NameCallback)callback;
+ nameCallback.setName(FederatedRepositorySource.this.getUsername());
+ }
+ if (callback instanceof PasswordCallback) {
+ PasswordCallback passwordCallback = (PasswordCallback)callback;
+ passwordCallback.setPassword(FederatedRepositorySource.this.getPassword().toCharArray());
+ }
+ }
+ }
+ };
+ }
+
+ protected Context getContext() {
+ return this.jndiContext;
+ }
+
+ protected synchronized void setContext( Context context ) {
+ this.jndiContext = context;
+ }
+
+ /**
+ * Create a {@link FederatedRepositoryConfig} instance from the current properties of this instance. This method does
+ * <i>not</i> modify the state of this instance.
+ *
+ * @param env the execution environment that should be used to read the configuration; may not be null
+ * @param factories the factories from which can be obtained the RepositoryConnectionFactory instances for each name source;
+ * may not be null
+ * @return a configuration reflecting the current state of this instance
+ */
+ protected synchronized FederatedRepositoryConfig getRepositoryConfiguration( ExecutionEnvironment env,
+ RepositoryConnectionFactories factories ) {
+ Problems problems = new SimpleProblems();
+ ValueFactories valueFactories = env.getValueFactories();
+ PathFactory pathFactory = valueFactories.getPathFactory();
+ NameFactory nameFactory = valueFactories.getNameFactory();
+ ValueFactory<Long> longFactory = valueFactories.getLongFactory();
+
+ // Create the configuration projection ...
+ ProjectionParser projectionParser = ProjectionParser.getInstance();
+ Projection.Rule[] rules = projectionParser.rulesFromStrings(env, this.getConfigurationSourceProjectionRules());
+ Projection configurationProjection = new Projection(this.getConfigurationSourceName(), rules);
+
+ // Create a federating command executor to execute the commands and merge the results into a single set of
+ // commands.
+ final String configurationSourceName = configurationProjection.getSourceName();
+ List<Projection> projections = Collections.singletonList(configurationProjection);
+ CommandExecutor executor = null;
+ if (configurationProjection.getRules().size() == 1) {
+ // There is just a single projection for the configuration repository, so just use an executor that
+ // translates the paths using the projection
+ executor = new SingleProjectionCommandExecutor(env, configurationSourceName, configurationProjection, factories);
+ } else if (configurationProjection.getRules().size() == 0) {
+ // There is no projection for the configuration repository, so just use a no-op executor
+ executor = new NoOpCommandExecutor(env, configurationSourceName);
+ } else {
+ // The configuration repository has more than one projection, so we need to merge the results
+ executor = new FederatingCommandExecutor(env, configurationSourceName, null, projections, factories);
+ }
+ // Wrap the executor with a logging executor ...
+ executor = new LoggingCommandExecutor(executor, Logger.getLogger(getClass()), Logger.Level.INFO);
+
+ // The configuration projection (via "executor") will convert this path into a path that exists in the configuration
+ // repository
+ Path configNode = pathFactory.create("/dna:system/dna:federation");
+
+ try {
+ // Get the repository node ...
+ BasicGetNodeCommand getRepository = new BasicGetNodeCommand(configNode);
+ executor.execute(getRepository);
+ if (getRepository.hasError()) {
+ throw new FederationException(FederationI18n.federatedRepositoryCannotBeFound.text(repositoryName));
+ }
+
+ // Add a command to get the projection defining the cache ...
+ Path pathToCacheRegion = pathFactory.create(configNode, nameFactory.create("dna:cache"));
+ BasicGetNodeCommand getCacheRegion = new BasicGetNodeCommand(pathToCacheRegion);
+ executor.execute(getCacheRegion);
+ Projection cacheProjection = createProjection(env,
+ projectionParser,
+ getCacheRegion.getPath(),
+ getCacheRegion.getProperties(),
+ problems);
+
+ if (getCacheRegion.hasError()) {
+ I18n msg = FederationI18n.requiredNodeDoesNotExistRelativeToNode;
+ throw new FederationException(msg.text("dna:cache", configNode));
+ }
+
+ // Get the source projections for the repository ...
+ Path projectionsNode = pathFactory.create(configNode, nameFactory.create("dna:projections"));
+ BasicGetChildrenCommand getProjections = new BasicGetChildrenCommand(projectionsNode);
+
+ executor.execute(getProjections);
+ if (getProjections.hasError()) {
+ I18n msg = FederationI18n.requiredNodeDoesNotExistRelativeToNode;
+ throw new FederationException(msg.text("dna:projections", configNode));
+ }
+
+ // Build the commands to get each of the projections (children of the "dna:projections" node) ...
+ List<Projection> sourceProjections = new LinkedList<Projection>();
+ if (getProjections.hasNoError() && !getProjections.getChildren().isEmpty()) {
+ BasicCompositeCommand commands = new BasicCompositeCommand();
+ for (Path.Segment child : getProjections.getChildren()) {
+ final Path pathToSource = pathFactory.create(projectionsNode, child);
+ commands.add(new BasicGetNodeCommand(pathToSource));
+ }
+ // Now execute these commands ...
+ executor.execute(commands);
+
+ // Iterate over each region node obtained ...
+ for (GraphCommand command : commands) {
+ BasicGetNodeCommand getProjectionCommand = (BasicGetNodeCommand)command;
+ if (getProjectionCommand.hasNoError()) {
+ Projection projection = createProjection(env,
+ projectionParser,
+ getProjectionCommand.getPath(),
+ getProjectionCommand.getProperties(),
+ problems);
+ if (projection != null) sourceProjections.add(projection);
+ }
+ }
+ }
+
+ // Look for the default cache policy ...
+ BasicCachePolicy cachePolicy = new BasicCachePolicy();
+ Property timeToExpireProperty = getRepository.getProperties().get(nameFactory.create(CACHE_POLICY_TIME_TO_EXPIRE_CONFIG_PROPERTY_NAME));
+ Property timeToCacheProperty = getRepository.getProperties().get(nameFactory.create(CACHE_POLICY_TIME_TO_CACHE_CONFIG_PROPERTY_NAME));
+ 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, cacheProjection, sourceProjections, defaultCachePolicy);
+ } catch (InvalidPathException err) {
+ I18n msg = FederationI18n.federatedRepositoryCannotBeFound;
+ throw new FederationException(msg.text(repositoryName));
+ } catch (InterruptedException err) {
+ I18n msg = FederationI18n.interruptedWhileUsingFederationConfigurationRepository;
+ throw new FederationException(msg.text(repositoryName));
+ }
+
+ }
+
+ /**
+ * Instantiate the {@link Projection} described by the supplied properties.
+ *
+ * @param env the execution environment that should be used to read the configuration; may not be null
+ * @param projectionParser the projection rule parser that should be used; may not be null
+ * @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
+ */
+ protected Projection createProjection( ExecutionEnvironment env,
+ ProjectionParser projectionParser,
+ Path path,
+ Map<Name, Property> properties,
+ Problems problems ) {
+ ValueFactories valueFactories = env.getValueFactories();
+ NameFactory nameFactory = valueFactories.getNameFactory();
+ ValueFactory<String> stringFactory = valueFactories.getStringFactory();
+
+ String sourceName = path.getLastSegment().getName().getLocalName();
+
+ // Get the rules ...
+ Projection.Rule[] projectionRules = null;
+ Property projectionRulesProperty = properties.get(nameFactory.create(PROJECTION_RULES_CONFIG_PROPERTY_NAME));
+ if (projectionRulesProperty != null && !projectionRulesProperty.isEmpty()) {
+ String[] projectionRuleStrs = stringFactory.create(projectionRulesProperty.getValuesAsArray());
+ if (projectionRuleStrs != null && projectionRuleStrs.length != 0) {
+ projectionRules = projectionParser.rulesFromStrings(env, projectionRuleStrs);
+ }
+ }
+ if (problems.hasErrors()) return null;
+
+ Projection region = new Projection(sourceName, projectionRules);
+ return region;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
public synchronized Reference getReference() {
String className = getClass().getName();
String factoryClassName = NamingContextObjectFactory.class.getName();
Modified: trunk/connectors/dna-connector-federation/src/test/java/org/jboss/dna/connector/federation/FederatedRepositorySourceTest.java
===================================================================
--- trunk/connectors/dna-connector-federation/src/test/java/org/jboss/dna/connector/federation/FederatedRepositorySourceTest.java 2008-07-24 19:52:13 UTC (rev 369)
+++ trunk/connectors/dna-connector-federation/src/test/java/org/jboss/dna/connector/federation/FederatedRepositorySourceTest.java 2008-07-25 19:37:40 UTC (rev 370)
@@ -24,7 +24,6 @@
import static org.hamcrest.core.Is.is;
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.mockito.Matchers.argThat;
import static org.mockito.Matchers.eq;
@@ -43,6 +42,7 @@
import org.jboss.dna.spi.ExecutionContextFactory;
import org.jboss.dna.spi.graph.connection.BasicExecutionEnvironment;
import org.jboss.dna.spi.graph.connection.ExecutionEnvironment;
+import org.jboss.dna.spi.graph.connection.RepositoryConnection;
import org.jboss.dna.spi.graph.connection.RepositoryConnectionFactories;
import org.jboss.dna.spi.graph.connection.RepositorySourceException;
import org.jboss.dna.spi.graph.connection.SimpleRepository;
@@ -72,7 +72,7 @@
private SimpleRepositorySource configRepositorySource;
private ExecutionEnvironment env;
@Mock
- private FederatedRepositoryConnection connection;
+ private RepositoryConnection connection;
@Mock
private Context jndiContext;
@Mock
@@ -143,8 +143,8 @@
@Test
public void shouldCreateConnectionsByAuthenticateUsingFederationRepository() throws Exception {
- connection = (FederatedRepositoryConnection)source.getConnection();
- assertThat(connection, is(sameInstance(connection)));
+ connection = source.getConnection();
+ assertThat(connection, is(notNullValue()));
}
@Test( expected = RepositorySourceException.class )
Modified: trunk/connectors/dna-connector-federation/src/test/java/org/jboss/dna/connector/federation/FederatedRepositoryTest.java
===================================================================
--- trunk/connectors/dna-connector-federation/src/test/java/org/jboss/dna/connector/federation/FederatedRepositoryTest.java 2008-07-24 19:52:13 UTC (rev 369)
+++ trunk/connectors/dna-connector-federation/src/test/java/org/jboss/dna/connector/federation/FederatedRepositoryTest.java 2008-07-25 19:37:40 UTC (rev 370)
@@ -52,7 +52,7 @@
@Mock
private RepositoryConnectionFactories connectionFactories;
- // private BasicRepositoryConnectionPool connectionPool;
+ // private RepositoryConnectionPool connectionPool;
@Before
public void beforeEach() {
Modified: trunk/connectors/dna-connector-inmemory/src/main/java/org/jboss/dna/connector/inmemory/InMemoryRepositorySource.java
===================================================================
--- trunk/connectors/dna-connector-inmemory/src/main/java/org/jboss/dna/connector/inmemory/InMemoryRepositorySource.java 2008-07-24 19:52:13 UTC (rev 369)
+++ trunk/connectors/dna-connector-inmemory/src/main/java/org/jboss/dna/connector/inmemory/InMemoryRepositorySource.java 2008-07-25 19:37:40 UTC (rev 370)
@@ -27,7 +27,6 @@
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
-import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
@@ -41,13 +40,14 @@
import net.jcip.annotations.GuardedBy;
import org.jboss.dna.common.util.ArgCheck;
import org.jboss.dna.spi.cache.CachePolicy;
+import org.jboss.dna.spi.graph.connection.AbstractRepositorySource;
import org.jboss.dna.spi.graph.connection.RepositoryConnection;
-import org.jboss.dna.spi.graph.connection.RepositorySource;
+import org.jboss.dna.spi.graph.connection.RepositorySourceException;
/**
* @author Randall Hauch
*/
-public class InMemoryRepositorySource implements RepositorySource, ObjectFactory {
+public class InMemoryRepositorySource extends AbstractRepositorySource implements ObjectFactory {
/**
* The initial version is 1
@@ -95,7 +95,6 @@
private String name;
@GuardedBy( "this" )
private String jndiName;
- private final AtomicInteger retryLimit = new AtomicInteger(0);
private UUID rootNodeUuid = UUID.randomUUID();
private CachePolicy defaultCachePolicy;
private String configurationName;
@@ -105,6 +104,7 @@
* Create a repository source instance.
*/
public InMemoryRepositorySource() {
+ super();
}
/**
@@ -225,22 +225,11 @@
/**
* {@inheritDoc}
+ *
+ * @see org.jboss.dna.spi.graph.connection.AbstractRepositorySource#createConnection()
*/
- public int getRetryLimit() {
- return retryLimit.get();
- }
-
- /**
- * {@inheritDoc}
- */
- public void setRetryLimit( int limit ) {
- retryLimit.set(limit);
- }
-
- /**
- * {@inheritDoc}
- */
- public synchronized RepositoryConnection getConnection() {
+ @Override
+ protected synchronized RepositoryConnection createConnection() throws RepositorySourceException {
if (this.repository == null) {
repository = new InMemoryRepository(configurationName, this.rootNodeUuid);
}
Modified: trunk/connectors/dna-connector-jbosscache/src/main/java/org/jboss/dna/connector/jbosscache/JBossCacheSource.java
===================================================================
--- trunk/connectors/dna-connector-jbosscache/src/main/java/org/jboss/dna/connector/jbosscache/JBossCacheSource.java 2008-07-24 19:52:13 UTC (rev 369)
+++ trunk/connectors/dna-connector-jbosscache/src/main/java/org/jboss/dna/connector/jbosscache/JBossCacheSource.java 2008-07-25 19:37:40 UTC (rev 370)
@@ -27,7 +27,6 @@
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
-import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
@@ -47,14 +46,14 @@
import org.jboss.dna.spi.cache.CachePolicy;
import org.jboss.dna.spi.graph.Name;
import org.jboss.dna.spi.graph.NameFactory;
+import org.jboss.dna.spi.graph.connection.AbstractRepositorySource;
import org.jboss.dna.spi.graph.connection.RepositoryConnection;
-import org.jboss.dna.spi.graph.connection.RepositorySource;
/**
* @author Randall Hauch
*/
@ThreadSafe
-public class JBossCacheSource implements RepositorySource, ObjectFactory {
+public class JBossCacheSource extends AbstractRepositorySource implements ObjectFactory {
/**
*/
@@ -100,7 +99,6 @@
private String name;
@GuardedBy( "this" )
private String jndiName;
- private final AtomicInteger retryLimit = new AtomicInteger(0);
private UUID rootNodeUuid = UUID.randomUUID();
private CachePolicy defaultCachePolicy;
private String cacheConfigurationName;
@@ -261,21 +259,8 @@
/**
* {@inheritDoc}
*/
- public int getRetryLimit() {
- return retryLimit.get();
- }
-
- /**
- * {@inheritDoc}
- */
- public void setRetryLimit( int limit ) {
- retryLimit.set(limit);
- }
-
- /**
- * {@inheritDoc}
- */
- public synchronized RepositoryConnection getConnection() {
+ @Override
+ protected synchronized RepositoryConnection createConnection() {
if (this.cache == null) {
CacheFactory<Name, Object> factory = new DefaultCacheFactory<Name, Object>();
cache = factory.createCache(cacheConfigurationName);
Modified: trunk/dna-repository/src/main/java/org/jboss/dna/repository/RepositorySourceManager.java
===================================================================
--- trunk/dna-repository/src/main/java/org/jboss/dna/repository/RepositorySourceManager.java 2008-07-24 19:52:13 UTC (rev 369)
+++ trunk/dna-repository/src/main/java/org/jboss/dna/repository/RepositorySourceManager.java 2008-07-25 19:37:40 UTC (rev 370)
@@ -32,7 +32,6 @@
import org.jboss.dna.spi.graph.connection.RepositoryConnection;
import org.jboss.dna.spi.graph.connection.RepositoryConnectionFactories;
import org.jboss.dna.spi.graph.connection.RepositoryConnectionFactory;
-import org.jboss.dna.spi.graph.connection.RepositoryConnectionPool;
import org.jboss.dna.spi.graph.connection.RepositorySource;
/**
@@ -139,10 +138,7 @@
try {
this.sourcesLock.readLock().lock();
for (RepositorySource source : this.sources) {
- if (source instanceof RepositoryConnectionPool) {
- RepositoryConnectionPool pool = (RepositoryConnectionPool)source;
- pool.shutdown();
- }
+ source.shutdown();
}
} finally {
this.sourcesLock.readLock().unlock();
@@ -164,12 +160,7 @@
try {
this.sourcesLock.readLock().lock();
for (RepositorySource source : this.sources) {
- if (source instanceof RepositoryConnectionPool) {
- RepositoryConnectionPool pool = (RepositoryConnectionPool)source;
- if (!pool.awaitTermination(timeout, unit)) {
- return false;
- }
- }
+ if (!source.awaitTermination(timeout, unit)) return false;
}
return true;
} finally {
@@ -191,12 +182,7 @@
try {
this.sourcesLock.readLock().lock();
for (RepositorySource source : this.sources) {
- if (source instanceof RepositoryConnectionPool) {
- RepositoryConnectionPool pool = (RepositoryConnectionPool)source;
- if (pool.isTerminating()) {
- return true;
- }
- }
+ if (source.isTerminating()) return true;
}
return false;
} finally {
@@ -214,12 +200,7 @@
try {
this.sourcesLock.readLock().lock();
for (RepositorySource source : this.sources) {
- if (source instanceof RepositoryConnectionPool) {
- RepositoryConnectionPool pool = (RepositoryConnectionPool)source;
- if (!pool.isTerminated()) {
- return false;
- }
- }
+ if (!source.isTerminated()) return false;
}
return true;
} finally {
@@ -309,12 +290,9 @@
this.sourcesLock.writeLock().lock();
for (RepositorySource existingSource : this.sources) {
if (existingSource.getName().equals(name)) {
- // 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);
- }
+ // Shut down the source ...
+ existingSource.shutdown();
+ if (timeToAwait > 0l) existingSource.awaitTermination(timeToAwait, unit);
}
return existingSource;
}
Added: trunk/dna-spi/src/main/java/org/jboss/dna/spi/graph/connection/AbstractRepositorySource.java
===================================================================
--- trunk/dna-spi/src/main/java/org/jboss/dna/spi/graph/connection/AbstractRepositorySource.java (rev 0)
+++ trunk/dna-spi/src/main/java/org/jboss/dna/spi/graph/connection/AbstractRepositorySource.java 2008-07-25 19:37:40 UTC (rev 370)
@@ -0,0 +1,203 @@
+/*
+ * 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;
+import java.util.concurrent.atomic.AtomicInteger;
+import net.jcip.annotations.ThreadSafe;
+
+/**
+ * An abstract implementation of {@link RepositorySource} that may serve as a foundation for most implementations, since it
+ * automatically manages the {@link RepositoryConnection connections} using an internal {@link ManagedRepositoryConnectionFactory pool}.
+ *
+ * @author Randall Hauch
+ */
+@ThreadSafe
+public abstract class AbstractRepositorySource implements RepositorySource {
+
+ /**
+ */
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * The default limit is {@value} for retrying {@link RepositoryConnection connection} calls to the underlying source.
+ */
+ public static final int DEFAULT_RETRY_LIMIT = 0;
+
+ private final AtomicInteger retryLimit = new AtomicInteger(DEFAULT_RETRY_LIMIT);
+ private final RepositoryConnectionPool connections;
+ private final RepositoryConnectionFactory connectionFactory;
+
+ /**
+ * Create a new instance of the repository source, relying upon the {@link #createConnection()} method to do the actual
+ * creation of the {@link RepositoryConnection connections}.
+ */
+ protected AbstractRepositorySource() {
+ this(null);
+ }
+
+ /**
+ * Create a new instance of the repository source, relying upon the supplied factory to do the actual creation of the
+ * {@link RepositoryConnection connections}. If the supplied factory is null, then this class will use the
+ * {@link #createConnection()} method to do the actual creation of the {@link RepositoryConnection connections}.
+ *
+ * @param factory the connection factory that creates the connections, or null if the {@link #createConnection()} method
+ * should be used to create connections
+ */
+ protected AbstractRepositorySource( RepositoryConnectionFactory factory ) {
+ this.connectionFactory = factory != null ? factory : new ConnectionFactory();
+ this.connections = new RepositoryConnectionPool(this.connectionFactory);
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.jboss.dna.spi.graph.connection.RepositorySource#getRetryLimit()
+ */
+ public int getRetryLimit() {
+ return retryLimit.get();
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.jboss.dna.spi.graph.connection.RepositorySource#setRetryLimit(int)
+ */
+ public void setRetryLimit( int limit ) {
+ retryLimit.set(limit < 0 ? 0 : limit);
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.jboss.dna.spi.graph.connection.ManagedRepositoryConnectionFactory#isRunning()
+ */
+ public boolean isRunning() {
+ return this.connections.isRunning();
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.jboss.dna.spi.graph.connection.ManagedRepositoryConnectionFactory#isShutdown()
+ */
+ public boolean isShutdown() {
+ return this.connections.isShutdown();
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.jboss.dna.spi.graph.connection.RepositoryConnectionFactory#getConnection()
+ */
+ public RepositoryConnection getConnection() throws RepositorySourceException, InterruptedException {
+ return this.connections.getConnection();
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.jboss.dna.spi.graph.connection.ManagedRepositoryConnectionFactory#shutdown()
+ */
+ public void shutdown() {
+ this.connections.shutdown();
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.jboss.dna.spi.graph.connection.ManagedRepositoryConnectionFactory#shutdownNow()
+ */
+ public void shutdownNow() {
+ this.connections.shutdownNow();
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.jboss.dna.spi.graph.connection.ManagedRepositoryConnectionFactory#isTerminated()
+ */
+ public boolean isTerminated() {
+ return this.connections.isTerminated();
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.jboss.dna.spi.graph.connection.ManagedRepositoryConnectionFactory#isTerminating()
+ */
+ public boolean isTerminating() {
+ return this.connections.isTerminating();
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.jboss.dna.spi.graph.connection.ManagedRepositoryConnectionFactory#awaitTermination(long, java.util.concurrent.TimeUnit)
+ */
+ public boolean awaitTermination( long timeout,
+ TimeUnit unit ) throws InterruptedException {
+ return this.connections.awaitTermination(timeout, unit);
+ }
+
+ /**
+ * Method to create a new {@link RepositoryConnection} instance. This method is called only when this instance was
+ * {@link #AbstractRepositorySource(RepositoryConnectionFactory) constructed} with a null {@link RepositoryConnectionFactory}
+ * reference. This makes it easy for subclasses to simply override this method can not be required to implement a separate
+ * connection factory.
+ *
+ * @return the new connection
+ * @throws RepositorySourceException
+ * @throws InterruptedException
+ */
+ protected RepositoryConnection createConnection() throws RepositorySourceException, InterruptedException {
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * Class that is used by the {@link AbstractRepositorySource} and it's pool to create connections as needed, by delegating to
+ * the {@link AbstractRepositorySource}'s {@link AbstractRepositorySource#createConnection()} method.
+ *
+ * @author Randall Hauch
+ */
+ protected class ConnectionFactory implements RepositoryConnectionFactory {
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.jboss.dna.spi.graph.connection.RepositoryConnectionFactory#getConnection()
+ */
+ public RepositoryConnection getConnection() throws RepositorySourceException, InterruptedException {
+ return AbstractRepositorySource.this.createConnection();
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.jboss.dna.spi.graph.connection.RepositoryConnectionFactory#getName()
+ */
+ public String getName() {
+ return AbstractRepositorySource.this.getName();
+ }
+
+ }
+}
Property changes on: trunk/dna-spi/src/main/java/org/jboss/dna/spi/graph/connection/AbstractRepositorySource.java
___________________________________________________________________
Name: svn:mime-type
+ text/plain
Deleted: trunk/dna-spi/src/main/java/org/jboss/dna/spi/graph/connection/BasicRepositoryConnectionPool.java
===================================================================
--- trunk/dna-spi/src/main/java/org/jboss/dna/spi/graph/connection/BasicRepositoryConnectionPool.java 2008-07-24 19:52:13 UTC (rev 369)
+++ trunk/dna-spi/src/main/java/org/jboss/dna/spi/graph/connection/BasicRepositoryConnectionPool.java 2008-07-25 19:37:40 UTC (rev 370)
@@ -1,967 +0,0 @@
-/*
- * 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.Collection;
-import java.util.HashSet;
-import java.util.LinkedList;
-import java.util.Set;
-import java.util.concurrent.BlockingQueue;
-import java.util.concurrent.LinkedBlockingQueue;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.atomic.AtomicBoolean;
-import java.util.concurrent.atomic.AtomicInteger;
-import java.util.concurrent.atomic.AtomicLong;
-import java.util.concurrent.locks.Condition;
-import java.util.concurrent.locks.ReentrantLock;
-import javax.transaction.xa.XAResource;
-import net.jcip.annotations.GuardedBy;
-import net.jcip.annotations.ThreadSafe;
-import org.jboss.dna.common.util.ArgCheck;
-import org.jboss.dna.common.util.Logger;
-import org.jboss.dna.spi.SpiI18n;
-import org.jboss.dna.spi.cache.CachePolicy;
-import org.jboss.dna.spi.graph.commands.GraphCommand;
-
-/**
- * @author Randall Hauch
- */
-@ThreadSafe
-public class BasicRepositoryConnectionPool implements RepositoryConnectionPool {
-
- /**
- * The core pool size for default-constructed pools is {@value} .
- */
- public static final int DEFAULT_CORE_POOL_SIZE = 1;
-
- /**
- * The maximum pool size for default-constructed pools is {@value} .
- */
- public static final int DEFAULT_MAXIMUM_POOL_SIZE = 10;
-
- /**
- * The keep-alive time for connections in default-constructed pools is {@value} seconds.
- */
- public static final long DEFAULT_KEEP_ALIVE_TIME_IN_SECONDS = 30;
-
- /**
- * Permission for checking shutdown
- */
- private static final RuntimePermission shutdownPerm = new RuntimePermission("modifyThread");
-
- /**
- * The factory that this pool uses to create new connections.
- */
- private final RepositoryConnectionFactory connectionFactory;
-
- /**
- * Lock held on updates to poolSize, corePoolSize, maximumPoolSize, and workers set.
- */
- private final ReentrantLock mainLock = new ReentrantLock();
-
- /**
- * Wait condition to support awaitTermination
- */
- private final Condition termination = mainLock.newCondition();
-
- /**
- * Set containing all connections that are available for use.
- */
- @GuardedBy( "mainLock" )
- private final BlockingQueue<ConnectionWrapper> availableConnections = new LinkedBlockingQueue<ConnectionWrapper>();
-
- /**
- * The connections that are currently in use.
- */
- @GuardedBy( "mainLock" )
- private final Set<ConnectionWrapper> inUseConnections = new HashSet<ConnectionWrapper>();
-
- /**
- * Timeout in nanoseconds for idle connections waiting to be used. Threads use this timeout only when there are more than
- * corePoolSize present. Otherwise they wait forever to be used.
- */
- private volatile long keepAliveTime;
-
- /**
- * The target pool size, updated only while holding mainLock, but volatile to allow concurrent readability even during
- * updates.
- */
- @GuardedBy( "mainLock" )
- private volatile int corePoolSize;
-
- /**
- * Maximum pool size, updated only while holding mainLock but volatile to allow concurrent readability even during updates.
- */
- @GuardedBy( "mainLock" )
- private volatile int maximumPoolSize;
-
- /**
- * Current pool size, updated only while holding mainLock but volatile to allow concurrent readability even during updates.
- */
- @GuardedBy( "mainLock" )
- private volatile int poolSize;
-
- /**
- * Lifecycle state, updated only while holding mainLock but volatile to allow concurrent readability even during updates.
- */
- @GuardedBy( "mainLock" )
- private volatile int runState;
-
- // Special values for runState
- /** Normal, not-shutdown mode */
- static final int RUNNING = 0;
- /** Controlled shutdown mode */
- static final int SHUTDOWN = 1;
- /** Immediate shutdown mode */
- static final int STOP = 2;
- /** Final state */
- static final int TERMINATED = 3;
-
- /**
- * Flag specifying whether a connection should be validated before returning it from the {@link #getConnection()} method.
- */
- private final AtomicBoolean validateConnectionBeforeUse = new AtomicBoolean(false);
-
- /**
- * The time in nanoseconds that ping should wait before timing out and failing.
- */
- private final AtomicLong pingTimeout = new AtomicLong(0);
-
- /**
- * The number of times an attempt to obtain a connection should fail with invalid connections before throwing an exception.
- */
- private final AtomicInteger maxFailedAttemptsBeforeError = new AtomicInteger(10);
-
- private final AtomicLong totalConnectionsCreated = new AtomicLong(0);
-
- private final AtomicLong totalConnectionsUsed = new AtomicLong(0);
-
- private final Logger logger = Logger.getLogger(this.getClass());
-
- /**
- * Create the pool to use the supplied connection factory, which is typically a {@link RepositorySource}. This constructor
- * uses the {@link #DEFAULT_CORE_POOL_SIZE default core pool size}, {@link #DEFAULT_MAXIMUM_POOL_SIZE default maximum pool
- * size}, and {@link #DEFAULT_KEEP_ALIVE_TIME_IN_SECONDS default keep-alive time (in seconds)}.
- *
- * @param connectionFactory the factory for connections
- * @throws IllegalArgumentException if the connection factory is null or any of the supplied arguments are invalid
- */
- public BasicRepositoryConnectionPool( RepositoryConnectionFactory connectionFactory ) {
- this(connectionFactory, DEFAULT_CORE_POOL_SIZE, DEFAULT_MAXIMUM_POOL_SIZE, DEFAULT_KEEP_ALIVE_TIME_IN_SECONDS,
- TimeUnit.SECONDS);
- }
-
- /**
- * Create the pool to use the supplied connection factory, which is typically a {@link RepositorySource}.
- *
- * @param connectionFactory the factory for connections
- * @param corePoolSize the number of connections to keep in the pool, even if they are idle.
- * @param maximumPoolSize the maximum number of connections to allow in the pool.
- * @param keepAliveTime when the number of connection is greater than the core, this is the maximum time that excess idle
- * connections will be kept before terminating.
- * @param unit the time unit for the keepAliveTime argument.
- * @throws IllegalArgumentException if the connection factory is null or any of the supplied arguments are invalid
- */
- public BasicRepositoryConnectionPool( RepositoryConnectionFactory connectionFactory,
- int corePoolSize,
- int maximumPoolSize,
- long keepAliveTime,
- TimeUnit unit ) {
- ArgCheck.isNonNegative(corePoolSize, "corePoolSize");
- ArgCheck.isPositive(maximumPoolSize, "maximumPoolSize");
- ArgCheck.isNonNegative(keepAliveTime, "keepAliveTime");
- ArgCheck.isNotNull(connectionFactory, "repository connection factory");
- if (maximumPoolSize < corePoolSize) {
- throw new IllegalArgumentException(SpiI18n.maximumPoolSizeMayNotBeSmallerThanCorePoolSize.text());
- }
- this.connectionFactory = connectionFactory;
- this.corePoolSize = corePoolSize;
- this.maximumPoolSize = maximumPoolSize;
- this.keepAliveTime = unit.toNanos(keepAliveTime);
- this.setPingTimeout(100, TimeUnit.MILLISECONDS);
- }
-
- /**
- * {@inheritDoc}
- *
- * @see org.jboss.dna.spi.graph.connection.RepositoryConnectionFactory#getName()
- */
- public String getName() {
- return this.connectionFactory.getName();
- }
-
- // -------------------------------------------------
- // Property settings ...
- // -------------------------------------------------
-
- /**
- * @return validateConnectionBeforeUse
- */
- public boolean getValidateConnectionBeforeUse() {
- return this.validateConnectionBeforeUse.get();
- }
-
- /**
- * @param validateConnectionBeforeUse Sets validateConnectionBeforeUse to the specified value.
- */
- public void setValidateConnectionBeforeUse( boolean validateConnectionBeforeUse ) {
- this.validateConnectionBeforeUse.set(validateConnectionBeforeUse);
- }
-
- /**
- * @return pingTimeout
- */
- public long getPingTimeoutInNanos() {
- return this.pingTimeout.get();
- }
-
- /**
- * @param pingTimeout the time to wait for a ping to complete
- * @param unit the time unit of the time argument
- */
- public void setPingTimeout( long pingTimeout,
- TimeUnit unit ) {
- ArgCheck.isNonNegative(pingTimeout, "time");
- this.pingTimeout.set(unit.toNanos(pingTimeout));
- }
-
- /**
- * @return maxFailedAttemptsBeforeError
- */
- public int getMaxFailedAttemptsBeforeError() {
- return this.maxFailedAttemptsBeforeError.get();
- }
-
- /**
- * @param maxFailedAttemptsBeforeError Sets maxFailedAttemptsBeforeError to the specified value.
- */
- public void setMaxFailedAttemptsBeforeError( int maxFailedAttemptsBeforeError ) {
- this.maxFailedAttemptsBeforeError.set(maxFailedAttemptsBeforeError);
- }
-
- /**
- * Sets the time limit for which connections may remain idle before being closed. If there are more than the core number of
- * connections currently in the pool, after waiting this amount of time without being used, excess threads will be terminated.
- * This overrides any value set in the constructor.
- *
- * @param time the time to wait. A time value of zero will cause excess connections to terminate immediately after being
- * returned.
- * @param unit the time unit of the time argument
- * @throws IllegalArgumentException if time less than zero
- * @see #getKeepAliveTime
- */
- public void setKeepAliveTime( long time,
- TimeUnit unit ) {
- ArgCheck.isNonNegative(time, "time");
- this.keepAliveTime = unit.toNanos(time);
- }
-
- /**
- * Returns the connection keep-alive time, which is the amount of time which connections in excess of the core pool size may
- * remain idle before being closed.
- *
- * @param unit the desired time unit of the result
- * @return the time limit
- * @see #setKeepAliveTime
- */
- public long getKeepAliveTime( TimeUnit unit ) {
- assert unit != null;
- return unit.convert(keepAliveTime, TimeUnit.NANOSECONDS);
- }
-
- /**
- * @return maximumPoolSize
- */
- public int getMaximumPoolSize() {
- return this.maximumPoolSize;
- }
-
- /**
- * Sets the maximum allowed number of connections. This overrides any value set in the constructor. If the new value is
- * smaller than the current value, excess existing but unused connections will be closed.
- *
- * @param maximumPoolSize the new maximum
- * @throws IllegalArgumentException if maximumPoolSize less than zero or the {@link #getCorePoolSize() core pool size}
- * @see #getMaximumPoolSize
- */
- public void setMaximumPoolSize( int maximumPoolSize ) {
- ArgCheck.isPositive(maximumPoolSize, "maximum pool size");
- if (maximumPoolSize < corePoolSize) {
- throw new IllegalArgumentException(SpiI18n.maximumPoolSizeMayNotBeSmallerThanCorePoolSize.text());
- }
- final ReentrantLock mainLock = this.mainLock;
- try {
- mainLock.lock();
- int extra = this.maximumPoolSize - maximumPoolSize;
- this.maximumPoolSize = maximumPoolSize;
- if (extra > 0 && poolSize > maximumPoolSize) {
- // Drain the extra connections from those available ...
- drainUnusedConnections(extra);
- }
- } finally {
- mainLock.unlock();
- }
- }
-
- /**
- * Returns the core number of connections.
- *
- * @return the core number of connections
- * @see #setCorePoolSize(int)
- */
- public int getCorePoolSize() {
- return this.corePoolSize;
- }
-
- /**
- * Sets the core number of connections. This overrides any value set in the constructor. If the new value is smaller than the
- * current value, excess existing and unused connections will be closed. If larger, new connections will, if needed, be
- * created.
- *
- * @param corePoolSize the new core size
- * @throws RepositorySourceException if there was an error obtaining the new connection
- * @throws InterruptedException if the thread was interrupted during the operation
- * @throws IllegalArgumentException if <tt>corePoolSize</tt> less than zero
- * @see #getCorePoolSize()
- */
- public void setCorePoolSize( int corePoolSize ) throws RepositorySourceException, InterruptedException {
- ArgCheck.isNonNegative(corePoolSize, "core pool size");
- if (maximumPoolSize < corePoolSize) {
- throw new IllegalArgumentException(SpiI18n.maximumPoolSizeMayNotBeSmallerThanCorePoolSize.text());
- }
- final ReentrantLock mainLock = this.mainLock;
- try {
- mainLock.lock();
- int extra = this.corePoolSize - corePoolSize;
- this.corePoolSize = corePoolSize;
- if (extra < 0) {
- // Add connections ...
- addConnectionsIfUnderCorePoolSize();
- } else if (extra > 0 && poolSize > corePoolSize) {
- // Drain the extra connections from those available ...
- drainUnusedConnections(extra);
- }
- } finally {
- mainLock.unlock();
- }
- }
-
- // -------------------------------------------------
- // Statistics ...
- // -------------------------------------------------
-
- /**
- * Returns the current number of connections in the pool, including those that are checked out (in use) and those that are not
- * being used.
- *
- * @return the number of connections
- */
- public int getPoolSize() {
- return poolSize;
- }
-
- /**
- * Returns the approximate number of connections that are currently checked out from the pool.
- *
- * @return the number of checked-out connections
- */
- public int getInUseCount() {
- final ReentrantLock mainLock = this.mainLock;
- try {
- mainLock.lock();
- return this.inUseConnections.size();
- } finally {
- mainLock.unlock();
- }
- }
-
- /**
- * Get the total number of connections that have been created by this pool.
- *
- * @return the total number of connections created by this pool
- */
- public long getTotalConnectionsCreated() {
- return this.totalConnectionsCreated.get();
- }
-
- /**
- * Get the total number of times connections have been {@link #getConnection()} used.
- *
- * @return the total number
- */
- public long getTotalConnectionsUsed() {
- return this.totalConnectionsUsed.get();
- }
-
- // -------------------------------------------------
- // State management methods ...
- // -------------------------------------------------
-
- /**
- * Starts a core connection, causing it to idly wait for use. This overrides the default policy of starting core connections
- * only when they are {@link #getConnection() needed}. This method will return <tt>false</tt> if all core connections have
- * already been started.
- *
- * @return true if a connection was started
- * @throws RepositorySourceException if there was an error obtaining the new connection
- * @throws InterruptedException if the thread was interrupted during the operation
- */
- public boolean prestartCoreConnection() throws RepositorySourceException, InterruptedException {
- final ReentrantLock mainLock = this.mainLock;
- try {
- mainLock.lock();
- return addConnectionIfUnderCorePoolSize();
- } finally {
- mainLock.unlock();
- }
- }
-
- /**
- * Starts all core connections, causing them to idly wait for use. This overrides the default policy of starting core
- * connections only when they are {@link #getConnection() needed}.
- *
- * @return the number of connections started.
- * @throws RepositorySourceException if there was an error obtaining the new connection
- * @throws InterruptedException if the thread was interrupted during the operation
- */
- public int prestartAllCoreConnections() throws RepositorySourceException, InterruptedException {
- final ReentrantLock mainLock = this.mainLock;
- try {
- mainLock.lock();
- return addConnectionsIfUnderCorePoolSize();
- } finally {
- mainLock.unlock();
- }
- }
-
- /**
- * {@inheritDoc}
- *
- * @see org.jboss.dna.spi.graph.connection.RepositoryConnectionPool#shutdown()
- */
- public void shutdown() {
- // Fail if caller doesn't have modifyThread permission. We
- // explicitly check permissions directly because we can't trust
- // implementations of SecurityManager to correctly override
- // the "check access" methods such that our documented
- // security policy is implemented.
- SecurityManager security = System.getSecurityManager();
- if (security != null) java.security.AccessController.checkPermission(shutdownPerm);
-
- this.logger.debug("Shutting down repository connection pool for {0}", getName());
- boolean fullyTerminated = false;
- final ReentrantLock mainLock = this.mainLock;
- try {
- mainLock.lock();
- int state = this.runState;
- if (state == RUNNING) {
- // don't override shutdownNow
- this.runState = SHUTDOWN;
- }
-
- // Kill the maintenance thread ...
-
- // Remove and close all available connections ...
- if (!this.availableConnections.isEmpty()) {
- // Drain the extra connections from those available ...
- drainUnusedConnections(this.availableConnections.size());
- }
-
- // If there are no connections being used, trigger full termination now ...
- if (this.inUseConnections.isEmpty()) {
- fullyTerminated = true;
- this.logger.trace("Signalling termination of repository connection pool for {0}", getName());
- runState = TERMINATED;
- termination.signalAll();
- this.logger.debug("Terminated repository connection pool for {0}", getName());
- }
- // Otherwise the last connection that is closed will transition the runState to TERMINATED ...
- } finally {
- mainLock.unlock();
- }
- if (fullyTerminated) terminated();
- }
-
- /**
- * {@inheritDoc}
- *
- * @see org.jboss.dna.spi.graph.connection.RepositoryConnectionPool#shutdownNow()
- */
- public void shutdownNow() {
- // Almost the same code as shutdown()
- SecurityManager security = System.getSecurityManager();
- if (security != null) java.security.AccessController.checkPermission(shutdownPerm);
-
- this.logger.debug("Shutting down (immediately) repository connection pool for {0}", getName());
- boolean fullyTerminated = false;
- final ReentrantLock mainLock = this.mainLock;
- try {
- mainLock.lock();
- int state = this.runState;
- if (state != TERMINATED) {
- // don't override shutdownNow
- this.runState = STOP;
- }
-
- // Kill the maintenance thread ...
-
- // Remove and close all available connections ...
- if (!this.availableConnections.isEmpty()) {
- // Drain the extra connections from those available ...
- drainUnusedConnections(this.availableConnections.size());
- }
-
- // If there are connections being used, close them now ...
- if (!this.inUseConnections.isEmpty()) {
- for (ConnectionWrapper connectionInUse : this.inUseConnections) {
- try {
- this.logger.trace("Closing repository connection to {0}", getName());
- connectionInUse.getOriginal().close();
- } catch (InterruptedException e) {
- // Ignore this ...
- }
- }
- this.poolSize -= this.inUseConnections.size();
- // The last connection that is closed will transition the runState to TERMINATED ...
- } else {
- // There are no connections in use, so trigger full termination now ...
- fullyTerminated = true;
- this.logger.trace("Signalling termination of repository connection pool for {0}", getName());
- runState = TERMINATED;
- termination.signalAll();
- this.logger.debug("Terminated repository connection pool for {0}", getName());
- }
-
- } finally {
- mainLock.unlock();
- }
- if (fullyTerminated) terminated();
- }
-
- /**
- * {@inheritDoc}
- *
- * @see org.jboss.dna.spi.graph.connection.RepositoryConnectionPool#isRunning()
- */
- public boolean isRunning() {
- return runState == RUNNING;
- }
-
- /**
- * {@inheritDoc}
- *
- * @see org.jboss.dna.spi.graph.connection.RepositoryConnectionPool#isShutdown()
- */
- public boolean isShutdown() {
- return runState != RUNNING;
- }
-
- /**
- * {@inheritDoc}
- *
- * @see org.jboss.dna.spi.graph.connection.RepositoryConnectionPool#isTerminating()
- */
- public boolean isTerminating() {
- return runState == STOP;
- }
-
- /**
- * {@inheritDoc}
- *
- * @see org.jboss.dna.spi.graph.connection.RepositoryConnectionPool#isTerminated()
- */
- public boolean isTerminated() {
- return runState == TERMINATED;
- }
-
- /**
- * {@inheritDoc}
- *
- * @see org.jboss.dna.spi.graph.connection.RepositoryConnectionPool#awaitTermination(long, java.util.concurrent.TimeUnit)
- */
- public boolean awaitTermination( long timeout,
- TimeUnit unit ) throws InterruptedException {
- long nanos = unit.toNanos(timeout);
- final ReentrantLock mainLock = this.mainLock;
- try {
- mainLock.lock();
- for (;;) {
- // this.logger.debug("---> Run state = {}; condition = {}", runState, termination);
- if (runState == TERMINATED) return true;
- if (nanos <= 0) return false;
- nanos = termination.awaitNanos(nanos);
- // this.logger.debug("---> Done waiting: run state = {}; condition = {}", runState, termination);
- }
- } finally {
- mainLock.unlock();
- }
- }
-
- /**
- * Method invoked when the pool has terminated. Default implementation does nothing. Note: To properly nest multiple
- * overridings, subclasses should generally invoke <tt>super.terminated</tt> within this method.
- */
- protected void terminated() {
- }
-
- /**
- * Invokes <tt>shutdown</tt> when this pool is no longer referenced.
- */
- @Override
- protected void finalize() {
- shutdown();
- }
-
- // -------------------------------------------------
- // Connection management methods ...
- // -------------------------------------------------
-
- /**
- * {@inheritDoc}
- */
- public RepositoryConnection getConnection() throws RepositorySourceException, InterruptedException {
- int attemptsAllowed = this.maxFailedAttemptsBeforeError.get();
- ConnectionWrapper connection = null;
- // Do this until we get a good connection ...
- int attemptsRemaining = attemptsAllowed;
- while (connection == null && attemptsRemaining > 0) {
- --attemptsRemaining;
- ReentrantLock mainLock = this.mainLock;
- try {
- mainLock.lock();
- // If we're shutting down the pool, then just close the connection ...
- if (this.runState != RUNNING) {
- throw new IllegalStateException(SpiI18n.repositoryConnectionPoolIsNotRunning.text());
- }
- // If there are fewer total connections than the core size ...
- if (this.poolSize < this.corePoolSize) {
- // Immediately create a wrapped connection and return it ...
- connection = newWrappedConnection();
- }
- // Peek to see if there is a connection available ...
- else if (this.availableConnections.peek() != null) {
- // There is, so take it and return it ...
- connection = this.availableConnections.take();
- }
- // There is no connection available. If there are fewer total connections than the maximum size ...
- else if (this.poolSize < this.maximumPoolSize) {
- // Immediately create a wrapped connection and return it ...
- connection = newWrappedConnection();
- }
- if (connection != null) {
- this.inUseConnections.add(connection);
- }
- } finally {
- mainLock.unlock();
- }
- if (connection == null) {
- // There are not enough connections, so wait in line for the next available connection ...
- this.logger.trace("Waiting for a repository connection from pool {0}", getName());
- connection = this.availableConnections.take();
- mainLock = this.mainLock;
- mainLock.lock();
- try {
- if (connection != null) {
- this.inUseConnections.add(connection);
- }
- } finally {
- mainLock.unlock();
- }
- this.logger.trace("Recieved a repository connection from pool {0}", getName());
- }
- if (connection != null && this.validateConnectionBeforeUse.get()) {
- connection = validateConnection(connection);
- }
- }
- if (connection == null) {
- // We were unable to obtain a usable connection, so fail ...
- throw new RepositorySourceException(SpiI18n.unableToObtainValidRepositoryAfterAttempts.text(attemptsAllowed));
- }
- this.totalConnectionsUsed.incrementAndGet();
- return connection;
- }
-
- /**
- * This method is automatically called by the {@link ConnectionWrapper} when it is {@link ConnectionWrapper#close() closed}.
- *
- * @param wrapper the wrapper to the connection that is being returned to the pool
- */
- protected void returnConnection( ConnectionWrapper wrapper ) {
- assert wrapper != null;
- ConnectionWrapper wrapperToClose = null;
- final ReentrantLock mainLock = this.mainLock;
- try {
- mainLock.lock();
- // Remove the connection from the in-use set ...
- boolean removed = this.inUseConnections.remove(wrapper);
- assert removed;
-
- // If we're shutting down the pool, then just close the connection ...
- if (this.runState != RUNNING) {
- wrapperToClose = wrapper;
- }
- // If there are more connections than the maximum size...
- else if (this.poolSize > this.maximumPoolSize) {
- // Immediately close this connection ...
- wrapperToClose = wrapper;
- }
- // Attempt to make the connection available (this should generally work, unless there is an upper limit
- // to the number of available connections) ...
- else if (!this.availableConnections.offer(new ConnectionWrapper(wrapper.getOriginal()))) {
- // The pool of available connection is full, so release it ...
- wrapperToClose = wrapper;
- }
- } finally {
- mainLock.unlock();
- }
- // Close the connection if we're supposed to (do it outside of the main lock)...
- if (wrapperToClose != null) {
- try {
- closeConnection(wrapper);
- } catch (InterruptedException e) {
- // catch this, as there's not much we can do and the caller doesn't care or know how to handle it
- this.logger.trace(e, "Interrupted while closing a repository connection");
- }
- }
- }
-
- /**
- * Validate the supplied connection, returning the connection if valid or null if the connection is not valid.
- *
- * @param connection the connection to be validated; may not be null
- * @return the validated connection, or null if the connection did not validate and was removed from the pool
- */
- protected ConnectionWrapper validateConnection( ConnectionWrapper connection ) {
- assert connection != null;
- ConnectionWrapper invalidConnection = null;
- try {
- if (!connection.ping(this.pingTimeout.get(), TimeUnit.NANOSECONDS)) {
- invalidConnection = connection;
- }
- } catch (InterruptedException e) {
- // catch this, as there's not much we can do and the caller doesn't care or know how to handle it
- this.logger.trace(e, "Interrupted while pinging a repository connection");
- invalidConnection = connection;
- } finally {
- if (invalidConnection != null) {
- connection = null;
- returnConnection(invalidConnection);
- }
- }
- return connection;
- }
-
- /**
- * Obtain a new connection wrapped in a {@link ConnectionWrapper}. This method does not check whether creating the new
- * connection would violate the {@link #maximumPoolSize maximum pool size} nor does it add the new connection to the
- * {@link #availableConnections available connections} (as the caller may want it immediately), but it does increment the
- * {@link #poolSize pool size}.
- *
- * @return the connection wrapper with a new connection
- * @throws RepositorySourceException if there was an error obtaining the new connection
- * @throws InterruptedException if the thread was interrupted during the operation
- */
- @GuardedBy( "mainLock" )
- protected ConnectionWrapper newWrappedConnection() throws RepositorySourceException, InterruptedException {
- RepositoryConnection connection = this.connectionFactory.getConnection();
- ++this.poolSize;
- this.totalConnectionsCreated.incrementAndGet();
- return new ConnectionWrapper(connection);
- }
-
- /**
- * Close a connection that is in the pool but no longer in the {@link #availableConnections available connections}. This
- * method does decrement the {@link #poolSize pool size}.
- *
- * @param wrapper the wrapper for the connection to be closed
- * @throws InterruptedException if the thread was interrupted during the operation
- */
- protected void closeConnection( ConnectionWrapper wrapper ) throws InterruptedException {
- assert wrapper != null;
- RepositoryConnection original = wrapper.getOriginal();
- assert original != null;
- try {
- this.logger.debug("Closing repository connection to {0}", getName());
- original.close();
- } finally {
- final ReentrantLock mainLock = this.mainLock;
- try {
- mainLock.lock();
- // No matter what reduce the pool size count
- --this.poolSize;
- // And if shutting down and this was the last connection being used...
- if (this.runState == SHUTDOWN && this.poolSize <= 0) {
- // then signal anybody that has called "awaitTermination(...)"
- this.logger.trace("Signalling termination of repository connection pool for {0}", getName());
- this.runState = TERMINATED;
- this.termination.signalAll();
- this.logger.trace("Terminated repository connection pool for {0}", getName());
-
- // fall through to call terminate() outside of lock.
- }
- } finally {
- mainLock.unlock();
- }
- }
- }
-
- @GuardedBy( "mainLock" )
- protected int drainUnusedConnections( int count ) {
- if (count <= 0) return 0;
- this.logger.trace("Draining up to {0} unused repository connections to {1}", count, getName());
- // Drain the extra connections from those available ...
- Collection<ConnectionWrapper> extraConnections = new LinkedList<ConnectionWrapper>();
- this.availableConnections.drainTo(extraConnections, count);
- for (ConnectionWrapper connection : extraConnections) {
- try {
- this.logger.trace("Closing repository connection to {0}", getName());
- connection.getOriginal().close();
- } catch (InterruptedException e) {
- // Ignore this ...
- }
- }
- int numClosed = extraConnections.size();
- this.poolSize -= numClosed;
- this.logger.trace("Drained {0} unused connections", numClosed);
- return numClosed;
- }
-
- @GuardedBy( "mainLock" )
- protected boolean addConnectionIfUnderCorePoolSize() throws RepositorySourceException, InterruptedException {
- // Add connection ...
- if (this.poolSize < this.corePoolSize) {
- this.availableConnections.offer(newWrappedConnection());
- this.logger.trace("Added connection to {0} in undersized pool", getName());
- return true;
- }
- return false;
- }
-
- @GuardedBy( "mainLock" )
- protected int addConnectionsIfUnderCorePoolSize() throws RepositorySourceException, InterruptedException {
- // Add connections ...
- int n = 0;
- while (this.poolSize < this.corePoolSize) {
- this.availableConnections.offer(newWrappedConnection());
- ++n;
- }
- this.logger.trace("Added {0} connection(s) to {1} in undersized pool", n, getName());
- return n;
- }
-
- protected class ConnectionWrapper implements RepositoryConnection {
-
- private final RepositoryConnection original;
- private final long timeCreated;
- private long lastUsed;
- private boolean closed = false;
-
- protected ConnectionWrapper( RepositoryConnection connection ) {
- assert connection != null;
- this.original = connection;
- this.timeCreated = System.currentTimeMillis();
- }
-
- /**
- * @return original
- */
- protected RepositoryConnection getOriginal() {
- return this.original;
- }
-
- /**
- * @return lastUsed
- */
- public long getTimeLastUsed() {
- return this.lastUsed;
- }
-
- /**
- * @return timeCreated
- */
- public long getTimeCreated() {
- return this.timeCreated;
- }
-
- /**
- * {@inheritDoc}
- */
- public String getSourceName() {
- return this.original.getSourceName();
- }
-
- /**
- * {@inheritDoc}
- */
- public XAResource getXAResource() {
- if (closed) throw new IllegalStateException(SpiI18n.closedConnectionMayNotBeUsed.text());
- return this.original.getXAResource();
- }
-
- /**
- * {@inheritDoc}
- */
- public CachePolicy getDefaultCachePolicy() {
- if (closed) throw new IllegalStateException(SpiI18n.closedConnectionMayNotBeUsed.text());
- return this.original.getDefaultCachePolicy();
- }
-
- /**
- * {@inheritDoc}
- */
- public void execute( ExecutionEnvironment env,
- GraphCommand... commands ) throws RepositorySourceException, InterruptedException {
- if (closed) throw new IllegalStateException(SpiI18n.closedConnectionMayNotBeUsed.text());
- this.original.execute(env, commands);
- }
-
- /**
- * {@inheritDoc}
- */
- public boolean ping( long time,
- TimeUnit unit ) throws InterruptedException {
- if (closed) throw new IllegalStateException(SpiI18n.closedConnectionMayNotBeUsed.text());
- return this.original.ping(time, unit);
- }
-
- /**
- * {@inheritDoc}
- */
- public void close() throws InterruptedException {
- if (!closed) {
- this.lastUsed = System.currentTimeMillis();
- this.original.close();
- this.closed = true;
- returnConnection(this);
- }
- }
-
- /**
- * {@inheritDoc}
- */
- public void setListener( RepositorySourceListener listener ) {
- if (!closed) this.original.setListener(listener);
- }
-
- }
-
-}
Copied: trunk/dna-spi/src/main/java/org/jboss/dna/spi/graph/connection/ManagedRepositoryConnectionFactory.java (from rev 369, 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/ManagedRepositoryConnectionFactory.java (rev 0)
+++ trunk/dna-spi/src/main/java/org/jboss/dna/spi/graph/connection/ManagedRepositoryConnectionFactory.java 2008-07-25 19:37:40 UTC (rev 370)
@@ -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 ManagedRepositoryConnectionFactory 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;
+
+}
Deleted: 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 2008-07-24 19:52:13 UTC (rev 369)
+++ trunk/dna-spi/src/main/java/org/jboss/dna/spi/graph/connection/RepositoryConnectionPool.java 2008-07-25 19:37:40 UTC (rev 370)
@@ -1,111 +0,0 @@
-/*
- * 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;
-
-}
Copied: trunk/dna-spi/src/main/java/org/jboss/dna/spi/graph/connection/RepositoryConnectionPool.java (from rev 368, trunk/dna-spi/src/main/java/org/jboss/dna/spi/graph/connection/BasicRepositoryConnectionPool.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-07-25 19:37:40 UTC (rev 370)
@@ -0,0 +1,967 @@
+/*
+ * 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.Collection;
+import java.util.HashSet;
+import java.util.LinkedList;
+import java.util.Set;
+import java.util.concurrent.BlockingQueue;
+import java.util.concurrent.LinkedBlockingQueue;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.concurrent.atomic.AtomicLong;
+import java.util.concurrent.locks.Condition;
+import java.util.concurrent.locks.ReentrantLock;
+import javax.transaction.xa.XAResource;
+import net.jcip.annotations.GuardedBy;
+import net.jcip.annotations.ThreadSafe;
+import org.jboss.dna.common.util.ArgCheck;
+import org.jboss.dna.common.util.Logger;
+import org.jboss.dna.spi.SpiI18n;
+import org.jboss.dna.spi.cache.CachePolicy;
+import org.jboss.dna.spi.graph.commands.GraphCommand;
+
+/**
+ * @author Randall Hauch
+ */
+@ThreadSafe
+public class RepositoryConnectionPool implements ManagedRepositoryConnectionFactory {
+
+ /**
+ * The core pool size for default-constructed pools is {@value} .
+ */
+ public static final int DEFAULT_CORE_POOL_SIZE = 1;
+
+ /**
+ * The maximum pool size for default-constructed pools is {@value} .
+ */
+ public static final int DEFAULT_MAXIMUM_POOL_SIZE = 10;
+
+ /**
+ * The keep-alive time for connections in default-constructed pools is {@value} seconds.
+ */
+ public static final long DEFAULT_KEEP_ALIVE_TIME_IN_SECONDS = 30;
+
+ /**
+ * Permission for checking shutdown
+ */
+ private static final RuntimePermission shutdownPerm = new RuntimePermission("modifyThread");
+
+ /**
+ * The factory that this pool uses to create new connections.
+ */
+ private final RepositoryConnectionFactory connectionFactory;
+
+ /**
+ * Lock held on updates to poolSize, corePoolSize, maximumPoolSize, and workers set.
+ */
+ private final ReentrantLock mainLock = new ReentrantLock();
+
+ /**
+ * Wait condition to support awaitTermination
+ */
+ private final Condition termination = mainLock.newCondition();
+
+ /**
+ * Set containing all connections that are available for use.
+ */
+ @GuardedBy( "mainLock" )
+ private final BlockingQueue<ConnectionWrapper> availableConnections = new LinkedBlockingQueue<ConnectionWrapper>();
+
+ /**
+ * The connections that are currently in use.
+ */
+ @GuardedBy( "mainLock" )
+ private final Set<ConnectionWrapper> inUseConnections = new HashSet<ConnectionWrapper>();
+
+ /**
+ * Timeout in nanoseconds for idle connections waiting to be used. Threads use this timeout only when there are more than
+ * corePoolSize present. Otherwise they wait forever to be used.
+ */
+ private volatile long keepAliveTime;
+
+ /**
+ * The target pool size, updated only while holding mainLock, but volatile to allow concurrent readability even during
+ * updates.
+ */
+ @GuardedBy( "mainLock" )
+ private volatile int corePoolSize;
+
+ /**
+ * Maximum pool size, updated only while holding mainLock but volatile to allow concurrent readability even during updates.
+ */
+ @GuardedBy( "mainLock" )
+ private volatile int maximumPoolSize;
+
+ /**
+ * Current pool size, updated only while holding mainLock but volatile to allow concurrent readability even during updates.
+ */
+ @GuardedBy( "mainLock" )
+ private volatile int poolSize;
+
+ /**
+ * Lifecycle state, updated only while holding mainLock but volatile to allow concurrent readability even during updates.
+ */
+ @GuardedBy( "mainLock" )
+ private volatile int runState;
+
+ // Special values for runState
+ /** Normal, not-shutdown mode */
+ static final int RUNNING = 0;
+ /** Controlled shutdown mode */
+ static final int SHUTDOWN = 1;
+ /** Immediate shutdown mode */
+ static final int STOP = 2;
+ /** Final state */
+ static final int TERMINATED = 3;
+
+ /**
+ * Flag specifying whether a connection should be validated before returning it from the {@link #getConnection()} method.
+ */
+ private final AtomicBoolean validateConnectionBeforeUse = new AtomicBoolean(false);
+
+ /**
+ * The time in nanoseconds that ping should wait before timing out and failing.
+ */
+ private final AtomicLong pingTimeout = new AtomicLong(0);
+
+ /**
+ * The number of times an attempt to obtain a connection should fail with invalid connections before throwing an exception.
+ */
+ private final AtomicInteger maxFailedAttemptsBeforeError = new AtomicInteger(10);
+
+ private final AtomicLong totalConnectionsCreated = new AtomicLong(0);
+
+ private final AtomicLong totalConnectionsUsed = new AtomicLong(0);
+
+ private final Logger logger = Logger.getLogger(this.getClass());
+
+ /**
+ * Create the pool to use the supplied connection factory, which is typically a {@link RepositorySource}. This constructor
+ * uses the {@link #DEFAULT_CORE_POOL_SIZE default core pool size}, {@link #DEFAULT_MAXIMUM_POOL_SIZE default maximum pool
+ * size}, and {@link #DEFAULT_KEEP_ALIVE_TIME_IN_SECONDS default keep-alive time (in seconds)}.
+ *
+ * @param connectionFactory the factory for connections
+ * @throws IllegalArgumentException if the connection factory is null or any of the supplied arguments are invalid
+ */
+ public RepositoryConnectionPool( RepositoryConnectionFactory connectionFactory ) {
+ this(connectionFactory, DEFAULT_CORE_POOL_SIZE, DEFAULT_MAXIMUM_POOL_SIZE, DEFAULT_KEEP_ALIVE_TIME_IN_SECONDS,
+ TimeUnit.SECONDS);
+ }
+
+ /**
+ * Create the pool to use the supplied connection factory, which is typically a {@link RepositorySource}.
+ *
+ * @param connectionFactory the factory for connections
+ * @param corePoolSize the number of connections to keep in the pool, even if they are idle.
+ * @param maximumPoolSize the maximum number of connections to allow in the pool.
+ * @param keepAliveTime when the number of connection is greater than the core, this is the maximum time that excess idle
+ * connections will be kept before terminating.
+ * @param unit the time unit for the keepAliveTime argument.
+ * @throws IllegalArgumentException if the connection factory is null or any of the supplied arguments are invalid
+ */
+ public RepositoryConnectionPool( RepositoryConnectionFactory connectionFactory,
+ int corePoolSize,
+ int maximumPoolSize,
+ long keepAliveTime,
+ TimeUnit unit ) {
+ ArgCheck.isNonNegative(corePoolSize, "corePoolSize");
+ ArgCheck.isPositive(maximumPoolSize, "maximumPoolSize");
+ ArgCheck.isNonNegative(keepAliveTime, "keepAliveTime");
+ ArgCheck.isNotNull(connectionFactory, "repository connection factory");
+ if (maximumPoolSize < corePoolSize) {
+ throw new IllegalArgumentException(SpiI18n.maximumPoolSizeMayNotBeSmallerThanCorePoolSize.text());
+ }
+ this.connectionFactory = connectionFactory;
+ this.corePoolSize = corePoolSize;
+ this.maximumPoolSize = maximumPoolSize;
+ this.keepAliveTime = unit.toNanos(keepAliveTime);
+ this.setPingTimeout(100, TimeUnit.MILLISECONDS);
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.jboss.dna.spi.graph.connection.RepositoryConnectionFactory#getName()
+ */
+ public String getName() {
+ return this.connectionFactory.getName();
+ }
+
+ // -------------------------------------------------
+ // Property settings ...
+ // -------------------------------------------------
+
+ /**
+ * @return validateConnectionBeforeUse
+ */
+ public boolean getValidateConnectionBeforeUse() {
+ return this.validateConnectionBeforeUse.get();
+ }
+
+ /**
+ * @param validateConnectionBeforeUse Sets validateConnectionBeforeUse to the specified value.
+ */
+ public void setValidateConnectionBeforeUse( boolean validateConnectionBeforeUse ) {
+ this.validateConnectionBeforeUse.set(validateConnectionBeforeUse);
+ }
+
+ /**
+ * @return pingTimeout
+ */
+ public long getPingTimeoutInNanos() {
+ return this.pingTimeout.get();
+ }
+
+ /**
+ * @param pingTimeout the time to wait for a ping to complete
+ * @param unit the time unit of the time argument
+ */
+ public void setPingTimeout( long pingTimeout,
+ TimeUnit unit ) {
+ ArgCheck.isNonNegative(pingTimeout, "time");
+ this.pingTimeout.set(unit.toNanos(pingTimeout));
+ }
+
+ /**
+ * @return maxFailedAttemptsBeforeError
+ */
+ public int getMaxFailedAttemptsBeforeError() {
+ return this.maxFailedAttemptsBeforeError.get();
+ }
+
+ /**
+ * @param maxFailedAttemptsBeforeError Sets maxFailedAttemptsBeforeError to the specified value.
+ */
+ public void setMaxFailedAttemptsBeforeError( int maxFailedAttemptsBeforeError ) {
+ this.maxFailedAttemptsBeforeError.set(maxFailedAttemptsBeforeError);
+ }
+
+ /**
+ * Sets the time limit for which connections may remain idle before being closed. If there are more than the core number of
+ * connections currently in the pool, after waiting this amount of time without being used, excess threads will be terminated.
+ * This overrides any value set in the constructor.
+ *
+ * @param time the time to wait. A time value of zero will cause excess connections to terminate immediately after being
+ * returned.
+ * @param unit the time unit of the time argument
+ * @throws IllegalArgumentException if time less than zero
+ * @see #getKeepAliveTime
+ */
+ public void setKeepAliveTime( long time,
+ TimeUnit unit ) {
+ ArgCheck.isNonNegative(time, "time");
+ this.keepAliveTime = unit.toNanos(time);
+ }
+
+ /**
+ * Returns the connection keep-alive time, which is the amount of time which connections in excess of the core pool size may
+ * remain idle before being closed.
+ *
+ * @param unit the desired time unit of the result
+ * @return the time limit
+ * @see #setKeepAliveTime
+ */
+ public long getKeepAliveTime( TimeUnit unit ) {
+ assert unit != null;
+ return unit.convert(keepAliveTime, TimeUnit.NANOSECONDS);
+ }
+
+ /**
+ * @return maximumPoolSize
+ */
+ public int getMaximumPoolSize() {
+ return this.maximumPoolSize;
+ }
+
+ /**
+ * Sets the maximum allowed number of connections. This overrides any value set in the constructor. If the new value is
+ * smaller than the current value, excess existing but unused connections will be closed.
+ *
+ * @param maximumPoolSize the new maximum
+ * @throws IllegalArgumentException if maximumPoolSize less than zero or the {@link #getCorePoolSize() core pool size}
+ * @see #getMaximumPoolSize
+ */
+ public void setMaximumPoolSize( int maximumPoolSize ) {
+ ArgCheck.isPositive(maximumPoolSize, "maximum pool size");
+ if (maximumPoolSize < corePoolSize) {
+ throw new IllegalArgumentException(SpiI18n.maximumPoolSizeMayNotBeSmallerThanCorePoolSize.text());
+ }
+ final ReentrantLock mainLock = this.mainLock;
+ try {
+ mainLock.lock();
+ int extra = this.maximumPoolSize - maximumPoolSize;
+ this.maximumPoolSize = maximumPoolSize;
+ if (extra > 0 && poolSize > maximumPoolSize) {
+ // Drain the extra connections from those available ...
+ drainUnusedConnections(extra);
+ }
+ } finally {
+ mainLock.unlock();
+ }
+ }
+
+ /**
+ * Returns the core number of connections.
+ *
+ * @return the core number of connections
+ * @see #setCorePoolSize(int)
+ */
+ public int getCorePoolSize() {
+ return this.corePoolSize;
+ }
+
+ /**
+ * Sets the core number of connections. This overrides any value set in the constructor. If the new value is smaller than the
+ * current value, excess existing and unused connections will be closed. If larger, new connections will, if needed, be
+ * created.
+ *
+ * @param corePoolSize the new core size
+ * @throws RepositorySourceException if there was an error obtaining the new connection
+ * @throws InterruptedException if the thread was interrupted during the operation
+ * @throws IllegalArgumentException if <tt>corePoolSize</tt> less than zero
+ * @see #getCorePoolSize()
+ */
+ public void setCorePoolSize( int corePoolSize ) throws RepositorySourceException, InterruptedException {
+ ArgCheck.isNonNegative(corePoolSize, "core pool size");
+ if (maximumPoolSize < corePoolSize) {
+ throw new IllegalArgumentException(SpiI18n.maximumPoolSizeMayNotBeSmallerThanCorePoolSize.text());
+ }
+ final ReentrantLock mainLock = this.mainLock;
+ try {
+ mainLock.lock();
+ int extra = this.corePoolSize - corePoolSize;
+ this.corePoolSize = corePoolSize;
+ if (extra < 0) {
+ // Add connections ...
+ addConnectionsIfUnderCorePoolSize();
+ } else if (extra > 0 && poolSize > corePoolSize) {
+ // Drain the extra connections from those available ...
+ drainUnusedConnections(extra);
+ }
+ } finally {
+ mainLock.unlock();
+ }
+ }
+
+ // -------------------------------------------------
+ // Statistics ...
+ // -------------------------------------------------
+
+ /**
+ * Returns the current number of connections in the pool, including those that are checked out (in use) and those that are not
+ * being used.
+ *
+ * @return the number of connections
+ */
+ public int getPoolSize() {
+ return poolSize;
+ }
+
+ /**
+ * Returns the approximate number of connections that are currently checked out from the pool.
+ *
+ * @return the number of checked-out connections
+ */
+ public int getInUseCount() {
+ final ReentrantLock mainLock = this.mainLock;
+ try {
+ mainLock.lock();
+ return this.inUseConnections.size();
+ } finally {
+ mainLock.unlock();
+ }
+ }
+
+ /**
+ * Get the total number of connections that have been created by this pool.
+ *
+ * @return the total number of connections created by this pool
+ */
+ public long getTotalConnectionsCreated() {
+ return this.totalConnectionsCreated.get();
+ }
+
+ /**
+ * Get the total number of times connections have been {@link #getConnection()} used.
+ *
+ * @return the total number
+ */
+ public long getTotalConnectionsUsed() {
+ return this.totalConnectionsUsed.get();
+ }
+
+ // -------------------------------------------------
+ // State management methods ...
+ // -------------------------------------------------
+
+ /**
+ * Starts a core connection, causing it to idly wait for use. This overrides the default policy of starting core connections
+ * only when they are {@link #getConnection() needed}. This method will return <tt>false</tt> if all core connections have
+ * already been started.
+ *
+ * @return true if a connection was started
+ * @throws RepositorySourceException if there was an error obtaining the new connection
+ * @throws InterruptedException if the thread was interrupted during the operation
+ */
+ public boolean prestartCoreConnection() throws RepositorySourceException, InterruptedException {
+ final ReentrantLock mainLock = this.mainLock;
+ try {
+ mainLock.lock();
+ return addConnectionIfUnderCorePoolSize();
+ } finally {
+ mainLock.unlock();
+ }
+ }
+
+ /**
+ * Starts all core connections, causing them to idly wait for use. This overrides the default policy of starting core
+ * connections only when they are {@link #getConnection() needed}.
+ *
+ * @return the number of connections started.
+ * @throws RepositorySourceException if there was an error obtaining the new connection
+ * @throws InterruptedException if the thread was interrupted during the operation
+ */
+ public int prestartAllCoreConnections() throws RepositorySourceException, InterruptedException {
+ final ReentrantLock mainLock = this.mainLock;
+ try {
+ mainLock.lock();
+ return addConnectionsIfUnderCorePoolSize();
+ } finally {
+ mainLock.unlock();
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.jboss.dna.spi.graph.connection.ManagedRepositoryConnectionFactory#shutdown()
+ */
+ public void shutdown() {
+ // Fail if caller doesn't have modifyThread permission. We
+ // explicitly check permissions directly because we can't trust
+ // implementations of SecurityManager to correctly override
+ // the "check access" methods such that our documented
+ // security policy is implemented.
+ SecurityManager security = System.getSecurityManager();
+ if (security != null) java.security.AccessController.checkPermission(shutdownPerm);
+
+ this.logger.debug("Shutting down repository connection pool for {0}", getName());
+ boolean fullyTerminated = false;
+ final ReentrantLock mainLock = this.mainLock;
+ try {
+ mainLock.lock();
+ int state = this.runState;
+ if (state == RUNNING) {
+ // don't override shutdownNow
+ this.runState = SHUTDOWN;
+ }
+
+ // Kill the maintenance thread ...
+
+ // Remove and close all available connections ...
+ if (!this.availableConnections.isEmpty()) {
+ // Drain the extra connections from those available ...
+ drainUnusedConnections(this.availableConnections.size());
+ }
+
+ // If there are no connections being used, trigger full termination now ...
+ if (this.inUseConnections.isEmpty()) {
+ fullyTerminated = true;
+ this.logger.trace("Signalling termination of repository connection pool for {0}", getName());
+ runState = TERMINATED;
+ termination.signalAll();
+ this.logger.debug("Terminated repository connection pool for {0}", getName());
+ }
+ // Otherwise the last connection that is closed will transition the runState to TERMINATED ...
+ } finally {
+ mainLock.unlock();
+ }
+ if (fullyTerminated) terminated();
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.jboss.dna.spi.graph.connection.ManagedRepositoryConnectionFactory#shutdownNow()
+ */
+ public void shutdownNow() {
+ // Almost the same code as shutdown()
+ SecurityManager security = System.getSecurityManager();
+ if (security != null) java.security.AccessController.checkPermission(shutdownPerm);
+
+ this.logger.debug("Shutting down (immediately) repository connection pool for {0}", getName());
+ boolean fullyTerminated = false;
+ final ReentrantLock mainLock = this.mainLock;
+ try {
+ mainLock.lock();
+ int state = this.runState;
+ if (state != TERMINATED) {
+ // don't override shutdownNow
+ this.runState = STOP;
+ }
+
+ // Kill the maintenance thread ...
+
+ // Remove and close all available connections ...
+ if (!this.availableConnections.isEmpty()) {
+ // Drain the extra connections from those available ...
+ drainUnusedConnections(this.availableConnections.size());
+ }
+
+ // If there are connections being used, close them now ...
+ if (!this.inUseConnections.isEmpty()) {
+ for (ConnectionWrapper connectionInUse : this.inUseConnections) {
+ try {
+ this.logger.trace("Closing repository connection to {0}", getName());
+ connectionInUse.getOriginal().close();
+ } catch (InterruptedException e) {
+ // Ignore this ...
+ }
+ }
+ this.poolSize -= this.inUseConnections.size();
+ // The last connection that is closed will transition the runState to TERMINATED ...
+ } else {
+ // There are no connections in use, so trigger full termination now ...
+ fullyTerminated = true;
+ this.logger.trace("Signalling termination of repository connection pool for {0}", getName());
+ runState = TERMINATED;
+ termination.signalAll();
+ this.logger.debug("Terminated repository connection pool for {0}", getName());
+ }
+
+ } finally {
+ mainLock.unlock();
+ }
+ if (fullyTerminated) terminated();
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.jboss.dna.spi.graph.connection.ManagedRepositoryConnectionFactory#isRunning()
+ */
+ public boolean isRunning() {
+ return runState == RUNNING;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.jboss.dna.spi.graph.connection.ManagedRepositoryConnectionFactory#isShutdown()
+ */
+ public boolean isShutdown() {
+ return runState != RUNNING;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.jboss.dna.spi.graph.connection.ManagedRepositoryConnectionFactory#isTerminating()
+ */
+ public boolean isTerminating() {
+ return runState == STOP;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.jboss.dna.spi.graph.connection.ManagedRepositoryConnectionFactory#isTerminated()
+ */
+ public boolean isTerminated() {
+ return runState == TERMINATED;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.jboss.dna.spi.graph.connection.ManagedRepositoryConnectionFactory#awaitTermination(long, java.util.concurrent.TimeUnit)
+ */
+ public boolean awaitTermination( long timeout,
+ TimeUnit unit ) throws InterruptedException {
+ long nanos = unit.toNanos(timeout);
+ final ReentrantLock mainLock = this.mainLock;
+ try {
+ mainLock.lock();
+ for (;;) {
+ // this.logger.debug("---> Run state = {}; condition = {}", runState, termination);
+ if (runState == TERMINATED) return true;
+ if (nanos <= 0) return false;
+ nanos = termination.awaitNanos(nanos);
+ // this.logger.debug("---> Done waiting: run state = {}; condition = {}", runState, termination);
+ }
+ } finally {
+ mainLock.unlock();
+ }
+ }
+
+ /**
+ * Method invoked when the pool has terminated. Default implementation does nothing. Note: To properly nest multiple
+ * overridings, subclasses should generally invoke <tt>super.terminated</tt> within this method.
+ */
+ protected void terminated() {
+ }
+
+ /**
+ * Invokes <tt>shutdown</tt> when this pool is no longer referenced.
+ */
+ @Override
+ protected void finalize() {
+ shutdown();
+ }
+
+ // -------------------------------------------------
+ // Connection management methods ...
+ // -------------------------------------------------
+
+ /**
+ * {@inheritDoc}
+ */
+ public RepositoryConnection getConnection() throws RepositorySourceException, InterruptedException {
+ int attemptsAllowed = this.maxFailedAttemptsBeforeError.get();
+ ConnectionWrapper connection = null;
+ // Do this until we get a good connection ...
+ int attemptsRemaining = attemptsAllowed;
+ while (connection == null && attemptsRemaining > 0) {
+ --attemptsRemaining;
+ ReentrantLock mainLock = this.mainLock;
+ try {
+ mainLock.lock();
+ // If we're shutting down the pool, then just close the connection ...
+ if (this.runState != RUNNING) {
+ throw new IllegalStateException(SpiI18n.repositoryConnectionPoolIsNotRunning.text());
+ }
+ // If there are fewer total connections than the core size ...
+ if (this.poolSize < this.corePoolSize) {
+ // Immediately create a wrapped connection and return it ...
+ connection = newWrappedConnection();
+ }
+ // Peek to see if there is a connection available ...
+ else if (this.availableConnections.peek() != null) {
+ // There is, so take it and return it ...
+ connection = this.availableConnections.take();
+ }
+ // There is no connection available. If there are fewer total connections than the maximum size ...
+ else if (this.poolSize < this.maximumPoolSize) {
+ // Immediately create a wrapped connection and return it ...
+ connection = newWrappedConnection();
+ }
+ if (connection != null) {
+ this.inUseConnections.add(connection);
+ }
+ } finally {
+ mainLock.unlock();
+ }
+ if (connection == null) {
+ // There are not enough connections, so wait in line for the next available connection ...
+ this.logger.trace("Waiting for a repository connection from pool {0}", getName());
+ connection = this.availableConnections.take();
+ mainLock = this.mainLock;
+ mainLock.lock();
+ try {
+ if (connection != null) {
+ this.inUseConnections.add(connection);
+ }
+ } finally {
+ mainLock.unlock();
+ }
+ this.logger.trace("Recieved a repository connection from pool {0}", getName());
+ }
+ if (connection != null && this.validateConnectionBeforeUse.get()) {
+ connection = validateConnection(connection);
+ }
+ }
+ if (connection == null) {
+ // We were unable to obtain a usable connection, so fail ...
+ throw new RepositorySourceException(SpiI18n.unableToObtainValidRepositoryAfterAttempts.text(attemptsAllowed));
+ }
+ this.totalConnectionsUsed.incrementAndGet();
+ return connection;
+ }
+
+ /**
+ * This method is automatically called by the {@link ConnectionWrapper} when it is {@link ConnectionWrapper#close() closed}.
+ *
+ * @param wrapper the wrapper to the connection that is being returned to the pool
+ */
+ protected void returnConnection( ConnectionWrapper wrapper ) {
+ assert wrapper != null;
+ ConnectionWrapper wrapperToClose = null;
+ final ReentrantLock mainLock = this.mainLock;
+ try {
+ mainLock.lock();
+ // Remove the connection from the in-use set ...
+ boolean removed = this.inUseConnections.remove(wrapper);
+ assert removed;
+
+ // If we're shutting down the pool, then just close the connection ...
+ if (this.runState != RUNNING) {
+ wrapperToClose = wrapper;
+ }
+ // If there are more connections than the maximum size...
+ else if (this.poolSize > this.maximumPoolSize) {
+ // Immediately close this connection ...
+ wrapperToClose = wrapper;
+ }
+ // Attempt to make the connection available (this should generally work, unless there is an upper limit
+ // to the number of available connections) ...
+ else if (!this.availableConnections.offer(new ConnectionWrapper(wrapper.getOriginal()))) {
+ // The pool of available connection is full, so release it ...
+ wrapperToClose = wrapper;
+ }
+ } finally {
+ mainLock.unlock();
+ }
+ // Close the connection if we're supposed to (do it outside of the main lock)...
+ if (wrapperToClose != null) {
+ try {
+ closeConnection(wrapper);
+ } catch (InterruptedException e) {
+ // catch this, as there's not much we can do and the caller doesn't care or know how to handle it
+ this.logger.trace(e, "Interrupted while closing a repository connection");
+ }
+ }
+ }
+
+ /**
+ * Validate the supplied connection, returning the connection if valid or null if the connection is not valid.
+ *
+ * @param connection the connection to be validated; may not be null
+ * @return the validated connection, or null if the connection did not validate and was removed from the pool
+ */
+ protected ConnectionWrapper validateConnection( ConnectionWrapper connection ) {
+ assert connection != null;
+ ConnectionWrapper invalidConnection = null;
+ try {
+ if (!connection.ping(this.pingTimeout.get(), TimeUnit.NANOSECONDS)) {
+ invalidConnection = connection;
+ }
+ } catch (InterruptedException e) {
+ // catch this, as there's not much we can do and the caller doesn't care or know how to handle it
+ this.logger.trace(e, "Interrupted while pinging a repository connection");
+ invalidConnection = connection;
+ } finally {
+ if (invalidConnection != null) {
+ connection = null;
+ returnConnection(invalidConnection);
+ }
+ }
+ return connection;
+ }
+
+ /**
+ * Obtain a new connection wrapped in a {@link ConnectionWrapper}. This method does not check whether creating the new
+ * connection would violate the {@link #maximumPoolSize maximum pool size} nor does it add the new connection to the
+ * {@link #availableConnections available connections} (as the caller may want it immediately), but it does increment the
+ * {@link #poolSize pool size}.
+ *
+ * @return the connection wrapper with a new connection
+ * @throws RepositorySourceException if there was an error obtaining the new connection
+ * @throws InterruptedException if the thread was interrupted during the operation
+ */
+ @GuardedBy( "mainLock" )
+ protected ConnectionWrapper newWrappedConnection() throws RepositorySourceException, InterruptedException {
+ RepositoryConnection connection = this.connectionFactory.getConnection();
+ ++this.poolSize;
+ this.totalConnectionsCreated.incrementAndGet();
+ return new ConnectionWrapper(connection);
+ }
+
+ /**
+ * Close a connection that is in the pool but no longer in the {@link #availableConnections available connections}. This
+ * method does decrement the {@link #poolSize pool size}.
+ *
+ * @param wrapper the wrapper for the connection to be closed
+ * @throws InterruptedException if the thread was interrupted during the operation
+ */
+ protected void closeConnection( ConnectionWrapper wrapper ) throws InterruptedException {
+ assert wrapper != null;
+ RepositoryConnection original = wrapper.getOriginal();
+ assert original != null;
+ try {
+ this.logger.debug("Closing repository connection to {0}", getName());
+ original.close();
+ } finally {
+ final ReentrantLock mainLock = this.mainLock;
+ try {
+ mainLock.lock();
+ // No matter what reduce the pool size count
+ --this.poolSize;
+ // And if shutting down and this was the last connection being used...
+ if (this.runState == SHUTDOWN && this.poolSize <= 0) {
+ // then signal anybody that has called "awaitTermination(...)"
+ this.logger.trace("Signalling termination of repository connection pool for {0}", getName());
+ this.runState = TERMINATED;
+ this.termination.signalAll();
+ this.logger.trace("Terminated repository connection pool for {0}", getName());
+
+ // fall through to call terminate() outside of lock.
+ }
+ } finally {
+ mainLock.unlock();
+ }
+ }
+ }
+
+ @GuardedBy( "mainLock" )
+ protected int drainUnusedConnections( int count ) {
+ if (count <= 0) return 0;
+ this.logger.trace("Draining up to {0} unused repository connections to {1}", count, getName());
+ // Drain the extra connections from those available ...
+ Collection<ConnectionWrapper> extraConnections = new LinkedList<ConnectionWrapper>();
+ this.availableConnections.drainTo(extraConnections, count);
+ for (ConnectionWrapper connection : extraConnections) {
+ try {
+ this.logger.trace("Closing repository connection to {0}", getName());
+ connection.getOriginal().close();
+ } catch (InterruptedException e) {
+ // Ignore this ...
+ }
+ }
+ int numClosed = extraConnections.size();
+ this.poolSize -= numClosed;
+ this.logger.trace("Drained {0} unused connections", numClosed);
+ return numClosed;
+ }
+
+ @GuardedBy( "mainLock" )
+ protected boolean addConnectionIfUnderCorePoolSize() throws RepositorySourceException, InterruptedException {
+ // Add connection ...
+ if (this.poolSize < this.corePoolSize) {
+ this.availableConnections.offer(newWrappedConnection());
+ this.logger.trace("Added connection to {0} in undersized pool", getName());
+ return true;
+ }
+ return false;
+ }
+
+ @GuardedBy( "mainLock" )
+ protected int addConnectionsIfUnderCorePoolSize() throws RepositorySourceException, InterruptedException {
+ // Add connections ...
+ int n = 0;
+ while (this.poolSize < this.corePoolSize) {
+ this.availableConnections.offer(newWrappedConnection());
+ ++n;
+ }
+ this.logger.trace("Added {0} connection(s) to {1} in undersized pool", n, getName());
+ return n;
+ }
+
+ protected class ConnectionWrapper implements RepositoryConnection {
+
+ private final RepositoryConnection original;
+ private final long timeCreated;
+ private long lastUsed;
+ private boolean closed = false;
+
+ protected ConnectionWrapper( RepositoryConnection connection ) {
+ assert connection != null;
+ this.original = connection;
+ this.timeCreated = System.currentTimeMillis();
+ }
+
+ /**
+ * @return original
+ */
+ protected RepositoryConnection getOriginal() {
+ return this.original;
+ }
+
+ /**
+ * @return lastUsed
+ */
+ public long getTimeLastUsed() {
+ return this.lastUsed;
+ }
+
+ /**
+ * @return timeCreated
+ */
+ public long getTimeCreated() {
+ return this.timeCreated;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public String getSourceName() {
+ return this.original.getSourceName();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public XAResource getXAResource() {
+ if (closed) throw new IllegalStateException(SpiI18n.closedConnectionMayNotBeUsed.text());
+ return this.original.getXAResource();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public CachePolicy getDefaultCachePolicy() {
+ if (closed) throw new IllegalStateException(SpiI18n.closedConnectionMayNotBeUsed.text());
+ return this.original.getDefaultCachePolicy();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void execute( ExecutionEnvironment env,
+ GraphCommand... commands ) throws RepositorySourceException, InterruptedException {
+ if (closed) throw new IllegalStateException(SpiI18n.closedConnectionMayNotBeUsed.text());
+ this.original.execute(env, commands);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean ping( long time,
+ TimeUnit unit ) throws InterruptedException {
+ if (closed) throw new IllegalStateException(SpiI18n.closedConnectionMayNotBeUsed.text());
+ return this.original.ping(time, unit);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void close() throws InterruptedException {
+ if (!closed) {
+ this.lastUsed = System.currentTimeMillis();
+ this.original.close();
+ this.closed = true;
+ returnConnection(this);
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void setListener( RepositorySourceListener listener ) {
+ if (!closed) this.original.setListener(listener);
+ }
+
+ }
+
+}
Modified: trunk/dna-spi/src/main/java/org/jboss/dna/spi/graph/connection/RepositorySource.java
===================================================================
--- trunk/dna-spi/src/main/java/org/jboss/dna/spi/graph/connection/RepositorySource.java 2008-07-24 19:52:13 UTC (rev 369)
+++ trunk/dna-spi/src/main/java/org/jboss/dna/spi/graph/connection/RepositorySource.java 2008-07-25 19:37:40 UTC (rev 370)
@@ -38,29 +38,28 @@
* repository (e.g., in a configuration area), and needs to be reinstantiated.
* </p>
* <p>
- * Objects that implement this <code>RepositorySource</code> interface are typically registered with a naming service such as
- * Java Naming and Directory Interface<sup><font size=-3>TM</font></sup> (JNDI). This interface extends both
- * {@link Referenceable} and {@link Serializable} so that such objects can be stored in any JNDI naming context and enable proper
- * system recovery,
+ * Objects that implement this <code>RepositorySource</code> interface are typically registered with a naming service such as Java
+ * Naming and Directory Interface<sup><font size=-3>TM</font></sup> (JNDI). This interface extends both {@link Referenceable} and
+ * {@link Serializable} so that such objects can be stored in any JNDI naming context and enable proper system recovery,
* </p>
*
* @author Randall Hauch
*/
-public interface RepositorySource extends RepositoryConnectionFactory, Referenceable, Serializable {
+public interface RepositorySource extends ManagedRepositoryConnectionFactory, Referenceable, Serializable {
/**
- * Get the maximum number of retries that may be performed on a given operation when using
- * {@link #getConnection() connections} created by this source. This value does not constitute a minimum number of retries; in
- * fact, the connection user is not required to retry any operations.
+ * Get the maximum number of retries that may be performed on a given operation when using {@link #getConnection()
+ * connections} created by this source. This value does not constitute a minimum number of retries; in fact, the connection
+ * user is not required to retry any operations.
*
* @return the maximum number of allowable retries, or 0 if the source has no limit
*/
int getRetryLimit();
/**
- * Set the maximum number of retries that may be performed on a given operation when using
- * {@link #getConnection() connections} created by this source. This value does not constitute a minimum number of retries; in
- * fact, the connection user is not required to retry any operations.
+ * Set the maximum number of retries that may be performed on a given operation when using {@link #getConnection()
+ * connections} created by this source. This value does not constitute a minimum number of retries; in fact, the connection
+ * user is not required to retry any operations.
*
* @param limit the maximum number of allowable retries, or 0 if the source has no limit
*/
Deleted: trunk/dna-spi/src/test/java/org/jboss/dna/spi/graph/connection/BasicRepositoryConnectionPoolTest.java
===================================================================
--- trunk/dna-spi/src/test/java/org/jboss/dna/spi/graph/connection/BasicRepositoryConnectionPoolTest.java 2008-07-24 19:52:13 UTC (rev 369)
+++ trunk/dna-spi/src/test/java/org/jboss/dna/spi/graph/connection/BasicRepositoryConnectionPoolTest.java 2008-07-25 19:37:40 UTC (rev 370)
@@ -1,218 +0,0 @@
-/*
- * 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 static org.hamcrest.core.Is.is;
-import static org.hamcrest.core.IsNull.notNullValue;
-import static org.jboss.dna.spi.graph.connection.RepositorySourceLoadHarness.runLoadTest;
-import static org.junit.Assert.assertThat;
-import java.util.List;
-import java.util.concurrent.Future;
-import java.util.concurrent.TimeUnit;
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Ignore;
-import org.junit.Test;
-
-/**
- * @author Randall Hauch
- */
-public class BasicRepositoryConnectionPoolTest {
-
- private BasicRepositoryConnectionPool pool;
- private TimeDelayingRepositorySource repositorySource;
- private ExecutionEnvironment env;
-
- @Before
- public void beforeEach() {
- this.repositorySource = new TimeDelayingRepositorySource("source 1");
- this.pool = new BasicRepositoryConnectionPool(this.repositorySource, 1, 1, 100, TimeUnit.SECONDS);
- this.env = null;
- }
-
- @After
- public void afterEach() throws Exception {
- pool.shutdown();
- pool.awaitTermination(2, TimeUnit.SECONDS);
- }
-
- @Test
- public void shouldBeCreatedInRunningState() {
- assertThat(pool.isShutdown(), is(false));
- assertThat(pool.isTerminating(), is(false));
- assertThat(pool.isTerminated(), is(false));
- assertThat(pool.getTotalConnectionsCreated(), is(0l));
- assertThat(pool.getTotalConnectionsUsed(), is(0l));
- }
-
- @Test
- public void shouldShutdownWhenNoConnectionsWereCreatedOrUsed() throws InterruptedException {
- assertThat(pool.isShutdown(), is(false));
- assertThat(pool.isTerminating(), is(false));
- assertThat(pool.isTerminated(), is(false));
- assertThat(pool.getTotalConnectionsCreated(), is(0l));
- assertThat(pool.getTotalConnectionsUsed(), is(0l));
-
- for (int i = 0; i != 4; ++i) {
- pool.shutdown();
- assertThat(pool.isShutdown() || pool.isTerminating() || pool.isTerminated(), is(true));
- pool.awaitTermination(2, TimeUnit.SECONDS);
- assertThat(pool.isTerminated(), is(true));
- assertThat(pool.getTotalConnectionsCreated(), is(0l));
- assertThat(pool.getTotalConnectionsUsed(), is(0l));
- }
- }
-
- @Test
- public void shouldCreateConnectionAndRecoverWhenClosed() throws RepositorySourceException, InterruptedException {
- assertThat(pool.getTotalConnectionsCreated(), is(0l));
- assertThat(pool.getTotalConnectionsUsed(), is(0l));
-
- RepositoryConnection conn = pool.getConnection();
- assertThat(conn, is(notNullValue()));
- assertThat(pool.getTotalConnectionsCreated(), is(1l));
- assertThat(pool.getTotalConnectionsUsed(), is(1l));
- assertThat(pool.getPoolSize(), is(1));
-
- conn.close();
-
- assertThat(pool.getTotalConnectionsCreated(), is(1l));
- assertThat(pool.getTotalConnectionsUsed(), is(1l));
- assertThat(pool.getPoolSize(), is(1));
- }
-
- @Test
- public void shouldAllowShutdownToBeCalledMultipleTimesEvenWhenShutdown()
- throws RepositorySourceException, InterruptedException {
- assertThat(pool.getTotalConnectionsCreated(), is(0l));
- assertThat(pool.getTotalConnectionsUsed(), is(0l));
-
- RepositoryConnection conn = pool.getConnection();
- assertThat(conn, is(notNullValue()));
- assertThat(pool.getTotalConnectionsCreated(), is(1l));
- assertThat(pool.getTotalConnectionsUsed(), is(1l));
- assertThat(pool.getPoolSize(), is(1));
-
- conn.close();
-
- assertThat(pool.getTotalConnectionsCreated(), is(1l));
- assertThat(pool.getTotalConnectionsUsed(), is(1l));
- assertThat(pool.getPoolSize(), is(1));
-
- pool.shutdown();
- pool.shutdown();
- pool.awaitTermination(2, TimeUnit.SECONDS);
- assertThat(pool.isTerminated(), is(true));
- assertThat(pool.getTotalConnectionsCreated(), is(1l));
- assertThat(pool.getTotalConnectionsUsed(), is(1l));
- pool.shutdown();
- pool.awaitTermination(2, TimeUnit.SECONDS);
- pool.shutdown();
- pool.awaitTermination(2, TimeUnit.SECONDS);
- }
-
- @Test( expected = IllegalStateException.class )
- public void shouldNotCreateConnectionIfPoolIsNotRunning() throws RepositorySourceException, InterruptedException {
- pool.shutdown();
- pool.awaitTermination(2, TimeUnit.SECONDS);
- assertThat(pool.isTerminated(), is(true));
- assertThat(pool.getTotalConnectionsCreated(), is(0l));
- assertThat(pool.getTotalConnectionsUsed(), is(0l));
- pool.getConnection(); // this should fail with illegal state
- }
-
- @Test
- public void shouldAllowConnectionsToBeClosedMoreThanOnceWithNoIllEffects()
- throws RepositorySourceException, InterruptedException {
- assertThat(pool.getTotalConnectionsCreated(), is(0l));
- assertThat(pool.getTotalConnectionsUsed(), is(0l));
-
- RepositoryConnection conn = pool.getConnection();
- assertThat(conn, is(notNullValue()));
- assertThat(pool.getTotalConnectionsCreated(), is(1l));
- assertThat(pool.getTotalConnectionsUsed(), is(1l));
- assertThat(pool.getPoolSize(), is(1));
-
- conn.close();
- conn.close();
- }
-
- @Test
- public void shouldBlockClientsWhenNotEnoughConnections() throws Exception {
- int numConnectionsInPool = 1;
- int numClients = 2;
- BasicRepositoryConnectionPool pool = new BasicRepositoryConnectionPool(repositorySource);
- pool.setCorePoolSize(numConnectionsInPool);
- pool.setMaximumPoolSize(numConnectionsInPool);
- RepositoryOperation.Factory<Integer> operationFactory = RepositorySourceLoadHarness.createMultipleLoadOperationFactory(10);
- runLoadTest(env, pool, numClients, 100, TimeUnit.MILLISECONDS, operationFactory);
- pool.shutdown();
- pool.awaitTermination(4, TimeUnit.SECONDS);
- }
-
- @Test
- public void shouldLimitClientsToRunSequentiallyWithOneConnectionInPool() throws Exception {
- int numConnectionsInPool = 1;
- int numClients = 3;
- BasicRepositoryConnectionPool pool = new BasicRepositoryConnectionPool(repositorySource);
- pool.setCorePoolSize(numConnectionsInPool);
- pool.setMaximumPoolSize(numConnectionsInPool);
- RepositoryOperation.Factory<Integer> operationFactory = RepositorySourceLoadHarness.createMultipleLoadOperationFactory(10);
- runLoadTest(env, pool, numClients, 100, TimeUnit.MILLISECONDS, operationFactory);
- pool.shutdown();
- pool.awaitTermination(4, TimeUnit.SECONDS);
- }
-
- @Test
- public void shouldClientsToRunConncurrentlyWithTwoConnectionsInPool() throws Exception {
- int numConnectionsInPool = 2;
- int numClients = 10;
- BasicRepositoryConnectionPool pool = new BasicRepositoryConnectionPool(repositorySource);
- pool.setCorePoolSize(numConnectionsInPool);
- pool.setMaximumPoolSize(numConnectionsInPool);
- RepositoryOperation.Factory<Integer> operationFactory = RepositorySourceLoadHarness.createMultipleLoadOperationFactory(10);
- runLoadTest(env, pool, numClients, 100, TimeUnit.MILLISECONDS, operationFactory);
- pool.shutdown();
- pool.awaitTermination(4, TimeUnit.SECONDS);
- }
-
- @Ignore( "doesn't run on hudson" )
- @Test
- public void shouldClientsToRunConncurrentlyWithMultipleConnectionInPool() throws Exception {
- int numConnectionsInPool = 10;
- int numClients = 50;
- BasicRepositoryConnectionPool pool = new BasicRepositoryConnectionPool(repositorySource);
- pool.setCorePoolSize(numConnectionsInPool);
- pool.setMaximumPoolSize(numConnectionsInPool);
- RepositoryOperation.Factory<Integer> operationFactory = RepositorySourceLoadHarness.createMultipleLoadOperationFactory(20);
- List<Future<Integer>> results = runLoadTest(env, pool, numClients, 200, TimeUnit.MILLISECONDS, operationFactory);
- int total = 0;
- for (Future<Integer> result : results) {
- assertThat(result.isDone(), is(true));
- if (result.isDone()) total += result.get();
- }
- assertThat(total, is(20 * numClients));
- pool.shutdown();
- pool.awaitTermination(4, TimeUnit.SECONDS);
- }
-
-}
Copied: trunk/dna-spi/src/test/java/org/jboss/dna/spi/graph/connection/RepositoryConnectionPoolTest.java (from rev 368, trunk/dna-spi/src/test/java/org/jboss/dna/spi/graph/connection/BasicRepositoryConnectionPoolTest.java)
===================================================================
--- trunk/dna-spi/src/test/java/org/jboss/dna/spi/graph/connection/RepositoryConnectionPoolTest.java (rev 0)
+++ trunk/dna-spi/src/test/java/org/jboss/dna/spi/graph/connection/RepositoryConnectionPoolTest.java 2008-07-25 19:37:40 UTC (rev 370)
@@ -0,0 +1,218 @@
+/*
+ * 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 static org.hamcrest.core.Is.is;
+import static org.hamcrest.core.IsNull.notNullValue;
+import static org.jboss.dna.spi.graph.connection.RepositorySourceLoadHarness.runLoadTest;
+import static org.junit.Assert.assertThat;
+import java.util.List;
+import java.util.concurrent.Future;
+import java.util.concurrent.TimeUnit;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Ignore;
+import org.junit.Test;
+
+/**
+ * @author Randall Hauch
+ */
+public class RepositoryConnectionPoolTest {
+
+ private RepositoryConnectionPool pool;
+ private TimeDelayingRepositorySource repositorySource;
+ private ExecutionEnvironment env;
+
+ @Before
+ public void beforeEach() {
+ this.repositorySource = new TimeDelayingRepositorySource("source 1");
+ this.pool = new RepositoryConnectionPool(this.repositorySource, 1, 1, 100, TimeUnit.SECONDS);
+ this.env = null;
+ }
+
+ @After
+ public void afterEach() throws Exception {
+ pool.shutdown();
+ pool.awaitTermination(2, TimeUnit.SECONDS);
+ }
+
+ @Test
+ public void shouldBeCreatedInRunningState() {
+ assertThat(pool.isShutdown(), is(false));
+ assertThat(pool.isTerminating(), is(false));
+ assertThat(pool.isTerminated(), is(false));
+ assertThat(pool.getTotalConnectionsCreated(), is(0l));
+ assertThat(pool.getTotalConnectionsUsed(), is(0l));
+ }
+
+ @Test
+ public void shouldShutdownWhenNoConnectionsWereCreatedOrUsed() throws InterruptedException {
+ assertThat(pool.isShutdown(), is(false));
+ assertThat(pool.isTerminating(), is(false));
+ assertThat(pool.isTerminated(), is(false));
+ assertThat(pool.getTotalConnectionsCreated(), is(0l));
+ assertThat(pool.getTotalConnectionsUsed(), is(0l));
+
+ for (int i = 0; i != 4; ++i) {
+ pool.shutdown();
+ assertThat(pool.isShutdown() || pool.isTerminating() || pool.isTerminated(), is(true));
+ pool.awaitTermination(2, TimeUnit.SECONDS);
+ assertThat(pool.isTerminated(), is(true));
+ assertThat(pool.getTotalConnectionsCreated(), is(0l));
+ assertThat(pool.getTotalConnectionsUsed(), is(0l));
+ }
+ }
+
+ @Test
+ public void shouldCreateConnectionAndRecoverWhenClosed() throws RepositorySourceException, InterruptedException {
+ assertThat(pool.getTotalConnectionsCreated(), is(0l));
+ assertThat(pool.getTotalConnectionsUsed(), is(0l));
+
+ RepositoryConnection conn = pool.getConnection();
+ assertThat(conn, is(notNullValue()));
+ assertThat(pool.getTotalConnectionsCreated(), is(1l));
+ assertThat(pool.getTotalConnectionsUsed(), is(1l));
+ assertThat(pool.getPoolSize(), is(1));
+
+ conn.close();
+
+ assertThat(pool.getTotalConnectionsCreated(), is(1l));
+ assertThat(pool.getTotalConnectionsUsed(), is(1l));
+ assertThat(pool.getPoolSize(), is(1));
+ }
+
+ @Test
+ public void shouldAllowShutdownToBeCalledMultipleTimesEvenWhenShutdown()
+ throws RepositorySourceException, InterruptedException {
+ assertThat(pool.getTotalConnectionsCreated(), is(0l));
+ assertThat(pool.getTotalConnectionsUsed(), is(0l));
+
+ RepositoryConnection conn = pool.getConnection();
+ assertThat(conn, is(notNullValue()));
+ assertThat(pool.getTotalConnectionsCreated(), is(1l));
+ assertThat(pool.getTotalConnectionsUsed(), is(1l));
+ assertThat(pool.getPoolSize(), is(1));
+
+ conn.close();
+
+ assertThat(pool.getTotalConnectionsCreated(), is(1l));
+ assertThat(pool.getTotalConnectionsUsed(), is(1l));
+ assertThat(pool.getPoolSize(), is(1));
+
+ pool.shutdown();
+ pool.shutdown();
+ pool.awaitTermination(2, TimeUnit.SECONDS);
+ assertThat(pool.isTerminated(), is(true));
+ assertThat(pool.getTotalConnectionsCreated(), is(1l));
+ assertThat(pool.getTotalConnectionsUsed(), is(1l));
+ pool.shutdown();
+ pool.awaitTermination(2, TimeUnit.SECONDS);
+ pool.shutdown();
+ pool.awaitTermination(2, TimeUnit.SECONDS);
+ }
+
+ @Test( expected = IllegalStateException.class )
+ public void shouldNotCreateConnectionIfPoolIsNotRunning() throws RepositorySourceException, InterruptedException {
+ pool.shutdown();
+ pool.awaitTermination(2, TimeUnit.SECONDS);
+ assertThat(pool.isTerminated(), is(true));
+ assertThat(pool.getTotalConnectionsCreated(), is(0l));
+ assertThat(pool.getTotalConnectionsUsed(), is(0l));
+ pool.getConnection(); // this should fail with illegal state
+ }
+
+ @Test
+ public void shouldAllowConnectionsToBeClosedMoreThanOnceWithNoIllEffects()
+ throws RepositorySourceException, InterruptedException {
+ assertThat(pool.getTotalConnectionsCreated(), is(0l));
+ assertThat(pool.getTotalConnectionsUsed(), is(0l));
+
+ RepositoryConnection conn = pool.getConnection();
+ assertThat(conn, is(notNullValue()));
+ assertThat(pool.getTotalConnectionsCreated(), is(1l));
+ assertThat(pool.getTotalConnectionsUsed(), is(1l));
+ assertThat(pool.getPoolSize(), is(1));
+
+ conn.close();
+ conn.close();
+ }
+
+ @Test
+ public void shouldBlockClientsWhenNotEnoughConnections() throws Exception {
+ int numConnectionsInPool = 1;
+ int numClients = 2;
+ RepositoryConnectionPool pool = new RepositoryConnectionPool(repositorySource);
+ pool.setCorePoolSize(numConnectionsInPool);
+ pool.setMaximumPoolSize(numConnectionsInPool);
+ RepositoryOperation.Factory<Integer> operationFactory = RepositorySourceLoadHarness.createMultipleLoadOperationFactory(10);
+ runLoadTest(env, pool, numClients, 100, TimeUnit.MILLISECONDS, operationFactory);
+ pool.shutdown();
+ pool.awaitTermination(4, TimeUnit.SECONDS);
+ }
+
+ @Test
+ public void shouldLimitClientsToRunSequentiallyWithOneConnectionInPool() throws Exception {
+ int numConnectionsInPool = 1;
+ int numClients = 3;
+ RepositoryConnectionPool pool = new RepositoryConnectionPool(repositorySource);
+ pool.setCorePoolSize(numConnectionsInPool);
+ pool.setMaximumPoolSize(numConnectionsInPool);
+ RepositoryOperation.Factory<Integer> operationFactory = RepositorySourceLoadHarness.createMultipleLoadOperationFactory(10);
+ runLoadTest(env, pool, numClients, 100, TimeUnit.MILLISECONDS, operationFactory);
+ pool.shutdown();
+ pool.awaitTermination(4, TimeUnit.SECONDS);
+ }
+
+ @Test
+ public void shouldClientsToRunConncurrentlyWithTwoConnectionsInPool() throws Exception {
+ int numConnectionsInPool = 2;
+ int numClients = 10;
+ RepositoryConnectionPool pool = new RepositoryConnectionPool(repositorySource);
+ pool.setCorePoolSize(numConnectionsInPool);
+ pool.setMaximumPoolSize(numConnectionsInPool);
+ RepositoryOperation.Factory<Integer> operationFactory = RepositorySourceLoadHarness.createMultipleLoadOperationFactory(10);
+ runLoadTest(env, pool, numClients, 100, TimeUnit.MILLISECONDS, operationFactory);
+ pool.shutdown();
+ pool.awaitTermination(4, TimeUnit.SECONDS);
+ }
+
+ @Ignore( "doesn't run on hudson" )
+ @Test
+ public void shouldClientsToRunConncurrentlyWithMultipleConnectionInPool() throws Exception {
+ int numConnectionsInPool = 10;
+ int numClients = 50;
+ RepositoryConnectionPool pool = new RepositoryConnectionPool(repositorySource);
+ pool.setCorePoolSize(numConnectionsInPool);
+ pool.setMaximumPoolSize(numConnectionsInPool);
+ RepositoryOperation.Factory<Integer> operationFactory = RepositorySourceLoadHarness.createMultipleLoadOperationFactory(20);
+ List<Future<Integer>> results = runLoadTest(env, pool, numClients, 200, TimeUnit.MILLISECONDS, operationFactory);
+ int total = 0;
+ for (Future<Integer> result : results) {
+ assertThat(result.isDone(), is(true));
+ if (result.isDone()) total += result.get();
+ }
+ assertThat(total, is(20 * numClients));
+ pool.shutdown();
+ pool.awaitTermination(4, TimeUnit.SECONDS);
+ }
+
+}
Property changes on: trunk/dna-spi/src/test/java/org/jboss/dna/spi/graph/connection/RepositoryConnectionPoolTest.java
___________________________________________________________________
Name: svn:mime-type
+ text/plain
Modified: trunk/dna-spi/src/test/java/org/jboss/dna/spi/graph/connection/SimpleRepositorySource.java
===================================================================
--- trunk/dna-spi/src/test/java/org/jboss/dna/spi/graph/connection/SimpleRepositorySource.java 2008-07-24 19:52:13 UTC (rev 369)
+++ trunk/dna-spi/src/test/java/org/jboss/dna/spi/graph/connection/SimpleRepositorySource.java 2008-07-25 19:37:40 UTC (rev 370)
@@ -28,6 +28,7 @@
import java.util.concurrent.TimeUnit;
import javax.naming.Reference;
import javax.transaction.xa.XAResource;
+import net.jcip.annotations.ThreadSafe;
import org.jboss.dna.spi.cache.CachePolicy;
import org.jboss.dna.spi.graph.InvalidPathException;
import org.jboss.dna.spi.graph.Name;
@@ -37,48 +38,27 @@
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 {
+@ThreadSafe
+public class SimpleRepositorySource extends AbstractRepositorySource {
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;
+ public SimpleRepositorySource() {
+ super();
}
/**
* {@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() {
@@ -118,20 +98,6 @@
/**
* {@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
@@ -156,6 +122,21 @@
return false;
}
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.jboss.dna.spi.graph.connection.AbstractRepositorySource#createConnection()
+ */
+ @Override
+ protected synchronized RepositoryConnection createConnection() throws RepositorySourceException {
+ String reposName = this.getRepositoryName();
+ SimpleRepository repository = SimpleRepository.get(reposName);
+ if (repository == null) {
+ throw new RepositorySourceException(this.getName(), "Unable to find repository \"" + reposName + "\"");
+ }
+ return new Connection(repository);
+ }
+
protected class Connection implements RepositoryConnection {
private RepositorySourceListener listener;
Modified: trunk/dna-spi/src/test/java/org/jboss/dna/spi/graph/connection/TimeDelayingRepositorySource.java
===================================================================
--- trunk/dna-spi/src/test/java/org/jboss/dna/spi/graph/connection/TimeDelayingRepositorySource.java 2008-07-24 19:52:13 UTC (rev 369)
+++ trunk/dna-spi/src/test/java/org/jboss/dna/spi/graph/connection/TimeDelayingRepositorySource.java 2008-07-25 19:37:40 UTC (rev 370)
@@ -36,16 +36,17 @@
import org.jboss.dna.spi.graph.commands.GraphCommand;
/**
+ * A simple {@link RepositorySource} that simulates an imaginary source with a built-in delay mechanism.
+ *
* @author Randall Hauch
*/
@ThreadSafe
-public class TimeDelayingRepositorySource implements RepositorySource {
+public class TimeDelayingRepositorySource extends AbstractRepositorySource {
/**
*/
private static final long serialVersionUID = -2756725117087437347L;
private String name;
- private final AtomicInteger retryLimit = new AtomicInteger(0);
private final AtomicInteger connectionsOpenedCount = new AtomicInteger(0);
private final AtomicInteger connectionsClosedCount = new AtomicInteger(0);
private final Set<Connection> openConnections = new CopyOnWriteArraySet<Connection>();
@@ -56,6 +57,7 @@
private CachePolicy defaultCachePolicy;
public TimeDelayingRepositorySource( String identifier ) {
+ super();
this.name = identifier;
}
@@ -73,20 +75,6 @@
this.name = name;
}
- /**
- * {@inheritDoc}
- */
- public int getRetryLimit() {
- return this.retryLimit.get();
- }
-
- /**
- * {@inheritDoc}
- */
- public void setRetryLimit( int limit ) {
- this.retryLimit.set(limit);
- }
-
public CachePolicy getDefaultCachePolicy() {
return defaultCachePolicy;
}
@@ -135,8 +123,11 @@
/**
* {@inheritDoc}
+ *
+ * @see org.jboss.dna.spi.graph.connection.AbstractRepositorySource#createConnection()
*/
- public RepositoryConnection getConnection() throws RepositorySourceException {
+ @Override
+ protected RepositoryConnection createConnection() throws RepositorySourceException {
int connectionNumber = this.connectionsOpenedCount.incrementAndGet();
String connectionName = "Connection " + connectionNumber;
XAResource xaResource = newXaResource(connectionName);
15 years, 9 months
DNA SVN: r369 - in trunk: connectors and 39 other directories.
by dna-commits@lists.jboss.org
Author: rhauch
Date: 2008-07-24 15:52:13 -0400 (Thu, 24 Jul 2008)
New Revision: 369
Added:
trunk/connectors/dna-connector-federation/
trunk/connectors/dna-connector-federation/.classpath
trunk/connectors/dna-connector-federation/.project
trunk/connectors/dna-connector-federation/pom.xml
trunk/connectors/dna-connector-federation/src/
trunk/connectors/dna-connector-federation/src/main/
trunk/connectors/dna-connector-federation/src/main/java/
trunk/connectors/dna-connector-federation/src/main/java/org/
trunk/connectors/dna-connector-federation/src/main/java/org/jboss/
trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/
trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/
trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/
trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/FederatedRepository.java
trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/FederatedRepositoryConfig.java
trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/FederatedRepositoryConnection.java
trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/FederatedRepositorySource.java
trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/FederationException.java
trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/FederationI18n.java
trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/Projection.java
trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/ProjectionParser.java
trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/contribution/
trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/contribution/AbstractContribution.java
trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/contribution/Contribution.java
trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/contribution/EmptyContribution.java
trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/contribution/NodeContribution.java
trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/contribution/PropertyContribution.java
trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/executor/
trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/executor/ActsOnProjectedPathCommand.java
trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/executor/FederatingCommandExecutor.java
trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/executor/ProjectedCopyBranchCommand.java
trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/executor/ProjectedCopyNodeCommand.java
trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/executor/ProjectedCreateNodeCommand.java
trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/executor/ProjectedDeleteBranchCommand.java
trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/executor/ProjectedGetChildrenCommand.java
trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/executor/ProjectedGetNodeCommand.java
trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/executor/ProjectedGetPropertiesCommand.java
trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/executor/ProjectedMoveBranchCommand.java
trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/executor/ProjectedRecordBranchCommand.java
trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/executor/ProjectedSetPropertiesCommand.java
trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/executor/SingleProjectionCommandExecutor.java
trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/merge/
trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/merge/BasicFederatedNode.java
trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/merge/BasicMergePlan.java
trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/merge/DoubleContributionMergePlan.java
trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/merge/FederatedNode.java
trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/merge/MergePlan.java
trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/merge/MultipleContributionMergePlan.java
trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/merge/SingleContributionMergePlan.java
trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/merge/TripleContributionMergePlan.java
trunk/connectors/dna-connector-federation/src/main/resources/
trunk/connectors/dna-connector-federation/src/main/resources/org/
trunk/connectors/dna-connector-federation/src/main/resources/org/jboss/
trunk/connectors/dna-connector-federation/src/main/resources/org/jboss/dna/
trunk/connectors/dna-connector-federation/src/main/resources/org/jboss/dna/connector/
trunk/connectors/dna-connector-federation/src/main/resources/org/jboss/dna/connector/federation/
trunk/connectors/dna-connector-federation/src/main/resources/org/jboss/dna/connector/federation/FederationI18n.properties
trunk/connectors/dna-connector-federation/src/test/
trunk/connectors/dna-connector-federation/src/test/java/
trunk/connectors/dna-connector-federation/src/test/java/org/
trunk/connectors/dna-connector-federation/src/test/java/org/jboss/
trunk/connectors/dna-connector-federation/src/test/java/org/jboss/dna/
trunk/connectors/dna-connector-federation/src/test/java/org/jboss/dna/connector/
trunk/connectors/dna-connector-federation/src/test/java/org/jboss/dna/connector/federation/
trunk/connectors/dna-connector-federation/src/test/java/org/jboss/dna/connector/federation/FederatedRepositoryConnectionTest.java
trunk/connectors/dna-connector-federation/src/test/java/org/jboss/dna/connector/federation/FederatedRepositorySourceTest.java
trunk/connectors/dna-connector-federation/src/test/java/org/jboss/dna/connector/federation/FederatedRepositoryTest.java
trunk/connectors/dna-connector-federation/src/test/java/org/jboss/dna/connector/federation/FederationI18nTest.java
trunk/connectors/dna-connector-federation/src/test/java/org/jboss/dna/connector/federation/ProjectionParserTest.java
trunk/connectors/dna-connector-federation/src/test/java/org/jboss/dna/connector/federation/ProjectionPathRuleTest.java
trunk/connectors/dna-connector-federation/src/test/java/org/jboss/dna/connector/federation/ProjectionTest.java
trunk/connectors/dna-connector-federation/src/test/java/org/jboss/dna/connector/federation/merge/
trunk/connectors/dna-connector-federation/src/test/java/org/jboss/dna/connector/federation/merge/BasicFederatedNodeTest.java
trunk/connectors/dna-connector-federation/src/test/resources/
trunk/dna-repository/src/main/java/org/jboss/dna/repository/RepositoryService.java
trunk/dna-repository/src/main/java/org/jboss/dna/repository/RepositorySourceManager.java
trunk/dna-repository/src/test/java/org/jboss/dna/repository/RepositoryServiceTest.java
trunk/dna-spi/src/main/java/org/jboss/dna/spi/ExecutionContextFactory.java
trunk/dna-spi/src/main/java/org/jboss/dna/spi/graph/commands/executor/DelegatingCommandExecutor.java
trunk/dna-spi/src/main/java/org/jboss/dna/spi/graph/commands/executor/LoggingCommandExecutor.java
trunk/dna-spi/src/main/java/org/jboss/dna/spi/graph/commands/executor/NoOpCommandExecutor.java
trunk/dna-spi/src/test/java/org/jboss/dna/spi/graph/connection/SimpleRepository.java
trunk/dna-spi/src/test/java/org/jboss/dna/spi/graph/connection/SimpleRepositorySource.java
Removed:
trunk/dna-repository/src/main/java/org/jboss/dna/repository/federation/
trunk/dna-repository/src/test/java/org/jboss/dna/repository/federation/
Modified:
trunk/dna-repository/pom.xml
trunk/dna-repository/src/main/java/org/jboss/dna/repository/RepositoryI18n.java
trunk/dna-repository/src/main/resources/org/jboss/dna/repository/RepositoryI18n.properties
trunk/dna-spi/src/main/java/org/jboss/dna/spi/SpiI18n.java
trunk/dna-spi/src/main/java/org/jboss/dna/spi/graph/Path.java
trunk/dna-spi/src/main/java/org/jboss/dna/spi/graph/PathFactory.java
trunk/dna-spi/src/main/java/org/jboss/dna/spi/graph/commands/executor/AbstractCommandExecutor.java
trunk/dna-spi/src/main/java/org/jboss/dna/spi/graph/commands/executor/CommandExecutor.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/commands/impl/BasicCopyNodeCommand.java
trunk/dna-spi/src/main/java/org/jboss/dna/spi/graph/commands/impl/BasicCreateNodeCommand.java
trunk/dna-spi/src/main/java/org/jboss/dna/spi/graph/commands/impl/BasicDeleteBranchCommand.java
trunk/dna-spi/src/main/java/org/jboss/dna/spi/graph/commands/impl/BasicGetChildrenCommand.java
trunk/dna-spi/src/main/java/org/jboss/dna/spi/graph/commands/impl/BasicGetNodeCommand.java
trunk/dna-spi/src/main/java/org/jboss/dna/spi/graph/commands/impl/BasicGetPropertiesCommand.java
trunk/dna-spi/src/main/java/org/jboss/dna/spi/graph/commands/impl/BasicMoveBranchCommand.java
trunk/dna-spi/src/main/java/org/jboss/dna/spi/graph/commands/impl/BasicRecordBranchCommand.java
trunk/dna-spi/src/main/java/org/jboss/dna/spi/graph/commands/impl/BasicSetPropertiesCommand.java
trunk/dna-spi/src/main/java/org/jboss/dna/spi/graph/impl/BasicPath.java
trunk/dna-spi/src/main/java/org/jboss/dna/spi/graph/impl/PathValueFactory.java
trunk/dna-spi/src/main/resources/org/jboss/dna/spi/SpiI18n.properties
trunk/dna-spi/src/test/java/org/jboss/dna/spi/graph/commands/executor/AbstractCommandExecutorTest.java
trunk/dna-spi/src/test/java/org/jboss/dna/spi/graph/impl/BasicPathTest.java
trunk/pom.xml
Log:
DNA-115 - Moved the federating functionality into a separate connector and out of 'dna-repository'. This cleans up the 'dna-repository' project and also makes it easier to assemble and (re)use the federation capability in different parts of the system.
Property changes on: trunk/connectors/dna-connector-federation
___________________________________________________________________
Name: svn:ignore
+ target
Added: trunk/connectors/dna-connector-federation/.classpath
===================================================================
--- trunk/connectors/dna-connector-federation/.classpath (rev 0)
+++ trunk/connectors/dna-connector-federation/.classpath 2008-07-24 19:52:13 UTC (rev 369)
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+ <classpathentry kind="src" path="src/main/java"/>
+ <classpathentry kind="src" path="src/main/resources"/>
+ <classpathentry kind="src" output="target/test-classes" path="src/test/java"/>
+ <classpathentry kind="src" output="target/test-classes" path="src/test/resources"/>
+ <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
+ <classpathentry kind="con" path="org.maven.ide.eclipse.MAVEN2_CLASSPATH_CONTAINER"/>
+ <classpathentry kind="output" path="target/classes"/>
+</classpath>
Added: trunk/connectors/dna-connector-federation/.project
===================================================================
--- trunk/connectors/dna-connector-federation/.project (rev 0)
+++ trunk/connectors/dna-connector-federation/.project 2008-07-24 19:52:13 UTC (rev 369)
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>dna-connector-federation</name>
+ <comment></comment>
+ <projects>
+ </projects>
+ <buildSpec>
+ <buildCommand>
+ <name>org.eclipse.jdt.core.javabuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.maven.ide.eclipse.maven2Builder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ </buildSpec>
+ <natures>
+ <nature>org.eclipse.jdt.core.javanature</nature>
+ <nature>org.maven.ide.eclipse.maven2Nature</nature>
+ </natures>
+</projectDescription>
Added: trunk/connectors/dna-connector-federation/pom.xml
===================================================================
--- trunk/connectors/dna-connector-federation/pom.xml (rev 0)
+++ trunk/connectors/dna-connector-federation/pom.xml 2008-07-24 19:52:13 UTC (rev 369)
@@ -0,0 +1,92 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.jboss.dna</groupId>
+ <artifactId>dna</artifactId>
+ <version>0.2-SNAPSHOT</version>
+ <relativePath>../..</relativePath>
+ </parent>
+ <!-- The groupId and version values are inherited from parent -->
+ <artifactId>dna-connector-federation</artifactId>
+ <packaging>jar</packaging>
+ <name>JBoss DNA Federation Connector</name>
+ <description>JBoss DNA Connector that federates content from multiple connectors.</description>
+ <url>http://labs.jboss.org/dna</url>
+
+ <properties>
+ <dna-version>0.2-SNAPSHOT</dna-version>
+ </properties>
+ <!--
+ Define the dependencies. Note that all version and scopes default to those
+ defined in the dependencyManagement section of the parent pom.
+ -->
+ <dependencies>
+ <!--
+ Common
+ -->
+ <dependency>
+ <groupId>org.jboss.dna</groupId>
+ <artifactId>dna-common</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.jboss.dna</groupId>
+ <artifactId>dna-spi</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.jboss.dna</groupId>
+ <artifactId>dna-common</artifactId>
+ <version>${dna-version}</version>
+ <type>test-jar</type>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.jboss.dna</groupId>
+ <artifactId>dna-spi</artifactId>
+ <version>${dna-version}</version>
+ <type>test-jar</type>
+ <scope>test</scope>
+ </dependency>
+ <!--
+ Testing (note the scope)
+ -->
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.mockito</groupId>
+ <artifactId>mockito-all</artifactId>
+ </dependency>
+ <!--
+ Logging (require SLF4J API for compiling, but use Log4J and its SLF4J binding for testing)
+ -->
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-api</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-log4j12</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>log4j</groupId>
+ <artifactId>log4j</artifactId>
+ </dependency>
+ <!--
+ Java Concurrency in Practice annotations
+ -->
+ <dependency>
+ <groupId>net.jcip</groupId>
+ <artifactId>jcip-annotations</artifactId>
+ </dependency>
+ </dependencies>
+ <reporting>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-surefire-report-plugin</artifactId>
+ </plugin>
+ </plugins>
+ </reporting>
+</project>
\ No newline at end of file
Added: trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/FederatedRepository.java
===================================================================
--- trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/FederatedRepository.java (rev 0)
+++ trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/FederatedRepository.java 2008-07-24 19:52:13 UTC (rev 369)
@@ -0,0 +1,259 @@
+/*
+ * 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.connector.federation;
+
+import java.util.List;
+import java.util.concurrent.CopyOnWriteArrayList;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.atomic.AtomicInteger;
+import net.jcip.annotations.ThreadSafe;
+import org.jboss.dna.common.util.ArgCheck;
+import org.jboss.dna.connector.federation.executor.FederatingCommandExecutor;
+import org.jboss.dna.spi.graph.commands.executor.CommandExecutor;
+import org.jboss.dna.spi.graph.connection.ExecutionEnvironment;
+import org.jboss.dna.spi.graph.connection.RepositoryConnection;
+import org.jboss.dna.spi.graph.connection.RepositoryConnectionFactories;
+import org.jboss.dna.spi.graph.connection.RepositorySource;
+import org.jboss.dna.spi.graph.connection.RepositorySourceListener;
+
+/**
+ * The component 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
+ */
+@ThreadSafe
+public class FederatedRepository {
+
+ private final ExecutionEnvironment env;
+ private final RepositoryConnectionFactories connectionFactories;
+ private FederatedRepositoryConfig config;
+ private final AtomicInteger openExecutors = new AtomicInteger(0);
+ private final CountDownLatch shutdownLatch = new CountDownLatch(1);
+ private final AtomicBoolean shutdownRequested = new AtomicBoolean(false);
+ private final CopyOnWriteArrayList<RepositorySourceListener> listeners = new CopyOnWriteArrayList<RepositorySourceListener>();
+
+ /**
+ * Create a federated repository instance.
+ *
+ * @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( ExecutionEnvironment env,
+ RepositoryConnectionFactories connectionFactories,
+ FederatedRepositoryConfig config ) {
+ ArgCheck.isNotNull(connectionFactories, "connectionFactories");
+ ArgCheck.isNotNull(env, "env");
+ ArgCheck.isNotNull(config, "config");
+ this.env = env;
+ this.connectionFactories = connectionFactories;
+ this.config = config;
+ }
+
+ /**
+ * Get the name of this repository
+ *
+ * @return name
+ */
+ public String getName() {
+ return this.config.getName();
+ }
+
+ /**
+ * @return the execution environment
+ */
+ public ExecutionEnvironment getExecutionEnvironment() {
+ return env;
+ }
+
+ /**
+ * @return connectionFactories
+ */
+ protected RepositoryConnectionFactories getConnectionFactories() {
+ return connectionFactories;
+ }
+
+ /**
+ * Utility method called by the administrator.
+ */
+ public synchronized void start() {
+ // Do not establish connections to the sources; these will be established as needed
+ }
+
+ /**
+ * Return true if this federated repository is running and ready for connections.
+ *
+ * @return true if running, or false otherwise
+ */
+ public boolean isRunning() {
+ return this.shutdownRequested.get() != true;
+ }
+
+ /**
+ * Utility method called by the administrator.
+ */
+ public synchronized void shutdown() {
+ this.shutdownRequested.set(true);
+ if (this.openExecutors.get() <= 0) shutdownLatch.countDown();
+ }
+
+ /**
+ * Utility method called by the administrator.
+ *
+ * @param timeout
+ * @param unit
+ * @return true if all connections open at the time this method is called were {@link RepositoryConnection#close() closed} in
+ * the supplied time, or false if the timeout occurred before all the connections were closed
+ * @throws InterruptedException
+ */
+ public boolean awaitTermination( long timeout,
+ TimeUnit unit ) throws InterruptedException {
+ // Await until all connections have been closed, or until the timeout occurs
+ return shutdownLatch.await(timeout, unit);
+ }
+
+ /**
+ * Return true if this federated repository has completed its termination and no longer has any open connections.
+ *
+ * @return true if terminated, or false otherwise
+ */
+ public boolean isTerminated() {
+ return this.openExecutors.get() != 0;
+ }
+
+ /**
+ * 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.
+ *
+ * @param listener the new listener
+ * @return true if the listener was added, or false if the listener was not added (if reference is null, or if non-null
+ * listener is already an existing listener)
+ */
+ public boolean addListener( RepositorySourceListener listener ) {
+ if (listener == null) return false;
+ return this.listeners.addIfAbsent(listener);
+ }
+
+ /**
+ * Remove the supplied listener. This method does nothing if the supplied listener is null.
+ * <p>
+ * This method can safely be called while the federation repository is in use.
+ * </p>
+ *
+ * @param listener the listener to remove
+ * @return true if the listener was removed, or false if the listener was not registered
+ */
+ public boolean removeListener( RepositorySourceListener listener ) {
+ if (listener == null) return false;
+ return this.listeners.remove(listener);
+ }
+
+ /**
+ * Get the list of listeners, which is the actual list used by the repository.
+ *
+ * @return the listeners
+ */
+ public List<RepositorySourceListener> getListeners() {
+ return this.listeners;
+ }
+
+ /**
+ * Authenticate the supplied username with the supplied credentials, and return whether authentication was successful.
+ *
+ * @param source the {@link RepositorySource} that should be affiliated with the resulting connection
+ * @param username the username
+ * @param credentials the credentials
+ * @return the repository connection if authentication succeeded, or null otherwise
+ */
+ public RepositoryConnection createConnection( RepositorySource source,
+ String username,
+ Object credentials ) {
+ return new FederatedRepositoryConnection(this, source.getName());
+ }
+
+ /**
+ * 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 repository's configuration at the time this method is called.
+ */
+ public FederatedRepositoryConfig getConfiguration() {
+ return config;
+ }
+
+ /**
+ * 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 config the new configuration
+ * @throws IllegalArgumentException if the configuration is null
+ */
+ public void setConfiguration( FederatedRepositoryConfig config ) {
+ ArgCheck.isNotNull(config, "config");
+ this.config = config;
+ }
+
+ /**
+ * Called by
+ * {@link FederatedRepositoryConnection#execute(ExecutionEnvironment, org.jboss.dna.spi.graph.commands.GraphCommand...)}.
+ *
+ * @param env the execution environment in which the executor will be run; may not be null
+ * @param sourceName the name of the {@link RepositorySource} that is making use of this executor; may not be null or empty
+ * @return the executor
+ */
+ protected CommandExecutor getExecutor( ExecutionEnvironment env,
+ String sourceName ) {
+ FederatedRepositoryConfig config = this.getConfiguration();
+ return new FederatingCommandExecutor(env, sourceName, config.getCacheProjection(), config.getSourceProjections(),
+ getConnectionFactories());
+ }
+
+ /**
+ * Called by {@link FederatedRepositoryConnection#FederatedRepositoryConnection(FederatedRepository, String)}.
+ *
+ * @param connection the connection being opened
+ */
+ /*package*/void register( FederatedRepositoryConnection connection ) {
+ openExecutors.incrementAndGet();
+ }
+
+ /**
+ * Called by {@link FederatedRepositoryConnection#close()}.
+ *
+ * @param connection the connection being closed
+ */
+ /*package*/void unregister( FederatedRepositoryConnection connection ) {
+ if (openExecutors.decrementAndGet() <= 0 && shutdownRequested.get()) {
+ // Last connection, so turn out the lights ...
+ shutdownLatch.countDown();
+ }
+ }
+
+}
Added: trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/FederatedRepositoryConfig.java
===================================================================
--- trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/FederatedRepositoryConfig.java (rev 0)
+++ trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/FederatedRepositoryConfig.java 2008-07-24 19:52:13 UTC (rev 369)
@@ -0,0 +1,177 @@
+/*
+ * 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.connector.federation;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Iterator;
+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 federated repository. The configuration defines, among other things, the set of
+ * {@link #getSourceProjections() source projections} 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
+ */
+@Immutable
+public class FederatedRepositoryConfig implements Comparable<FederatedRepositoryConfig> {
+
+ private final Projection cacheProjection;
+ private final List<Projection> sourceProjections;
+ private final Problems problems;
+ private final String name;
+ private final CachePolicy defaultCachePolicy;
+
+ /**
+ * Create a federated repository instance.
+ *
+ * @param repositoryName the name of the repository
+ * @param cacheProjection the projection used for the cache; may not be null
+ * @param sourceProjections the source projections; 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,
+ Projection cacheProjection,
+ Iterable<Projection> sourceProjections,
+ CachePolicy defaultCachePolicy ) {
+ ArgCheck.isNotEmpty(repositoryName, "repositoryName");
+ ArgCheck.isNotNull(cacheProjection, "cacheProjection");
+ this.name = repositoryName;
+ this.problems = new ThreadSafeProblems();
+ this.defaultCachePolicy = defaultCachePolicy;
+ this.cacheProjection = cacheProjection;
+ List<Projection> projectionList = new ArrayList<Projection>();
+ for (Projection projection : sourceProjections) {
+ if (projection == null) continue;
+ if (!projectionList.contains(projection)) {
+ projectionList.add(projection);
+ }
+ }
+ this.sourceProjections = Collections.unmodifiableList(projectionList);
+ ArgCheck.isNotEmpty(this.sourceProjections, "sourceProjections");
+ }
+
+ /**
+ * 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;
+ }
+
+ /**
+ * Get the projection that defines the cache for this repository. This projection does not exist in the
+ * {@link #getSourceProjections() list of source projections}.
+ *
+ * @return the region used for caching; never null
+ */
+ public Projection getCacheProjection() {
+ return cacheProjection;
+ }
+
+ /**
+ * Return the unmodifiable list of source projections.
+ *
+ * @return the source projections; never null and never empty
+ */
+ public List<Projection> getSourceProjections() {
+ return sourceProjections;
+ }
+
+ /**
+ * Get the default cache policy for the repository with the supplied name
+ *
+ * @return the default cache policy
+ */
+ public CachePolicy getDefaultCachePolicy() {
+ return defaultCachePolicy;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see java.lang.Object#hashCode()
+ */
+ @Override
+ public int hashCode() {
+ return this.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 FederatedRepositoryConfig) {
+ FederatedRepositoryConfig that = (FederatedRepositoryConfig)obj;
+ if (!this.getName().equals(that.getName())) return false;
+ if (!this.getCacheProjection().equals(that.getCacheProjection())) return false;
+ if (!this.getSourceProjections().equals(that.getSourceProjections())) return false;
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see java.lang.Comparable#compareTo(java.lang.Object)
+ */
+ public int compareTo( FederatedRepositoryConfig that ) {
+ if (that == this) return 0;
+ int diff = this.getName().compareTo(that.getName());
+ if (diff != 0) return diff;
+ diff = this.getCacheProjection().compareTo(that.getCacheProjection());
+ if (diff != 0) return diff;
+ Iterator<Projection> thisIter = this.getSourceProjections().iterator();
+ Iterator<Projection> thatIter = that.getSourceProjections().iterator();
+ while (thisIter.hasNext() && thatIter.hasNext()) {
+ diff = thisIter.next().compareTo(thatIter.next());
+ if (diff != 0) return diff;
+ }
+ if (thisIter.hasNext()) return 1;
+ if (thatIter.hasNext()) return -1;
+ return 0;
+ }
+}
Added: trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/FederatedRepositoryConnection.java
===================================================================
--- trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/FederatedRepositoryConnection.java (rev 0)
+++ trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/FederatedRepositoryConnection.java 2008-07-24 19:52:13 UTC (rev 369)
@@ -0,0 +1,139 @@
+/*
+ * 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.connector.federation;
+
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicReference;
+import javax.transaction.xa.XAResource;
+import net.jcip.annotations.ThreadSafe;
+import org.jboss.dna.spi.cache.CachePolicy;
+import org.jboss.dna.spi.graph.commands.GraphCommand;
+import org.jboss.dna.spi.graph.commands.executor.CommandExecutor;
+import org.jboss.dna.spi.graph.connection.ExecutionEnvironment;
+import org.jboss.dna.spi.graph.connection.RepositoryConnection;
+import org.jboss.dna.spi.graph.connection.RepositorySourceException;
+import org.jboss.dna.spi.graph.connection.RepositorySourceListener;
+
+/**
+ * @author Randall Hauch
+ */
+@ThreadSafe
+public class FederatedRepositoryConnection implements RepositoryConnection {
+
+ protected static final RepositorySourceListener NO_OP_LISTENER = new RepositorySourceListener() {
+ public void notify( String sourceName,
+ Object... events ) {
+ // do nothing
+ }
+ };
+
+ private final FederatedRepository repository;
+ private final String sourceName;
+ private final AtomicReference<RepositorySourceListener> listener;
+
+ protected FederatedRepositoryConnection( FederatedRepository repository,
+ String sourceName ) {
+ assert sourceName != null;
+ assert repository != null;
+ this.sourceName = sourceName;
+ this.repository = repository;
+ this.listener = new AtomicReference<RepositorySourceListener>(NO_OP_LISTENER);
+ this.repository.register(this);
+ }
+
+ /**
+ * @return repository
+ */
+ protected FederatedRepository getRepository() {
+ return this.repository;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public String getSourceName() {
+ return this.sourceName;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public CachePolicy getDefaultCachePolicy() {
+ return this.repository.getConfiguration().getDefaultCachePolicy();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public XAResource getXAResource() {
+ return null;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void setListener( RepositorySourceListener listener ) {
+ if (listener == null) listener = NO_OP_LISTENER;
+ RepositorySourceListener oldListener = this.listener.getAndSet(listener);
+ this.repository.addListener(listener);
+ if (oldListener != NO_OP_LISTENER) {
+ this.repository.removeListener(oldListener);
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean ping( long time,
+ TimeUnit unit ) {
+ return this.repository.isRunning();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void execute( ExecutionEnvironment env,
+ GraphCommand... commands ) throws RepositorySourceException, InterruptedException {
+ if (!this.repository.isRunning()) {
+ throw new RepositorySourceException(FederationI18n.repositoryHasBeenShutDown.text(this.repository.getName()));
+ }
+ if (commands == null || commands.length == 0) return;
+
+ CommandExecutor executor = this.repository.getExecutor(env, sourceName);
+ assert executor != null;
+ for (GraphCommand command : commands) {
+ executor.execute(command);
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void close() {
+ try {
+ this.repository.removeListener(this.listener.get());
+ } finally {
+ this.repository.unregister(this);
+ }
+ }
+
+}
Added: trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/FederatedRepositorySource.java
===================================================================
--- trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/FederatedRepositorySource.java (rev 0)
+++ trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/FederatedRepositorySource.java 2008-07-24 19:52:13 UTC (rev 369)
@@ -0,0 +1,961 @@
+/*
+ * 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.connector.federation;
+
+import java.util.Collections;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.Hashtable;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import javax.naming.Context;
+import javax.naming.InitialContext;
+import javax.naming.RefAddr;
+import javax.naming.Reference;
+import javax.naming.StringRefAddr;
+import javax.naming.spi.ObjectFactory;
+import javax.security.auth.callback.Callback;
+import javax.security.auth.callback.CallbackHandler;
+import javax.security.auth.callback.NameCallback;
+import javax.security.auth.callback.PasswordCallback;
+import javax.security.auth.login.LoginException;
+import net.jcip.annotations.ThreadSafe;
+import org.jboss.dna.common.collection.Problems;
+import org.jboss.dna.common.collection.SimpleProblems;
+import org.jboss.dna.common.i18n.I18n;
+import org.jboss.dna.common.util.ArgCheck;
+import org.jboss.dna.common.util.Logger;
+import org.jboss.dna.common.util.StringUtil;
+import org.jboss.dna.connector.federation.executor.FederatingCommandExecutor;
+import org.jboss.dna.connector.federation.executor.SingleProjectionCommandExecutor;
+import org.jboss.dna.spi.ExecutionContextFactory;
+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;
+import org.jboss.dna.spi.graph.PathFactory;
+import org.jboss.dna.spi.graph.Property;
+import org.jboss.dna.spi.graph.ValueFactories;
+import org.jboss.dna.spi.graph.ValueFactory;
+import org.jboss.dna.spi.graph.commands.GraphCommand;
+import org.jboss.dna.spi.graph.commands.executor.CommandExecutor;
+import org.jboss.dna.spi.graph.commands.executor.LoggingCommandExecutor;
+import org.jboss.dna.spi.graph.commands.executor.NoOpCommandExecutor;
+import org.jboss.dna.spi.graph.commands.impl.BasicCompositeCommand;
+import org.jboss.dna.spi.graph.commands.impl.BasicGetChildrenCommand;
+import org.jboss.dna.spi.graph.commands.impl.BasicGetNodeCommand;
+import org.jboss.dna.spi.graph.connection.ExecutionEnvironment;
+import org.jboss.dna.spi.graph.connection.RepositoryConnection;
+import org.jboss.dna.spi.graph.connection.RepositoryConnectionFactories;
+import org.jboss.dna.spi.graph.connection.RepositorySource;
+import org.jboss.dna.spi.graph.connection.RepositorySourceException;
+
+/**
+ * @author Randall Hauch
+ */
+@ThreadSafe
+public class FederatedRepositorySource implements RepositorySource {
+
+ /**
+ */
+ private static final long serialVersionUID = 7587346948013486977L;
+
+ public static final int DEFAULT_RETRY_LIMIT = 0;
+ public static final String[] DEFAULT_CONFIGURATION_SOURCE_PROJECTION_RULES = {"/dna:system => /"};
+
+ protected static final String REPOSITORY_NAME = "repositoryName";
+ protected static final String SOURCE_NAME = "sourceName";
+ protected static final String USERNAME = "username";
+ protected static final String PASSWORD = "password";
+ protected static final String CONFIGURATION_SOURCE_NAME = "configurationSourceName";
+ protected static final String CONFIGURATION_SOURCE_PROJECTION_RULES = "configurationSourceProjectionRules";
+ protected static final String CONNECTION_FACTORIES_JNDI_NAME = "connectionFactoriesJndiName";
+ protected static final String EXECUTION_CONTEXT_FACTORY_JNDI_NAME = "executionContextFacotryJndiName";
+ protected static final String REPOSITORY_JNDI_NAME = "repositoryJndiName";
+ protected static final String SECURITY_DOMAIN = "securityDomain";
+ protected static final String RETRY_LIMIT = "retryLimit";
+
+ protected static final String PROJECTION_RULES_CONFIG_PROPERTY_NAME = "dna:projectionRules";
+ protected static final String CACHE_POLICY_TIME_TO_EXPIRE_CONFIG_PROPERTY_NAME = "dna:timeToExpire";
+ protected static final String CACHE_POLICY_TIME_TO_CACHE_CONFIG_PROPERTY_NAME = "dna:timeToCache";
+
+ private String repositoryName;
+ private String sourceName;
+ private String username;
+ private String password;
+ private String configurationSourceName;
+ private String[] configurationSourceProjectionRules = DEFAULT_CONFIGURATION_SOURCE_PROJECTION_RULES;
+ private String connectionFactoriesJndiName;
+ private String executionContextFactoryJndiName;
+ private String securityDomain;
+ private String repositoryJndiName;
+ private int retryLimit = DEFAULT_RETRY_LIMIT;
+ private transient FederatedRepository repository;
+ private transient Context jndiContext;
+
+ /**
+ * Create a new instance of the source, which must still be properly initialized with a {@link #setRepositoryName(String)
+ * repository name}.
+ */
+ public FederatedRepositorySource() {
+ }
+
+ /**
+ * Create a new instance of the source with the required repository name and federation service.
+ *
+ * @param repositoryName the repository name
+ * @throws IllegalArgumentException if the federation service is null or the repository name is null or blank
+ */
+ public FederatedRepositorySource( String repositoryName ) {
+ ArgCheck.isNotNull(repositoryName, "repositoryName");
+ this.repositoryName = repositoryName;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public int getRetryLimit() {
+ return this.retryLimit;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void setRetryLimit( int limit ) {
+ this.retryLimit = limit > 0 ? limit : 0;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public synchronized RepositoryConnection getConnection() throws RepositorySourceException {
+ if (getName() == null) {
+ throw new RepositorySourceException(FederationI18n.propertyIsRequired.text("name"));
+ }
+ if (getExecutionContextFactoryJndiName() == null) {
+ throw new RepositorySourceException(FederationI18n.propertyIsRequired.text("execution context factory JNDI name"));
+ }
+ if (getSecurityDomain() == null) {
+ throw new RepositorySourceException(FederationI18n.propertyIsRequired.text("security domain"));
+ }
+ if (getConnectionFactoriesJndiName() == null) {
+ throw new RepositorySourceException(FederationI18n.propertyIsRequired.text("connection factories JNDI name"));
+ }
+ // Find the repository ...
+ FederatedRepository repository = getRepository();
+ // Authenticate the user ...
+ String username = this.username;
+ Object credentials = this.password;
+ RepositoryConnection connection = repository.createConnection(this, username, credentials);
+ if (connection == null) {
+ I18n msg = FederationI18n.unableToAuthenticateConnectionToFederatedRepository;
+ throw new RepositorySourceException(msg.text(this.repositoryName, username));
+ }
+ // Return the new connection ...
+ return connection;
+ }
+
+ /**
+ * Get the {@link FederatedRepository} instance that this source is using. This method uses the following logic:
+ * <ol>
+ * <li>If a {@link FederatedRepository} already was obtained from a prior call, the same instance is returned.</li>
+ * <li>A {@link FederatedRepository} is created using a {@link FederatedRepositoryConfig} is created from this instance's
+ * properties and {@link ExecutionEnvironment} and {@link RepositoryConnectionFactories} instances obtained from JNDI.</li>
+ * <li></li>
+ * <li></li>
+ * </ol>
+ *
+ * @return the federated repository instance
+ * @throws RepositorySourceException
+ */
+ protected synchronized FederatedRepository getRepository() throws RepositorySourceException {
+ if (repository == null) {
+ String jndiName = this.getRepositoryJndiName();
+ Context context = getContext();
+ if (jndiName != null && jndiName.trim().length() != 0) {
+ // Look for an existing repository in JNDI ...
+ try {
+ if (context == null) context = new InitialContext();
+ repository = (FederatedRepository)context.lookup(jndiName);
+ } catch (Throwable err) {
+ I18n msg = FederationI18n.unableToFindFederatedRepositoryInJndi;
+ throw new RepositorySourceException(msg.text(this.sourceName, jndiName), err);
+ }
+ }
+
+ if (repository == null) {
+ // Find in JNDI the repository connection factories and the environment ...
+ ExecutionEnvironment env = getExecutionEnvironment();
+ RepositoryConnectionFactories factories = getRepositoryConnectionFactories();
+ // And create the configuration and the repository ...
+ FederatedRepositoryConfig config = getRepositoryConfiguration(env, factories);
+ repository = new FederatedRepository(env, factories, config);
+ }
+ }
+ return repository;
+ }
+
+ protected ExecutionEnvironment getExecutionEnvironment() {
+ ExecutionContextFactory factory = null;
+ Context context = getContext();
+ String jndiName = getExecutionContextFactoryJndiName();
+ if (jndiName != null && jndiName.trim().length() != 0) {
+ try {
+ if (context == null) context = new InitialContext();
+ factory = (ExecutionContextFactory)context.lookup(jndiName);
+ } catch (Throwable err) {
+ I18n msg = FederationI18n.unableToFindExecutionContextFactoryInJndi;
+ throw new RepositorySourceException(msg.text(this.sourceName, jndiName), err);
+ }
+ }
+ if (factory == null) {
+ I18n msg = FederationI18n.unableToFindExecutionContextFactoryInJndi;
+ throw new RepositorySourceException(msg.text(this.sourceName, jndiName));
+ }
+ String securityDomain = getSecurityDomain();
+ CallbackHandler handler = createCallbackHandler();
+ try {
+ return factory.create(securityDomain, handler);
+ } catch (LoginException e) {
+ I18n msg = FederationI18n.unableToCreateExecutionContext;
+ throw new RepositorySourceException(msg.text(this.sourceName, jndiName, securityDomain), e);
+ }
+ }
+
+ protected RepositoryConnectionFactories getRepositoryConnectionFactories() {
+ RepositoryConnectionFactories factories = null;
+ Context context = getContext();
+ String jndiName = getConnectionFactoriesJndiName();
+ if (jndiName != null && jndiName.trim().length() != 0) {
+ try {
+ if (context == null) context = new InitialContext();
+ factories = (RepositoryConnectionFactories)context.lookup(jndiName);
+ } catch (Throwable err) {
+ I18n msg = FederationI18n.unableToFindRepositoryConnectionFactoriesInJndi;
+ throw new RepositorySourceException(msg.text(this.sourceName, jndiName), err);
+ }
+ }
+ if (factories == null) {
+ I18n msg = FederationI18n.noRepositoryConnectionFactories;
+ throw new RepositorySourceException(msg.text(this.repositoryName));
+ }
+ return factories;
+ }
+
+ protected CallbackHandler createCallbackHandler() {
+ return new CallbackHandler() {
+ public void handle( Callback[] callbacks ) {
+ for (Callback callback : callbacks) {
+ if (callback instanceof NameCallback) {
+ NameCallback nameCallback = (NameCallback)callback;
+ nameCallback.setName(FederatedRepositorySource.this.getUsername());
+ }
+ if (callback instanceof PasswordCallback) {
+ PasswordCallback passwordCallback = (PasswordCallback)callback;
+ passwordCallback.setPassword(FederatedRepositorySource.this.getPassword().toCharArray());
+ }
+ }
+ }
+ };
+ }
+
+ protected Context getContext() {
+ return this.jndiContext;
+ }
+
+ protected synchronized void setContext( Context context ) {
+ this.jndiContext = context;
+ }
+
+ /**
+ * Create a {@link FederatedRepositoryConfig} instance from the current properties of this instance. This method does
+ * <i>not</i> modify the state of this instance.
+ *
+ * @param env the execution environment that should be used to read the configuration; may not be null
+ * @param factories the factories from which can be obtained the RepositoryConnectionFactory instances for each name source;
+ * may not be null
+ * @return a configuration reflecting the current state of this instance
+ */
+ protected synchronized FederatedRepositoryConfig getRepositoryConfiguration( ExecutionEnvironment env,
+ RepositoryConnectionFactories factories ) {
+ Problems problems = new SimpleProblems();
+ ValueFactories valueFactories = env.getValueFactories();
+ PathFactory pathFactory = valueFactories.getPathFactory();
+ NameFactory nameFactory = valueFactories.getNameFactory();
+ ValueFactory<Long> longFactory = valueFactories.getLongFactory();
+
+ // Create the configuration projection ...
+ ProjectionParser projectionParser = ProjectionParser.getInstance();
+ Projection.Rule[] rules = projectionParser.rulesFromStrings(env, this.getConfigurationSourceProjectionRules());
+ Projection configurationProjection = new Projection(this.getConfigurationSourceName(), rules);
+
+ // Create a federating command executor to execute the commands and merge the results into a single set of
+ // commands.
+ final String configurationSourceName = configurationProjection.getSourceName();
+ List<Projection> projections = Collections.singletonList(configurationProjection);
+ CommandExecutor executor = null;
+ if (configurationProjection.getRules().size() == 1) {
+ // There is just a single projection for the configuration repository, so just use an executor that
+ // translates the paths using the projection
+ executor = new SingleProjectionCommandExecutor(env, configurationSourceName, configurationProjection, factories);
+ } else if (configurationProjection.getRules().size() == 0) {
+ // There is no projection for the configuration repository, so just use a no-op executor
+ executor = new NoOpCommandExecutor(env, configurationSourceName);
+ } else {
+ // The configuration repository has more than one projection, so we need to merge the results
+ executor = new FederatingCommandExecutor(env, configurationSourceName, null, projections, factories);
+ }
+ // Wrap the executor with a logging executor ...
+ executor = new LoggingCommandExecutor(executor, Logger.getLogger(getClass()), Logger.Level.INFO);
+
+ // The configuration projection (via "executor") will convert this path into a path that exists in the configuration
+ // repository
+ Path configNode = pathFactory.create("/dna:system/dna:federation");
+
+ try {
+ // Get the repository node ...
+ BasicGetNodeCommand getRepository = new BasicGetNodeCommand(configNode);
+ executor.execute(getRepository);
+ if (getRepository.hasError()) {
+ throw new FederationException(FederationI18n.federatedRepositoryCannotBeFound.text(repositoryName));
+ }
+
+ // Add a command to get the projection defining the cache ...
+ Path pathToCacheRegion = pathFactory.create(configNode, nameFactory.create("dna:cache"));
+ BasicGetNodeCommand getCacheRegion = new BasicGetNodeCommand(pathToCacheRegion);
+ executor.execute(getCacheRegion);
+ Projection cacheProjection = createProjection(env,
+ projectionParser,
+ getCacheRegion.getPath(),
+ getCacheRegion.getProperties(),
+ problems);
+
+ if (getCacheRegion.hasError()) {
+ I18n msg = FederationI18n.requiredNodeDoesNotExistRelativeToNode;
+ throw new FederationException(msg.text("dna:cache", configNode));
+ }
+
+ // Get the source projections for the repository ...
+ Path projectionsNode = pathFactory.create(configNode, nameFactory.create("dna:projections"));
+ BasicGetChildrenCommand getProjections = new BasicGetChildrenCommand(projectionsNode);
+
+ executor.execute(getProjections);
+ if (getProjections.hasError()) {
+ I18n msg = FederationI18n.requiredNodeDoesNotExistRelativeToNode;
+ throw new FederationException(msg.text("dna:projections", configNode));
+ }
+
+ // Build the commands to get each of the projections (children of the "dna:projections" node) ...
+ List<Projection> sourceProjections = new LinkedList<Projection>();
+ if (getProjections.hasNoError() && !getProjections.getChildren().isEmpty()) {
+ BasicCompositeCommand commands = new BasicCompositeCommand();
+ for (Path.Segment child : getProjections.getChildren()) {
+ final Path pathToSource = pathFactory.create(projectionsNode, child);
+ commands.add(new BasicGetNodeCommand(pathToSource));
+ }
+ // Now execute these commands ...
+ executor.execute(commands);
+
+ // Iterate over each region node obtained ...
+ for (GraphCommand command : commands) {
+ BasicGetNodeCommand getProjectionCommand = (BasicGetNodeCommand)command;
+ if (getProjectionCommand.hasNoError()) {
+ Projection projection = createProjection(env,
+ projectionParser,
+ getProjectionCommand.getPath(),
+ getProjectionCommand.getProperties(),
+ problems);
+ if (projection != null) sourceProjections.add(projection);
+ }
+ }
+ }
+
+ // Look for the default cache policy ...
+ BasicCachePolicy cachePolicy = new BasicCachePolicy();
+ Property timeToExpireProperty = getRepository.getProperties().get(nameFactory.create(CACHE_POLICY_TIME_TO_EXPIRE_CONFIG_PROPERTY_NAME));
+ Property timeToCacheProperty = getRepository.getProperties().get(nameFactory.create(CACHE_POLICY_TIME_TO_CACHE_CONFIG_PROPERTY_NAME));
+ 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, cacheProjection, sourceProjections, defaultCachePolicy);
+ } catch (InvalidPathException err) {
+ I18n msg = FederationI18n.federatedRepositoryCannotBeFound;
+ throw new FederationException(msg.text(repositoryName));
+ } catch (InterruptedException err) {
+ I18n msg = FederationI18n.interruptedWhileUsingFederationConfigurationRepository;
+ throw new FederationException(msg.text(repositoryName));
+ }
+
+ }
+
+ /**
+ * Instantiate the {@link Projection} described by the supplied properties.
+ *
+ * @param env the execution environment that should be used to read the configuration; may not be null
+ * @param projectionParser the projection rule parser that should be used; may not be null
+ * @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
+ */
+ protected Projection createProjection( ExecutionEnvironment env,
+ ProjectionParser projectionParser,
+ Path path,
+ Map<Name, Property> properties,
+ Problems problems ) {
+ ValueFactories valueFactories = env.getValueFactories();
+ NameFactory nameFactory = valueFactories.getNameFactory();
+ ValueFactory<String> stringFactory = valueFactories.getStringFactory();
+
+ String sourceName = path.getLastSegment().getName().getLocalName();
+
+ // Get the rules ...
+ Projection.Rule[] projectionRules = null;
+ Property projectionRulesProperty = properties.get(nameFactory.create(PROJECTION_RULES_CONFIG_PROPERTY_NAME));
+ if (projectionRulesProperty != null && !projectionRulesProperty.isEmpty()) {
+ String[] projectionRuleStrs = stringFactory.create(projectionRulesProperty.getValuesAsArray());
+ if (projectionRuleStrs != null && projectionRuleStrs.length != 0) {
+ projectionRules = projectionParser.rulesFromStrings(env, projectionRuleStrs);
+ }
+ }
+ if (problems.hasErrors()) return null;
+
+ Projection region = new Projection(sourceName, projectionRules);
+ return region;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public synchronized String getName() {
+ return sourceName;
+ }
+
+ /**
+ * Set the name of this source.
+ * <p>
+ * This is a required property.
+ * </p>
+ *
+ * @param sourceName the name of this repository source
+ * @see #setConfigurationSourceName(String)
+ * @see #setConnectionFactoriesJndiName(String)
+ * @see #setConfigurationSourceProjectionRules(String[])
+ * @see #setPassword(String)
+ * @see #setUsername(String)
+ * @see #setRepositoryName(String)
+ * @see #setExecutionContextFactoryJndiName(String)
+ * @see #setPassword(String)
+ * @see #setUsername(String)
+ * @see #setName(String)
+ */
+ public synchronized void setName( String sourceName ) {
+ if (this.sourceName == sourceName || this.sourceName != null && this.sourceName.equals(sourceName)) return;
+ this.sourceName = sourceName;
+ changeRepositoryConfig();
+ }
+
+ /**
+ * Get the name in JNDI of a {@link FederatedRepository} instance that should be used. If this is set (and an instance can be
+ * found at that location), few of the remaining properties on this instance may not be used (basically just
+ * {@link #getUsername() username}, {@link #getPassword() password}, and {@link #getName() source name}).
+ * <p>
+ * This is an optional property.
+ * </p>
+ *
+ * @return the location in JNDI of the {@link FederatedRepository} that should be used by this source, or null if the
+ * {@link FederatedRepository} instance will be created from the properties of this instance
+ * @see #setRepositoryJndiName(String)
+ */
+ public String getRepositoryJndiName() {
+ return repositoryJndiName;
+ }
+
+ /**
+ * Set the name in JNDI of a {@link FederatedRepository} instance that should be used. If this is set (and an instance can be
+ * found at that location), few of the remaining properties on this instance may not be used (basically just
+ * {@link #getUsername() username}, {@link #getPassword() password}, and {@link #getName() source name}).
+ * <p>
+ * This is an optional property.
+ * </p>
+ *
+ * @param jndiName the JNDI name where the {@link FederatedRepository} instance can be found, or null if the instance is not
+ * to be found in JNDI but one should be instantiated from this instance's properties
+ * @see #getRepositoryJndiName()
+ * @see #setPassword(String)
+ * @see #setUsername(String)
+ * @see #setName(String)
+ */
+ public void setRepositoryJndiName( String jndiName ) {
+ if (this.repositoryJndiName == jndiName || this.repositoryJndiName != null && this.repositoryJndiName.equals(jndiName)) return;
+ this.repositoryJndiName = jndiName;
+ changeRepositoryConfig();
+ }
+
+ /**
+ * Get the name in JNDI of a {@link RepositorySource} instance that should be used by the {@link FederatedRepository federated
+ * repository} as the configuration repository.
+ * <p>
+ * This is a required property (unless the {@link #getRepositoryJndiName() federated repository is to be found in JDNI}).
+ * </p>
+ *
+ * @return the JNDI name of the {@link RepositorySource} instance that should be used for the configuration, or null if the
+ * federated repository instance is to be found in JNDI
+ * @see #setConfigurationSourceName(String)
+ */
+ public String getConfigurationSourceName() {
+ return configurationSourceName;
+ }
+
+ /**
+ * Get the name of a {@link RepositorySource} instance that should be used by the {@link FederatedRepository federated
+ * repository} as the configuration repository. The instance will be retrieved from the {@link RepositoryConnectionFactories}
+ * instance {@link #getConnectionFactoriesJndiName() found in JDNI}.
+ * <p>
+ * This is a required property (unless the {@link #getRepositoryJndiName() federated repository is to be found in JDNI}).
+ * </p>
+ *
+ * @param sourceName the name of the {@link RepositorySource} instance that should be used for the configuration, or null if
+ * the federated repository instance is to be found in JNDI
+ * @see #getConfigurationSourceName()
+ * @see #setConnectionFactoriesJndiName(String)
+ * @see #setConfigurationSourceProjectionRules(String[])
+ * @see #setPassword(String)
+ * @see #setUsername(String)
+ * @see #setRepositoryName(String)
+ * @see #setExecutionContextFactoryJndiName(String)
+ * @see #setName(String)
+ */
+ public void setConfigurationSourceName( String sourceName ) {
+ if (this.configurationSourceName == sourceName || this.configurationSourceName != null
+ && this.configurationSourceName.equals(sourceName)) return;
+ this.configurationSourceName = sourceName;
+ changeRepositoryConfig();
+ }
+
+ /**
+ * Get the projection rule definitions used for the {@link #getConfigurationSourceName() configuration source}. The
+ * {@link #DEFAULT_CONFIGURATION_SOURCE_PROJECTION_RULES default projection rules} map the root of the configuration source
+ * into the <code>/dna:system</code> branch of the repository.
+ * <p>
+ * This is a required property (unless the {@link #getRepositoryJndiName() federated repository is to be found in JDNI}).
+ * </p>
+ *
+ * @return the string array of projection rules, or null if the projection rules haven't yet been set or if the federated
+ * repository instance is to be found in JNDI
+ * @see #setConfigurationSourceProjectionRules(String[])
+ */
+ public String[] getConfigurationSourceProjectionRules() {
+ return configurationSourceProjectionRules;
+ }
+
+ /**
+ * Get the projection rule definitions used for the {@link #getConfigurationSourceName() configuration source}. The
+ * {@link #DEFAULT_CONFIGURATION_SOURCE_PROJECTION_RULES default projection rules} map the root of the configuration source
+ * into the <code>/dna:system</code> branch of the repository.
+ * <p>
+ * This is a required property (unless the {@link #getRepositoryJndiName() federated repository is to be found in JDNI}).
+ * </p>
+ *
+ * @param projectionRules the string array of projection rules, or null if the projection rules haven't yet been set or if the
+ * federated repository instance is to be found in JNDI
+ * @see #setConfigurationSourceProjectionRules(String[])
+ * @see #setConnectionFactoriesJndiName(String)
+ * @see #setConfigurationSourceName(String)
+ * @see #setPassword(String)
+ * @see #setUsername(String)
+ * @see #setRepositoryName(String)
+ * @see #setExecutionContextFactoryJndiName(String)
+ * @see #setName(String)
+ */
+ public void setConfigurationSourceProjectionRules( String[] projectionRules ) {
+ if (projectionRules != null) {
+ List<String> rules = new LinkedList<String>();
+ for (String rule : projectionRules) {
+ if (rule != null && rule.trim().length() != 0) rules.add(rule);
+ }
+ projectionRules = rules.toArray(new String[rules.size()]);
+ }
+ this.configurationSourceProjectionRules = projectionRules != null ? projectionRules : DEFAULT_CONFIGURATION_SOURCE_PROJECTION_RULES;
+ }
+
+ /**
+ * Get the name in JNDI of a {@link ExecutionContextFactory} instance that should be used to obtain the
+ * {@link ExecutionEnvironment execution context} used by the {@link FederatedRepository federated repository}.
+ * <p>
+ * This is a required property (unless the {@link #getRepositoryJndiName() federated repository is to be found in JDNI}).
+ * </p>
+ *
+ * @return the JNDI name of the {@link ExecutionContextFactory} instance that should be used, or null if the federated
+ * repository instance is to be found in JNDI
+ * @see #setExecutionContextFactoryJndiName(String)
+ */
+ public String getExecutionContextFactoryJndiName() {
+ return executionContextFactoryJndiName;
+ }
+
+ /**
+ * Set the name in JNDI of a {@link ExecutionContextFactory} instance that should be used to obtain the
+ * {@link ExecutionEnvironment execution context} used by the {@link FederatedRepository federated repository}.
+ * <p>
+ * This is a required property (unless the {@link #getRepositoryJndiName() federated repository is to be found in JDNI}).
+ * </p>
+ *
+ * @param jndiName the JNDI name where the {@link ExecutionContextFactory} instance can be found, or null if the federated
+ * repository instance is to be found in JNDI
+ * @see #getExecutionContextFactoryJndiName()
+ * @see #setConfigurationSourceName(String)
+ * @see #setConfigurationSourceProjectionRules(String[])
+ * @see #setConnectionFactoriesJndiName(String)
+ * @see #setPassword(String)
+ * @see #setUsername(String)
+ * @see #setRepositoryName(String)
+ * @see #setName(String)
+ */
+ public synchronized void setExecutionContextFactoryJndiName( String jndiName ) {
+ if (this.repositoryJndiName == jndiName || this.repositoryJndiName != null && this.repositoryJndiName.equals(jndiName)) return;
+ this.executionContextFactoryJndiName = jndiName;
+ changeRepositoryConfig();
+ }
+
+ /**
+ * Get the name in JNDI where the {@link RepositoryConnectionFactories} instance that can be used by the
+ * {@link FederatedRepository federated repository} can find any {@link RepositorySource} sources it needs, including those
+ * used for {@link Projection sources} and that used for it's {@link #getConfigurationSourceName() configuration}.
+ * <p>
+ * This is a required property (unless the {@link #getRepositoryJndiName() federated repository is to be found in JDNI}).
+ * </p>
+ *
+ * @return the JNDI name where the {@link RepositoryConnectionFactories} instance can be found, or null if the federated
+ * repository instance is to be found in JNDI
+ * @see #setConnectionFactoriesJndiName(String)
+ */
+ public String getConnectionFactoriesJndiName() {
+ return connectionFactoriesJndiName;
+ }
+
+ /**
+ * Set the name in JNDI where the {@link RepositoryConnectionFactories} instance that can be used by the
+ * {@link FederatedRepository federated repository} can find any {@link RepositorySource} sources it needs, including those
+ * used for {@link Projection sources} and that used for it's {@link #getConfigurationSourceName() configuration}.
+ * <p>
+ * This is a required property (unless the {@link #getRepositoryJndiName() federated repository is to be found in JDNI}).
+ * </p>
+ *
+ * @param jndiName the JNDI name where the {@link RepositoryConnectionFactories} instance can be found, or null if the
+ * federated repository instance is to be found in JNDI
+ * @see #getConnectionFactoriesJndiName()
+ * @see #setConfigurationSourceName(String)
+ * @see #setConfigurationSourceProjectionRules(String[])
+ * @see #setPassword(String)
+ * @see #setUsername(String)
+ * @see #setRepositoryName(String)
+ * @see #setExecutionContextFactoryJndiName(String)
+ * @see #setName(String)
+ */
+ public synchronized void setConnectionFactoriesJndiName( String jndiName ) {
+ if (this.connectionFactoriesJndiName == jndiName || this.connectionFactoriesJndiName != null
+ && this.connectionFactoriesJndiName.equals(jndiName)) return;
+ this.connectionFactoriesJndiName = jndiName;
+ changeRepositoryConfig();
+ }
+
+ /**
+ * @return securityDomain
+ */
+ public String getSecurityDomain() {
+ return securityDomain;
+ }
+
+ /**
+ * @param securityDomain Sets securityDomain to the specified value.
+ */
+ public void setSecurityDomain( String securityDomain ) {
+ this.securityDomain = securityDomain;
+ }
+
+ /**
+ * Get the name of the federated repository.
+ * <p>
+ * This is a required property (unless the {@link #getRepositoryJndiName() federated repository is to be found in JDNI}).
+ * </p>
+ *
+ * @return the name of the repository
+ * @see #setRepositoryName(String)
+ */
+ public synchronized String getRepositoryName() {
+ return this.repositoryName;
+ }
+
+ /**
+ * Get the name of the federated repository.
+ * <p>
+ * This is a required property (unless the {@link #getRepositoryJndiName() federated repository is to be found in JDNI}).
+ * </p>
+ *
+ * @param repositoryName the new name of the repository
+ * @throws IllegalArgumentException if the repository name is null, empty or blank
+ * @see #getRepositoryName()
+ * @see #setConfigurationSourceName(String)
+ * @see #setConfigurationSourceProjectionRules(String[])
+ * @see #setPassword(String)
+ * @see #setUsername(String)
+ * @see #setConnectionFactoriesJndiName(String)
+ * @see #setExecutionContextFactoryJndiName(String)
+ * @see #setName(String)
+ */
+ public synchronized void setRepositoryName( String repositoryName ) {
+ ArgCheck.isNotEmpty(repositoryName, "repositoryName");
+ if (this.repositoryName != null && this.repositoryName.equals(repositoryName)) return;
+ this.repositoryName = repositoryName;
+ changeRepositoryConfig();
+ }
+
+ /**
+ * This method is called to signal that some aspect of the configuration has changed. If a {@link #getRepository() repository}
+ * instance has been created, it's configuration is
+ * {@link #getRepositoryConfiguration(ExecutionEnvironment, RepositoryConnectionFactories) rebuilt} and updated. Nothing is
+ * done, however, if there is currently no {@link #getRepository() repository}.
+ */
+ protected synchronized void changeRepositoryConfig() {
+ if (this.repository != null) {
+ // Find in JNDI the repository connection factories and the environment ...
+ ExecutionEnvironment env = getExecutionEnvironment();
+ RepositoryConnectionFactories factories = getRepositoryConnectionFactories();
+ // Compute a new repository config and set it on the repository ...
+ FederatedRepositoryConfig newConfig = getRepositoryConfiguration(env, factories);
+ this.repository.setConfiguration(newConfig);
+ }
+ }
+
+ /**
+ * Get the username that should be used when authenticating and {@link #getConnection() creating connections}.
+ * <p>
+ * This is an optional property, required only when authentication is to be used.
+ * </p>
+ *
+ * @return the username, or null if no username has been set or are not to be used
+ * @see #setUsername(String)
+ */
+ public String getUsername() {
+ return this.username;
+ }
+
+ /**
+ * Set the username that should be used when authenticating and {@link #getConnection() creating connections}.
+ * <p>
+ * This is an optional property, required only when authentication is to be used.
+ * </p>
+ *
+ * @param username the username, or null if no username has been set or are not to be used
+ * @see #getUsername()
+ * @see #setPassword(String)
+ * @see #setConfigurationSourceName(String)
+ * @see #setConfigurationSourceProjectionRules(String[])
+ * @see #setPassword(String)
+ * @see #setRepositoryName(String)
+ * @see #setConnectionFactoriesJndiName(String)
+ * @see #setExecutionContextFactoryJndiName(String)
+ * @see #setName(String)
+ */
+ public void setUsername( String username ) {
+ this.username = username;
+ }
+
+ /**
+ * Get the password that should be used when authenticating and {@link #getConnection() creating connections}.
+ * <p>
+ * This is an optional property, required only when authentication is to be used.
+ * </p>
+ *
+ * @return the password, or null if no password have been set or are not to be used
+ * @see #setPassword(String)
+ */
+ public String getPassword() {
+ return this.password;
+ }
+
+ /**
+ * Get the password that should be used when authenticating and {@link #getConnection() creating connections}.
+ * <p>
+ * This is an optional property, required only when authentication is to be used.
+ * </p>
+ *
+ * @param password the password, or null if no password have been set or are not to be used
+ * @see #getPassword()
+ * @see #setConfigurationSourceName(String)
+ * @see #setConfigurationSourceProjectionRules(String[])
+ * @see #setUsername(String)
+ * @see #setRepositoryName(String)
+ * @see #setConnectionFactoriesJndiName(String)
+ * @see #setExecutionContextFactoryJndiName(String)
+ * @see #setName(String)
+ */
+ public void setPassword( String password ) {
+ this.password = password;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public synchronized Reference getReference() {
+ String className = getClass().getName();
+ String factoryClassName = NamingContextObjectFactory.class.getName();
+ Reference ref = new Reference(className, factoryClassName, null);
+
+ if (getRepositoryName() != null) {
+ ref.add(new StringRefAddr(REPOSITORY_NAME, getRepositoryName()));
+ }
+ if (getName() != null) {
+ ref.add(new StringRefAddr(SOURCE_NAME, getName()));
+ }
+ if (getUsername() != null) {
+ ref.add(new StringRefAddr(USERNAME, getUsername()));
+ }
+ if (getPassword() != null) {
+ ref.add(new StringRefAddr(PASSWORD, getPassword()));
+ }
+ if (getConfigurationSourceName() != null) {
+ ref.add(new StringRefAddr(CONFIGURATION_SOURCE_NAME, getConfigurationSourceName()));
+ }
+ if (getConfigurationSourceProjectionRules() != null) {
+ StringBuilder sb = new StringBuilder();
+ boolean first = true;
+ for (String rule : getConfigurationSourceProjectionRules()) {
+ if (!first) {
+ sb.append("\n");
+ first = false;
+ }
+ sb.append(rule);
+ }
+ ref.add(new StringRefAddr(CONFIGURATION_SOURCE_PROJECTION_RULES, sb.toString()));
+ }
+ if (getConnectionFactoriesJndiName() != null) {
+ ref.add(new StringRefAddr(CONNECTION_FACTORIES_JNDI_NAME, getConnectionFactoriesJndiName()));
+ }
+ if (getExecutionContextFactoryJndiName() != null) {
+ ref.add(new StringRefAddr(EXECUTION_CONTEXT_FACTORY_JNDI_NAME, getExecutionContextFactoryJndiName()));
+ }
+ if (getSecurityDomain() != null) {
+ ref.add(new StringRefAddr(SECURITY_DOMAIN, getSecurityDomain()));
+ }
+ if (getRepositoryJndiName() != null) {
+ ref.add(new StringRefAddr(REPOSITORY_JNDI_NAME, getRepositoryJndiName()));
+ }
+ ref.add(new StringRefAddr(RETRY_LIMIT, Integer.toString(getRetryLimit())));
+ return ref;
+ }
+
+ public static class NamingContextObjectFactory implements ObjectFactory {
+
+ public NamingContextObjectFactory() {
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public Object getObjectInstance( Object obj,
+ javax.naming.Name name,
+ Context nameCtx,
+ Hashtable<?, ?> environment ) throws Exception {
+ if (obj instanceof Reference) {
+ Map<String, String> values = new HashMap<String, String>();
+ Reference ref = (Reference)obj;
+ Enumeration<?> en = ref.getAll();
+ while (en.hasMoreElements()) {
+ RefAddr subref = (RefAddr)en.nextElement();
+ if (subref instanceof StringRefAddr) {
+ String key = subref.getType();
+ Object value = subref.getContent();
+ if (value != null) values.put(key, value.toString());
+ }
+ }
+ String repositoryName = values.get(FederatedRepositorySource.REPOSITORY_NAME);
+ String sourceName = values.get(FederatedRepositorySource.SOURCE_NAME);
+ String username = values.get(FederatedRepositorySource.USERNAME);
+ String password = values.get(FederatedRepositorySource.PASSWORD);
+ String configurationSourceName = values.get(FederatedRepositorySource.CONFIGURATION_SOURCE_NAME);
+ String projectionRules = values.get(FederatedRepositorySource.CONFIGURATION_SOURCE_PROJECTION_RULES);
+ String connectionFactoriesJndiName = values.get(FederatedRepositorySource.CONNECTION_FACTORIES_JNDI_NAME);
+ String environmentJndiName = values.get(FederatedRepositorySource.EXECUTION_CONTEXT_FACTORY_JNDI_NAME);
+ String repositoryJndiName = values.get(FederatedRepositorySource.REPOSITORY_JNDI_NAME);
+ String securityDomain = values.get(FederatedRepositorySource.SECURITY_DOMAIN);
+ String retryLimit = values.get(FederatedRepositorySource.RETRY_LIMIT);
+
+ // Create the source instance ...
+ FederatedRepositorySource source = new FederatedRepositorySource();
+ if (repositoryName != null) source.setRepositoryName(repositoryName);
+ if (sourceName != null) source.setName(sourceName);
+ if (username != null) source.setUsername(username);
+ if (password != null) source.setPassword(password);
+ if (configurationSourceName != null) source.setConfigurationSourceName(configurationSourceName);
+ if (projectionRules != null) {
+ List<String> rules = StringUtil.splitLines(projectionRules);
+ source.setConfigurationSourceProjectionRules(rules.toArray(new String[rules.size()]));
+ }
+ if (connectionFactoriesJndiName != null) source.setConnectionFactoriesJndiName(connectionFactoriesJndiName);
+ if (environmentJndiName != null) source.setExecutionContextFactoryJndiName(environmentJndiName);
+ if (repositoryJndiName != null) source.setRepositoryJndiName(repositoryJndiName);
+ if (securityDomain != null) source.setSecurityDomain(securityDomain);
+ if (retryLimit != null) source.setRetryLimit(Integer.parseInt(retryLimit));
+ return source;
+ }
+ return null;
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public int hashCode() {
+ return repositoryName.hashCode();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public boolean equals( Object obj ) {
+ if (obj == this) return true;
+ if (obj instanceof FederatedRepositorySource) {
+ FederatedRepositorySource that = (FederatedRepositorySource)obj;
+ // The repository name, source name, and federation service must all match
+ if (!this.getRepositoryName().equals(that.getRepositoryName())) return false;
+ if (this.getName() == null) {
+ if (that.getName() != null) return false;
+ } else {
+ if (!this.getName().equals(that.getName())) return false;
+ }
+ return true;
+ }
+ return false;
+ }
+
+}
Added: trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/FederationException.java
===================================================================
--- trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/FederationException.java (rev 0)
+++ trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/FederationException.java 2008-07-24 19:52:13 UTC (rev 369)
@@ -0,0 +1,66 @@
+/*
+ * 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.connector.federation;
+
+
+/**
+ *
+ * @author Randall Hauch
+ */
+public class FederationException extends RuntimeException {
+
+ /**
+ */
+ private static final long serialVersionUID = -27536888064529864L;
+
+ /**
+ *
+ */
+ public FederationException() {
+ }
+
+ /**
+ * @param message
+ */
+ public FederationException( String message ) {
+ super(message);
+
+ }
+
+ /**
+ * @param cause
+ */
+ public FederationException( Throwable cause ) {
+ super(cause);
+
+ }
+
+ /**
+ * @param message
+ * @param cause
+ */
+ public FederationException( String message, Throwable cause ) {
+ super(message, cause);
+
+ }
+
+}
Added: trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/FederationI18n.java
===================================================================
--- trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/FederationI18n.java (rev 0)
+++ trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/FederationI18n.java 2008-07-24 19:52:13 UTC (rev 369)
@@ -0,0 +1,70 @@
+/*
+ * 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.connector.federation;
+
+import java.util.Locale;
+import java.util.Set;
+import org.jboss.dna.common.i18n.I18n;
+
+/**
+ * @author Randall Hauch
+ */
+public final class FederationI18n {
+
+ public static I18n requiredNodeDoesNotExistRelativeToNode;
+ public static I18n propertyIsRequired;
+
+ public static I18n interruptedWhileUsingFederationConfigurationRepository;
+ public static I18n unableToFindFederatedRepositoryInJndi;
+ public static I18n unableToFindExecutionContextFactoryInJndi;
+ public static I18n unableToCreateExecutionContext;
+ public static I18n unableToFindRepositoryConnectionFactoriesInJndi;
+ public static I18n noRepositoryConnectionFactories;
+ public static I18n federatedRepositoryCannotBeFound;
+ public static I18n unableToFindRepositorySourceByName;
+ public static I18n unableToCreateConnectionToFederatedRepository;
+ public static I18n unableToAuthenticateConnectionToFederatedRepository;
+ public static I18n repositoryHasBeenShutDown;
+ public static I18n repositoryPathInFederationBindingIsNotAbsolute;
+ public static I18n errorReadingMergePlan;
+ public static I18n errorAddingProjectionRuleParseMethod;
+
+ static {
+ try {
+ I18n.initialize(FederationI18n.class);
+ } catch (final Exception err) {
+ System.err.println(err);
+ }
+ }
+
+ public static Set<Locale> getLocalizationProblemLocales() {
+ return I18n.getLocalizationProblemLocales(FederationI18n.class);
+ }
+
+ public static Set<String> getLocalizationProblems() {
+ return I18n.getLocalizationProblems(FederationI18n.class);
+ }
+
+ public static Set<String> getLocalizationProblems( Locale locale ) {
+ return I18n.getLocalizationProblems(FederationI18n.class, locale);
+ }
+}
Added: trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/Projection.java
===================================================================
--- trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/Projection.java (rev 0)
+++ trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/Projection.java 2008-07-24 19:52:13 UTC (rev 369)
@@ -0,0 +1,734 @@
+/*
+ * 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.connector.federation;
+
+import java.io.Serializable;
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Set;
+import java.util.concurrent.CopyOnWriteArrayList;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import net.jcip.annotations.Immutable;
+import org.jboss.dna.common.text.TextEncoder;
+import org.jboss.dna.common.util.ArgCheck;
+import org.jboss.dna.common.util.HashCode;
+import org.jboss.dna.common.util.Logger;
+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.connection.ExecutionEnvironment;
+import org.jboss.dna.spi.graph.connection.RepositorySource;
+
+/**
+ * A projection of content from a source into the integrated/federated repository. Each project consists of a set of {@link Rule
+ * rules} for a particular source, where each rule defines how content within a source is
+ * {@link Rule#getPathInRepository(Path, PathFactory) is project into the repository} and how the repository content is
+ * {@link Rule#getPathInSource(Path, PathFactory) projected into the source}. Different rule subclasses are used for different
+ * types.
+ *
+ * @author Randall Hauch
+ */
+@Immutable
+public class Projection implements Comparable<Projection>, Serializable {
+
+ /**
+ * Initial version
+ */
+ private static final long serialVersionUID = 1L;
+ protected static final List<Method> parserMethods;
+ static {
+ parserMethods = new CopyOnWriteArrayList<Method>();
+ try {
+ parserMethods.add(Projection.class.getDeclaredMethod("parsePathRule", String.class, ExecutionEnvironment.class));
+ } catch (Throwable err) {
+ Logger.getLogger(Projection.class).error(err, FederationI18n.errorAddingProjectionRuleParseMethod);
+ }
+ }
+
+ /**
+ * Add a static method that can be used to parse {@link Rule#getString(NamespaceRegistry, TextEncoder) rule definition
+ * strings}. These methods must be static, must accept a {@link String} definition as the first parameter and an
+ * {@link ExecutionEnvironment} environment reference as the second parameter, and should return the resulting {@link Rule}
+ * (or null if the definition format could not be understood by the method. Any exceptions during
+ * {@link Method#invoke(Object, Object...) invocation} will be logged at the
+ * {@link Logger#trace(Throwable, String, Object...) trace} level.
+ *
+ * @param method the method to be added
+ * @see #addRuleParser(ClassLoader, String, String)
+ */
+ public static void addRuleParser( Method method ) {
+ if (method != null) parserMethods.add(method);
+ }
+
+ /**
+ * Add a static method that can be used to parse {@link Rule#getString(NamespaceRegistry, TextEncoder) rule definition
+ * strings}. These methods must be static, must accept a {@link String} definition as the first parameter and an
+ * {@link ExecutionEnvironment} environment reference as the second parameter, and should return the resulting {@link Rule}
+ * (or null if the definition format could not be understood by the method. Any exceptions during
+ * {@link Method#invoke(Object, Object...) invocation} will be logged at the
+ * {@link Logger#trace(Throwable, String, Object...) trace} level.
+ *
+ * @param classLoader the class loader that should be used to load the class on which the method is defined; may not be null
+ * @param className the name of the class on which the static method is defined; may not be null
+ * @param methodName the name of the method
+ * @throws SecurityException if there is a security exception while loading the class or getting the method
+ * @throws NoSuchMethodException if the method does not exist on the class
+ * @throws ClassNotFoundException if the class could not be found given the supplied class loader
+ * @throws IllegalArgumentException if the class loader reference is null, or if the class name or method name are null or
+ * empty
+ * @see #addRuleParser(Method)
+ */
+ public static void addRuleParser( ClassLoader classLoader,
+ String className,
+ String methodName ) throws SecurityException, NoSuchMethodException, ClassNotFoundException {
+ ArgCheck.isNotNull(classLoader, "classLoader");
+ ArgCheck.isNotEmpty(className, "className");
+ ArgCheck.isNotEmpty(methodName, "methodName");
+ Class<?> clazz = Class.forName(className, true, classLoader);
+ parserMethods.add(clazz.getMethod(className, String.class, ExecutionEnvironment.class));
+ }
+
+ /**
+ * Remove the rule parser method.
+ *
+ * @param method the method to remove
+ * @return true if the method was removed, or false if the method was not a registered rule parser method
+ */
+ public static boolean removeRuleParser( Method method ) {
+ return parserMethods.remove(method);
+ }
+
+ /**
+ * Remove the rule parser method.
+ *
+ * @param declaringClassName the name of the class on which the static method is defined; may not be null
+ * @param methodName the name of the method
+ * @return true if the method was removed, or false if the method was not a registered rule parser method
+ * @throws IllegalArgumentException if the class loader reference is null, or if the class name or method name are null or
+ * empty
+ */
+ public static boolean removeRuleParser( String declaringClassName,
+ String methodName ) {
+ ArgCheck.isNotEmpty(declaringClassName, "declaringClassName");
+ ArgCheck.isNotEmpty(methodName, "methodName");
+ for (Method method : parserMethods) {
+ if (method.getName().equals(methodName) && method.getDeclaringClass().getName().equals(declaringClassName)) {
+ return parserMethods.remove(method);
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Parse the string form of a rule definition and return the rule
+ *
+ * @param definition the definition of the rule that is to be parsed
+ * @param env the environment in which this method is being executed; may not be null
+ * @return the rule, or null if the definition could not be parsed
+ */
+ public static Rule fromString( String definition,
+ ExecutionEnvironment env ) {
+ ArgCheck.isNotNull(env, "env");
+ definition = definition != null ? definition.trim() : "";
+ if (definition.length() == 0) return null;
+ for (Method method : parserMethods) {
+ try {
+ Rule rule = (Rule)method.invoke(null, definition, env);
+ if (rule != null) return rule;
+ } catch (Throwable err) {
+ String msg = "Error while parsing project rule definition \"{0}\" using {1}";
+ Logger.getLogger(Projection.class).trace(err, msg, definition, method);
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Pattern that identifies the form:
+ *
+ * <pre>
+ * repository_path [=> source_path [$ exception ]*]?
+ * </pre>
+ *
+ * where the following groups are captured on the first call to {@link Matcher#find()}:
+ * <ol>
+ * <li><code>repository_path</code></li>
+ * <li><code>source_path</code></li>
+ * </ol>
+ * and the following groups are captured on subsequent calls to {@link Matcher#find()}:
+ * <ol>
+ * <li>exception</code></li>
+ * </ol>
+ * <p>
+ * The regular expression is:
+ *
+ * <pre>
+ * ((?:[ˆ=$]|=(?!>))+)(?:(?:=>((?:[ˆ=$]|=(?!>))+))( \$ (?:(?:[ˆ=]|=(?!>))+))*)?
+ * </pre>
+ *
+ * </p>
+ */
+ protected static final String PATH_RULE_PATTERN_STRING = "((?:[^=$]|=(?!>))+)(?:(?:=>((?:[^=$]|=(?!>))+))( \\$ (?:(?:[^=]|=(?!>))+))*)?";
+ protected static final Pattern PATH_RULE_PATTERN = Pattern.compile(PATH_RULE_PATTERN_STRING);
+
+ /**
+ * Parse the string definition of a {@link PathRule}. This method is automatically registered in the {@link #parserMethods
+ * parser methods} by the static initializer of {@link Projection}.
+ *
+ * @param definition the definition
+ * @param env the environment
+ * @return the path rule, or null if the definition is not in the right form
+ */
+ public static PathRule parsePathRule( String definition,
+ ExecutionEnvironment env ) {
+ definition = definition != null ? definition.trim() : "";
+ if (definition.length() == 0) return null;
+ Matcher matcher = PATH_RULE_PATTERN.matcher(definition);
+ if (!matcher.find()) return null;
+ String reposPathStr = matcher.group(1);
+ String sourcePathStr = matcher.group(2);
+ PathFactory pathFactory = env.getValueFactories().getPathFactory();
+ Path repositoryPath = pathFactory.create(reposPathStr);
+ Path sourcePath = pathFactory.create(sourcePathStr);
+
+ // Grab the exceptions ...
+ List<Path> exceptions = new LinkedList<Path>();
+ while (matcher.find()) {
+ String exceptionStr = matcher.group(1);
+ Path exception = pathFactory.create(exceptionStr);
+ exceptions.add(exception);
+ }
+ return new PathRule(repositoryPath, sourcePath, exceptions);
+ }
+
+ private final String sourceName;
+ private final List<Rule> rules;
+
+ /**
+ * Create a new federated projection for the supplied source, using the supplied rules.
+ *
+ * @param sourceName the name of the source
+ * @param rules the projection rules
+ * @throws IllegalArgumentException if the source name or rule array is null, empty, or contains all nulls
+ */
+ public Projection( String sourceName,
+ Rule... rules ) {
+ ArgCheck.isNotEmpty(sourceName, "sourceName");
+ ArgCheck.isNotEmpty(rules, "rules");
+ this.sourceName = sourceName;
+ List<Rule> rulesList = new ArrayList<Rule>();
+ for (Rule rule : rules) {
+ if (rule != null) rulesList.add(rule);
+ }
+ this.rules = Collections.unmodifiableList(rulesList);
+ ArgCheck.isNotEmpty(this.rules, "rules");
+ }
+
+ /**
+ * Get the name of the source to which this projection applies.
+ *
+ * @return the source name
+ * @see RepositorySource#getName()
+ */
+ public String getSourceName() {
+ return sourceName;
+ }
+
+ /**
+ * Get the rules that define this projection.
+ *
+ * @return the unmodifiable list of immutable rules; never null
+ */
+ public List<Rule> getRules() {
+ return rules;
+ }
+
+ /**
+ * Get the paths in the source that correspond to the supplied path within the repository. This method computes the paths
+ * given all of the rules. In general, most sources will probably project a node onto a single repository node. However, some
+ * sources may be configured such that the same node in the repository is a projection of multiple nodes within the source.
+ *
+ * @param canonicalPathInRepository the canonical path of the node within the repository; may not be null
+ * @param factory the path factory; may not be null
+ * @return the set of unique paths in the source projected from the repository path; never null
+ * @throws IllegalArgumentException if the factory reference is null
+ */
+ public Set<Path> getPathsInSource( Path canonicalPathInRepository,
+ PathFactory factory ) {
+ ArgCheck.isNotNull(factory, "factory");
+ assert canonicalPathInRepository == null ? true : canonicalPathInRepository.equals(canonicalPathInRepository.getCanonicalPath());
+ Set<Path> paths = new HashSet<Path>();
+ for (Rule rule : getRules()) {
+ Path pathInSource = rule.getPathInSource(canonicalPathInRepository, factory);
+ if (pathInSource != null) paths.add(pathInSource);
+ }
+ return paths;
+ }
+
+ /**
+ * Get the paths in the repository that correspond to the supplied path within the source. This method computes the paths
+ * given all of the rules. In general, most sources will probably project a node onto a single repository node. However, some
+ * sources may be configured such that the same node in the source is projected into multiple nodes within the repository.
+ *
+ * @param canonicalPathInSource the canonical path of the node within the source; may not be null
+ * @param factory the path factory; may not be null
+ * @return the set of unique paths in the repository projected from the source path; never null
+ * @throws IllegalArgumentException if the factory reference is null
+ */
+ public Set<Path> getPathsInRepository( Path canonicalPathInSource,
+ PathFactory factory ) {
+ ArgCheck.isNotNull(factory, "factory");
+ assert canonicalPathInSource == null ? true : canonicalPathInSource.equals(canonicalPathInSource.getCanonicalPath());
+ Set<Path> paths = new HashSet<Path>();
+ for (Rule rule : getRules()) {
+ Path pathInRepository = rule.getPathInRepository(canonicalPathInSource, factory);
+ if (pathInRepository != null) paths.add(pathInRepository);
+ }
+ return paths;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see java.lang.Object#hashCode()
+ */
+ @Override
+ public int hashCode() {
+ return this.sourceName.hashCode();
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see java.lang.Object#equals(java.lang.Object)
+ */
+ @Override
+ public boolean equals( Object obj ) {
+ if (obj == this) return true;
+ if (obj instanceof Projection) {
+ Projection that = (Projection)obj;
+ if (!this.getSourceName().equals(that.getSourceName())) return false;
+ if (!this.getRules().equals(that.getRules())) return false;
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see java.lang.Comparable#compareTo(java.lang.Object)
+ */
+ public int compareTo( Projection that ) {
+ if (this == that) return 0;
+ int diff = this.getSourceName().compareTo(that.getSourceName());
+ if (diff != 0) return diff;
+ Iterator<Rule> thisIter = this.getRules().iterator();
+ Iterator<Rule> thatIter = that.getRules().iterator();
+ while (thisIter.hasNext() && thatIter.hasNext()) {
+ diff = thisIter.next().compareTo(thatIter.next());
+ if (diff != 0) return diff;
+ }
+ if (thisIter.hasNext()) return 1;
+ if (thatIter.hasNext()) return -1;
+ return 0;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see java.lang.Object#toString()
+ */
+ @Override
+ public String toString() {
+ StringBuilder sb = new StringBuilder();
+ sb.append(this.sourceName);
+ sb.append(" { ");
+ boolean first = true;
+ for (Rule rule : this.getRules()) {
+ if (!first) sb.append(" ; ");
+ sb.append(rule.toString());
+ first = false;
+ }
+ sb.append(" }");
+ return super.toString();
+ }
+
+ /**
+ * A rule used within a project do define how content within a source is project into the federated repository. This mapping
+ * is bi-directional, meaning it's possible to determine
+ * <ul>
+ * <li>the path in repository given a path in source; and</li>
+ * <li>the path in source given a path in repository.</li>
+ * </ul>
+ *
+ * @author Randall Hauch
+ */
+ @Immutable
+ public static abstract class Rule implements Comparable<Rule> {
+ /**
+ * Get the path in source that is projected from the supplied repository path, or null if the supplied repository path is
+ * not projected into the source.
+ *
+ * @param pathInRepository the path in the repository; may not be null
+ * @param factory the path factory; may not be null
+ * @return the path in source if it is projected by this rule, or null otherwise
+ */
+ public abstract Path getPathInSource( Path pathInRepository,
+ PathFactory factory );
+
+ /**
+ * Get the path in repository that is projected from the supplied source path, or null if the supplied source path is not
+ * projected into the repository.
+ *
+ * @param pathInSource the path in the source; may not be null
+ * @param factory the path factory; may not be null
+ * @return the path in repository if it is projected by this rule, or null otherwise
+ */
+ public abstract Path getPathInRepository( Path pathInSource,
+ PathFactory factory );
+
+ public abstract String getString( NamespaceRegistry registry,
+ TextEncoder encoder );
+
+ public abstract String getString( TextEncoder encoder );
+
+ public abstract String getString();
+ }
+
+ /**
+ * A rule that is defined with a single {@link #getPathInSource() path in source} and a single {@link #getPathInRepository()
+ * path in repository}, and which has a set of {@link #getExceptionsToRule() path exceptions} (relative paths below the path
+ * in source).
+ *
+ * @author Randall Hauch
+ */
+ @Immutable
+ public static class PathRule extends Rule {
+ /** The path of the content as known to the source */
+ private final Path sourcePath;
+ /** The path where the content is to be placed ("projected") into the repository */
+ private final Path repositoryPath;
+ /** The paths (relative to the source path) that identify exceptions to this rule */
+ private final List<Path> exceptions;
+ private final int hc;
+
+ public PathRule( Path repositoryPath,
+ Path sourcePath ) {
+ this(repositoryPath, sourcePath, (Path[])null);
+ }
+
+ public PathRule( Path repositoryPath,
+ Path sourcePath,
+ Path... exceptions ) {
+ assert sourcePath != null;
+ assert repositoryPath != null;
+ this.sourcePath = sourcePath;
+ this.repositoryPath = repositoryPath;
+ if (exceptions == null || exceptions.length == 0) {
+ this.exceptions = Collections.emptyList();
+ } else {
+ List<Path> exceptionList = new ArrayList<Path>();
+ for (Path exception : exceptions) {
+ if (exception != null) exceptionList.add(exception);
+ }
+ this.exceptions = Collections.unmodifiableList(exceptionList);
+ }
+ this.hc = HashCode.compute(sourcePath, repositoryPath, exceptions);
+ assert exceptionPathsAreRelative();
+ }
+
+ public PathRule( Path repositoryPath,
+ Path sourcePath,
+ List<Path> exceptions ) {
+ assert sourcePath != null;
+ assert repositoryPath != null;
+ this.sourcePath = sourcePath;
+ this.repositoryPath = repositoryPath;
+ if (exceptions == null || exceptions.isEmpty()) {
+ this.exceptions = Collections.emptyList();
+ } else {
+ this.exceptions = Collections.unmodifiableList(new ArrayList<Path>(exceptions));
+ }
+ this.hc = HashCode.compute(sourcePath, repositoryPath, exceptions);
+ assert exceptionPathsAreRelative();
+ }
+
+ private boolean exceptionPathsAreRelative() {
+ if (this.exceptions != null) {
+ for (Path path : this.exceptions) {
+ if (path.isAbsolute()) return false;
+ }
+ }
+ return true;
+ }
+
+ /**
+ * The path where the content is to be placed ("projected") into the repository.
+ *
+ * @return the projected path of the content in the repository; never null
+ */
+ public Path getPathInRepository() {
+ return repositoryPath;
+ }
+
+ /**
+ * The path of the content as known to the source
+ *
+ * @return the source-specific path of the content; never null
+ */
+ public Path getPathInSource() {
+ return sourcePath;
+ }
+
+ /**
+ * Get whether this rule has any exceptions.
+ *
+ * @return true if this rule has exceptions, or false if it has none.
+ */
+ public boolean hasExceptionsToRule() {
+ return exceptions.size() != 0;
+ }
+
+ /**
+ * Get the paths that define the exceptions to this rule. These paths are always relative to the
+ * {@link #getPathInSource() path in source}.
+ *
+ * @return the unmodifiable exception paths; never null but possibly empty
+ */
+ public List<Path> getExceptionsToRule() {
+ return exceptions;
+ }
+
+ /**
+ * @param pathInSource
+ * @return true if the source path is included by this rule
+ */
+ protected boolean includes( Path pathInSource ) {
+ // Check whether the path is outside the source-specific path ...
+ if (this.sourcePath.isAtOrAbove(pathInSource)) {
+
+ // The path is inside the source-specific region, so check the exceptions ...
+ List<Path> exceptions = getExceptionsToRule();
+ if (exceptions.size() != 0) {
+ Path subpathInSource = pathInSource.relativeTo(this.sourcePath);
+ if (subpathInSource.size() != 0) {
+ for (Path exception : exceptions) {
+ if (subpathInSource.isAtOrBelow(exception)) return false;
+ }
+ }
+ }
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * {@inheritDoc}
+ * <p>
+ * This method considers a path that is at or below the rule's {@link #getPathInSource() source path} to be included,
+ * except if there are {@link #getExceptionsToRule() exceptions} that explicitly disallow the path.
+ * </p>
+ *
+ * @see org.jboss.dna.connector.federation.Projection.Rule#getPathInSource(Path, PathFactory)
+ */
+ @Override
+ public Path getPathInSource( Path pathInRepository,
+ PathFactory factory ) {
+ assert pathInRepository.equals(pathInRepository.getCanonicalPath());
+ // Project the repository path into the equivalent source path ...
+ Path pathInSource = projectPathInRepositoryToPathInSource(pathInRepository, factory);
+
+ // Check whether the source path is included by this rule ...
+ return includes(pathInSource) ? pathInSource : null;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.jboss.dna.connector.federation.Projection.Rule#getPathInRepository(org.jboss.dna.spi.graph.Path,
+ * org.jboss.dna.spi.graph.PathFactory)
+ */
+ @Override
+ public Path getPathInRepository( Path pathInSource,
+ PathFactory factory ) {
+ assert pathInSource.equals(pathInSource.getCanonicalPath());
+ // Check whether the source path is included by this rule ...
+ if (!includes(pathInSource)) return null;
+
+ // Project the repository path into the equivalent source path ...
+ return projectPathInSourceToPathInRepository(pathInSource, factory);
+ }
+
+ /**
+ * 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()}), or null if the path is not at or under the {@link #getPathInSource()}
+ */
+ protected Path projectPathInSourceToPathInRepository( Path pathInSource,
+ PathFactory factory ) {
+ if (!this.sourcePath.isAtOrAbove(pathInSource)) return null;
+ // Remove the leading source path ...
+ Path relativeSourcePath = pathInSource.relativeTo(this.sourcePath);
+ // Prepend the region's root path ...
+ Path result = factory.create(this.repositoryPath, 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()}
+ * ), or null if the path is not at or under the {@link #getPathInRepository()}
+ */
+ protected Path projectPathInRepositoryToPathInSource( Path pathInRepository,
+ PathFactory factory ) {
+ if (!this.repositoryPath.isAtOrAbove(pathInRepository)) return null;
+ // Find the relative path from the root of this region ...
+ Path pathInRegion = pathInRepository.relativeTo(this.repositoryPath);
+ // Prepend the path in source ...
+ Path result = factory.create(this.sourcePath, pathInRegion);
+ return result.getNormalizedPath();
+ }
+
+ @Override
+ public String getString( NamespaceRegistry registry,
+ TextEncoder encoder ) {
+ StringBuilder sb = new StringBuilder();
+ sb.append(this.getPathInRepository().getString(registry, encoder));
+ sb.append(" => ");
+ sb.append(this.getPathInSource().getString(registry, encoder));
+ if (this.getExceptionsToRule().size() != 0) {
+ for (Path exception : this.getExceptionsToRule()) {
+ sb.append(" $ ");
+ sb.append(exception.getString(registry, encoder));
+ }
+ }
+ return sb.toString();
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.jboss.dna.connector.federation.Projection.Rule#getString(org.jboss.dna.common.text.TextEncoder)
+ */
+ @Override
+ public String getString( TextEncoder encoder ) {
+ StringBuilder sb = new StringBuilder();
+ sb.append(this.getPathInRepository().getString(encoder));
+ sb.append(" => ");
+ sb.append(this.getPathInSource().getString(encoder));
+ if (this.getExceptionsToRule().size() != 0) {
+ for (Path exception : this.getExceptionsToRule()) {
+ sb.append(" $ ");
+ sb.append(exception.getString(encoder));
+ }
+ }
+ return sb.toString();
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.jboss.dna.connector.federation.Projection.Rule#getString()
+ */
+ @Override
+ public String getString() {
+ return getString(Path.JSR283_ENCODER);
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see java.lang.Object#hashCode()
+ */
+ @Override
+ public int hashCode() {
+ return hc;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see java.lang.Object#equals(java.lang.Object)
+ */
+ @Override
+ public boolean equals( Object obj ) {
+ if (obj == this) return true;
+ if (obj instanceof PathRule) {
+ PathRule that = (PathRule)obj;
+ if (!this.getPathInRepository().equals(that.getPathInRepository())) return false;
+ if (!this.getPathInSource().equals(that.getPathInSource())) return false;
+ if (!this.getExceptionsToRule().equals(that.getExceptionsToRule())) return false;
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see java.lang.Comparable#compareTo(java.lang.Object)
+ */
+ public int compareTo( Rule other ) {
+ if (other == this) return 0;
+ if (other instanceof PathRule) {
+ PathRule that = (PathRule)other;
+ int diff = this.getPathInRepository().compareTo(that.getPathInRepository());
+ if (diff != 0) return diff;
+ diff = this.getPathInSource().compareTo(that.getPathInSource());
+ if (diff != 0) return diff;
+ Iterator<Path> thisIter = this.getExceptionsToRule().iterator();
+ Iterator<Path> thatIter = that.getExceptionsToRule().iterator();
+ while (thisIter.hasNext() && thatIter.hasNext()) {
+ diff = thisIter.next().compareTo(thatIter.next());
+ if (diff != 0) return diff;
+ }
+ if (thisIter.hasNext()) return 1;
+ if (thatIter.hasNext()) return -1;
+ return 0;
+ }
+ return other.getClass().getName().compareTo(this.getClass().getName());
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see java.lang.Object#toString()
+ */
+ @Override
+ public String toString() {
+ return getString();
+ }
+ }
+}
Added: trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/ProjectionParser.java
===================================================================
--- trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/ProjectionParser.java (rev 0)
+++ trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/ProjectionParser.java 2008-07-24 19:52:13 UTC (rev 369)
@@ -0,0 +1,243 @@
+/*
+ * 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.connector.federation;
+
+import java.lang.reflect.Method;
+import java.util.Collections;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.concurrent.CopyOnWriteArrayList;
+import org.jboss.dna.common.text.TextEncoder;
+import org.jboss.dna.common.util.ArgCheck;
+import org.jboss.dna.common.util.Logger;
+import org.jboss.dna.common.util.StringUtil;
+import org.jboss.dna.connector.federation.Projection.Rule;
+import org.jboss.dna.spi.graph.NamespaceRegistry;
+import org.jboss.dna.spi.graph.connection.ExecutionEnvironment;
+
+/**
+ * A parser library for {@link Projection projections} and {@link Projection.Rule projection rules}.
+ *
+ * @author Randall Hauch
+ */
+public class ProjectionParser {
+ private static final ProjectionParser INSTANCE;
+
+ static {
+ INSTANCE = new ProjectionParser();
+ try {
+ INSTANCE.addRuleParser(Projection.class, "parsePathRule");
+ assert INSTANCE.parserMethods.size() == 1;
+ } catch (Throwable err) {
+ Logger.getLogger(Projection.class).error(err, FederationI18n.errorAddingProjectionRuleParseMethod);
+ }
+ }
+
+ /**
+ * Get the shared projection parser, which is by default populated with the standard parser rules.
+ *
+ * @return the parser; never null
+ */
+ public static ProjectionParser getInstance() {
+ return INSTANCE;
+ }
+
+ private final List<Method> parserMethods = new CopyOnWriteArrayList<Method>();
+ protected final Logger logger;
+
+ public ProjectionParser() {
+ this.logger = Logger.getLogger(this.getClass());
+ }
+
+ /**
+ * Add a static method that can be used to parse {@link Rule#getString(NamespaceRegistry, TextEncoder) rule definition
+ * strings}. These methods must be static, must accept a {@link String} definition as the first parameter and an
+ * {@link ExecutionEnvironment} environment reference as the second parameter, and should return the resulting {@link Rule}
+ * (or null if the definition format could not be understood by the method. Any exceptions during
+ * {@link Method#invoke(Object, Object...) invocation} will be logged at the
+ * {@link Logger#trace(Throwable, String, Object...) trace} level.
+ *
+ * @param method the method to be added
+ * @see #addRuleParser(ClassLoader, String, String)
+ */
+ public void addRuleParser( Method method ) {
+ if (method != null) parserMethods.add(method);
+ }
+
+ /**
+ * Add a static method that can be used to parse {@link Rule#getString(NamespaceRegistry, TextEncoder) rule definition
+ * strings}. These methods must be static, must accept a {@link String} definition as the first parameter and an
+ * {@link ExecutionEnvironment} environment reference as the second parameter, and should return the resulting {@link Rule}
+ * (or null if the definition format could not be understood by the method. Any exceptions during
+ * {@link Method#invoke(Object, Object...) invocation} will be logged at the
+ * {@link Logger#trace(Throwable, String, Object...) trace} level.
+ *
+ * @param clazz the class on which the static method is defined; may not be null
+ * @param methodName the name of the method
+ * @throws SecurityException if there is a security exception while loading the class or getting the method
+ * @throws NoSuchMethodException if the method does not exist on the class
+ * @throws IllegalArgumentException if the class loader reference is null, or if the class name or method name are null or
+ * empty
+ * @see #addRuleParser(Method)
+ */
+ public void addRuleParser( Class<?> clazz,
+ String methodName ) throws SecurityException, NoSuchMethodException {
+ ArgCheck.isNotNull(clazz, "clazz");
+ ArgCheck.isNotEmpty(methodName, "methodName");
+ parserMethods.add(clazz.getMethod(methodName, String.class, ExecutionEnvironment.class));
+ }
+
+ /**
+ * Add a static method that can be used to parse {@link Rule#getString(NamespaceRegistry, TextEncoder) rule definition
+ * strings}. These methods must be static, must accept a {@link String} definition as the first parameter and an
+ * {@link ExecutionEnvironment} environment reference as the second parameter, and should return the resulting {@link Rule}
+ * (or null if the definition format could not be understood by the method. Any exceptions during
+ * {@link Method#invoke(Object, Object...) invocation} will be logged at the
+ * {@link Logger#trace(Throwable, String, Object...) trace} level.
+ *
+ * @param classLoader the class loader that should be used to load the class on which the method is defined; may not be null
+ * @param className the name of the class on which the static method is defined; may not be null
+ * @param methodName the name of the method
+ * @throws SecurityException if there is a security exception while loading the class or getting the method
+ * @throws NoSuchMethodException if the method does not exist on the class
+ * @throws ClassNotFoundException if the class could not be found given the supplied class loader
+ * @throws IllegalArgumentException if the class loader reference is null, or if the class name or method name are null or
+ * empty
+ * @see #addRuleParser(Method)
+ */
+ public void addRuleParser( ClassLoader classLoader,
+ String className,
+ String methodName ) throws SecurityException, NoSuchMethodException, ClassNotFoundException {
+ ArgCheck.isNotNull(classLoader, "classLoader");
+ ArgCheck.isNotEmpty(className, "className");
+ ArgCheck.isNotEmpty(methodName, "methodName");
+ Class<?> clazz = Class.forName(className, true, classLoader);
+ parserMethods.add(clazz.getMethod(methodName, String.class, ExecutionEnvironment.class));
+ }
+
+ /**
+ * Remove the rule parser method.
+ *
+ * @param method the method to remove
+ * @return true if the method was removed, or false if the method was not a registered rule parser method
+ */
+ public boolean removeRuleParser( Method method ) {
+ return parserMethods.remove(method);
+ }
+
+ /**
+ * Remove the rule parser method.
+ *
+ * @param declaringClassName the name of the class on which the static method is defined; may not be null
+ * @param methodName the name of the method
+ * @return true if the method was removed, or false if the method was not a registered rule parser method
+ * @throws IllegalArgumentException if the class loader reference is null, or if the class name or method name are null or
+ * empty
+ */
+ public boolean removeRuleParser( String declaringClassName,
+ String methodName ) {
+ ArgCheck.isNotEmpty(declaringClassName, "declaringClassName");
+ ArgCheck.isNotEmpty(methodName, "methodName");
+ for (Method method : parserMethods) {
+ if (method.getName().equals(methodName) && method.getDeclaringClass().getName().equals(declaringClassName)) {
+ return parserMethods.remove(method);
+ }
+ }
+ return false;
+ }
+
+ /**
+ * @return parserMethods
+ */
+ /*package*/List<Method> getParserMethods() {
+ return Collections.unmodifiableList(parserMethods);
+ }
+
+ /**
+ * Parse the string form of a rule definition and return the rule
+ *
+ * @param definition the definition of the rule that is to be parsed
+ * @param env the environment in which this method is being executed; may not be null
+ * @return the rule, or null if the definition could not be parsed
+ */
+ public Rule ruleFromString( String definition,
+ ExecutionEnvironment env ) {
+ ArgCheck.isNotNull(env, "env");
+ definition = definition != null ? definition.trim() : "";
+ if (definition.length() == 0) return null;
+ for (Method method : parserMethods) {
+ try {
+ Rule rule = (Rule)method.invoke(null, definition, env);
+ if (rule != null) {
+ if (logger.isTraceEnabled()) {
+ String msg = "Success parsing project rule definition \"{0}\" using {1}";
+ logger.trace(msg, definition, method);
+ }
+ return rule;
+ } else if (logger.isTraceEnabled()) {
+ String msg = "Unable to parse project rule definition \"{0}\" using {1}";
+ logger.trace(msg, definition, method);
+ }
+ } catch (Throwable err) {
+ String msg = "Error while parsing project rule definition \"{0}\" using {1}";
+ Logger.getLogger(Projection.class).trace(err, msg, definition, method);
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Parse string forms of an arry of rule definitions and return the rules
+ *
+ * @param env the environment in which this method is being executed; may not be null
+ * @param definitions the definition of the rules that are to be parsed
+ * @return the rule, or null if the definition could not be parsed
+ */
+ public Rule[] rulesFromStrings( ExecutionEnvironment env,
+ String... definitions ) {
+ List<Rule> rules = new LinkedList<Rule>();
+ for (String definition : definitions) {
+ Rule rule = ruleFromString(definition, env);
+ if (rule != null) rules.add(rule);
+ }
+ return rules.toArray(new Rule[rules.size()]);
+ }
+
+ /**
+ * Parse a single string containing one or more string forms of rule definitions, and return the rules. The string contains
+ * each rule on a separate line.
+ *
+ * @param env the environment in which this method is being executed; may not be null
+ * @param definitions the definitions of the rules that are to be parsed, each definition separated by a newline character.
+ * @return the rule, or null if the definition could not be parsed
+ */
+ public Rule[] rulesFromString( ExecutionEnvironment env,
+ String definitions ) {
+ List<String> lines = StringUtil.splitLines(definitions);
+ List<Rule> rules = new LinkedList<Rule>();
+ for (String definition : lines) {
+ Rule rule = ruleFromString(definition, env);
+ if (rule != null) rules.add(rule);
+ }
+ return rules.toArray(new Rule[rules.size()]);
+ }
+}
Added: trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/contribution/AbstractContribution.java
===================================================================
--- trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/contribution/AbstractContribution.java (rev 0)
+++ trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/contribution/AbstractContribution.java 2008-07-24 19:52:13 UTC (rev 369)
@@ -0,0 +1,132 @@
+/*
+ * 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.connector.federation.contribution;
+
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import org.jboss.dna.spi.graph.DateTime;
+import org.jboss.dna.spi.graph.Name;
+import org.jboss.dna.spi.graph.Property;
+import org.jboss.dna.spi.graph.Path.Segment;
+
+/**
+ * @author Randall Hauch
+ */
+public abstract class AbstractContribution implements Contribution {
+
+ /**
+ * This is the first version of this class. See the documentation of BasicMergePlan.serialVersionUID.
+ */
+ private static final long serialVersionUID = 1L;
+
+ protected static final List<Segment> EMPTY_CHILDREN = Collections.emptyList();
+ protected static final Map<Name, Property> EMPTY_PROPERTIES = Collections.emptyMap();
+
+ private final String sourceName;
+ private DateTime expirationTimeInUtc;
+
+ /**
+ * Create a contribution for the source with the supplied name.
+ *
+ * @param sourceName the name of the source, which may not be null or blank
+ */
+ protected AbstractContribution( String sourceName ) {
+ assert sourceName != null && sourceName.trim().length() != 0;
+ this.sourceName = sourceName;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public String getSourceName() {
+ return this.sourceName;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public List<Segment> getChildren() {
+ return EMPTY_CHILDREN;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public Map<Name, Property> getProperties() {
+ return EMPTY_PROPERTIES;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.jboss.dna.connector.federation.contribution.Contribution#isExpired(org.jboss.dna.spi.graph.DateTime)
+ */
+ public boolean isExpired( DateTime utcTime ) {
+ assert utcTime != null;
+ assert utcTime.toUtcTimeZone().equals(utcTime); // check that it is passed UTC time
+ return !expirationTimeInUtc.isAfter(utcTime);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public DateTime getExpirationTimeInUtc() {
+ return this.expirationTimeInUtc;
+ }
+
+ /**
+ * @param expirationTimeInUtc Sets expirationTimeInUtc to the specified value.
+ */
+ public void setExpirationTimeInUtc( DateTime expirationTimeInUtc ) {
+ this.expirationTimeInUtc = expirationTimeInUtc;
+ }
+
+ /**
+ * {@inheritDoc}
+ * <p>
+ * This implementation returns the hash code of the {@link #getSourceName() source name}, and is compatible with the
+ * implementation of {@link #equals(Object)}.
+ * </p>
+ */
+ @Override
+ public int hashCode() {
+ return this.sourceName.hashCode();
+ }
+
+ /**
+ * {@inheritDoc}
+ * <p>
+ * This implementation only compares the {@link #getSourceName() source name}.
+ * </p>
+ */
+ @Override
+ public boolean equals( Object obj ) {
+ if (obj == this) return true;
+ if (obj instanceof AbstractContribution) {
+ AbstractContribution that = (AbstractContribution)obj;
+ return this.getSourceName().equals(that.getSourceName());
+ }
+ return false;
+ }
+
+}
Added: trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/contribution/Contribution.java
===================================================================
--- trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/contribution/Contribution.java (rev 0)
+++ trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/contribution/Contribution.java 2008-07-24 19:52:13 UTC (rev 369)
@@ -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.connector.federation.contribution;
+
+import java.io.Serializable;
+import java.util.List;
+import java.util.Map;
+import net.jcip.annotations.NotThreadSafe;
+import org.jboss.dna.spi.graph.DateTime;
+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.Path.Segment;
+
+/**
+ * The contribution of a source to the information for a single federated node. Users of this interface should treat contributions
+ * as generally being immutable, since some implementation will be immutable and will return immutable {@link #getProperties()
+ * properties} and {@link #getChildren() children} containers. Thus, rather than make changes to an existing contribution, a new
+ * contribution is created to replace the previous contribution.
+ *
+ * @author Randall Hauch
+ */
+@NotThreadSafe
+public interface Contribution extends Serializable {
+
+ /**
+ * Get the name of the source that made this contribution.
+ *
+ * @return the name of the contributing source
+ */
+ public String getSourceName();
+
+ /**
+ * Get the source-specific path of this information.
+ *
+ * @return the path as known to the source, or null for {@link EmptyContribution}
+ */
+ public Path getPathInSource();
+
+ /**
+ * Determine whether this contribution has expired given the supplied current time.
+ *
+ * @param utcTime the current time expressed in UTC; may not be null
+ * @return true if at least one contribution has expired, or false otherwise
+ */
+ public boolean isExpired( DateTime utcTime );
+
+ /**
+ * Get the expiration time, already in UTC.
+ *
+ * @return the expiration time in UTC
+ */
+ public DateTime getExpirationTimeInUtc();
+
+ /**
+ * Get the properties that make up this contribution. This map is immutable.
+ *
+ * @return the map of properties; never null
+ */
+ public Map<Name, Property> getProperties();
+
+ /**
+ * Get the children that make up this contribution. This list is immutable.
+ *
+ * @return the list of children; never null
+ */
+ public List<Segment> getChildren();
+}
Added: trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/contribution/EmptyContribution.java
===================================================================
--- trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/contribution/EmptyContribution.java (rev 0)
+++ trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/contribution/EmptyContribution.java 2008-07-24 19:52:13 UTC (rev 369)
@@ -0,0 +1,61 @@
+/*
+ * 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.connector.federation.contribution;
+
+import org.jboss.dna.spi.graph.Path;
+
+/**
+ * A source contribution that is empty. In other words, the source has no contribution to make.
+ * <p>
+ * Note that this is different than an unknown contribution, which may occur when a source is added to a federated repository
+ * after the contributions have already been determined for nodes. In this case, the new source's contribution for a node is not
+ * known and must be determined.
+ * </p>
+ *
+ * @author Randall Hauch
+ */
+public class EmptyContribution extends AbstractContribution {
+
+ /**
+ * This is the first version of this class. See the documentation of BasicMergePlan.serialVersionUID.
+ */
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * Create a contribution for the source with the supplied name.
+ *
+ * @param sourceName the name of the source, which may not be null or blank
+ */
+ public EmptyContribution( String sourceName ) {
+ super(sourceName);
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.jboss.dna.connector.federation.contribution.Contribution#getPathInSource()
+ */
+ public Path getPathInSource() {
+ return null;
+ }
+
+}
Added: trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/contribution/NodeContribution.java
===================================================================
--- trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/contribution/NodeContribution.java (rev 0)
+++ trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/contribution/NodeContribution.java 2008-07-24 19:52:13 UTC (rev 369)
@@ -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.connector.federation.contribution;
+
+import java.util.ArrayList;
+import java.util.List;
+import net.jcip.annotations.NotThreadSafe;
+import org.jboss.dna.spi.graph.Path;
+import org.jboss.dna.spi.graph.Property;
+import org.jboss.dna.spi.graph.Path.Segment;
+
+/**
+ * The contribution of a source to the information for a single federated node.
+ * <p>
+ * This class does return a mutable list of {@link #getChildren() children} and mutable map of {@link #getProperties() properties}
+ * .
+ * </p>
+ *
+ * @author Randall Hauch
+ */
+@NotThreadSafe
+public class NodeContribution extends PropertyContribution {
+
+ /**
+ * This is the first version of this class. See the documentation of BasicMergePlan.serialVersionUID.
+ */
+ private static final long serialVersionUID = 1L;
+
+ private List<Segment> children;
+
+ /**
+ * Create a contribution of node properties and children from the source with the supplied name.
+ *
+ * @param sourceName the name of the source, which may not be null or blank
+ * @param pathInSource the path in the source for this contributed information; may not be null
+ * @param properties the properties from the source; may not be null
+ * @param children the children from the source; may not be null or empty
+ */
+ public NodeContribution( String sourceName,
+ Path pathInSource,
+ Iterable<Property> properties,
+ Iterable<Segment> children ) {
+ super(sourceName, pathInSource, properties);
+ this.children = new ArrayList<Segment>(1);
+ for (Segment child : children) {
+ this.children.add(child);
+ }
+ }
+
+ /**
+ * Get the children that make up this contribution. This list is immutable.
+ *
+ * @return the list of children; never null
+ */
+ @Override
+ public List<Segment> getChildren() {
+ return this.children;
+ }
+}
Added: trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/contribution/PropertyContribution.java
===================================================================
--- trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/contribution/PropertyContribution.java (rev 0)
+++ trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/contribution/PropertyContribution.java 2008-07-24 19:52:13 UTC (rev 369)
@@ -0,0 +1,84 @@
+/*
+ * 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.connector.federation.contribution;
+
+import java.util.HashMap;
+import java.util.Map;
+import org.jboss.dna.spi.graph.Name;
+import org.jboss.dna.spi.graph.Path;
+import org.jboss.dna.spi.graph.Property;
+
+/**
+ * The record of a source contributing only properties to a node.
+ * <p>
+ * This class does return a mutable mutable map of {@link #getProperties() properties}.
+ * </p>
+ *
+ * @author Randall Hauch
+ */
+public class PropertyContribution extends AbstractContribution {
+
+ /**
+ * This is the first version of this class. See the documentation of BasicMergePlan.serialVersionUID.
+ */
+ private static final long serialVersionUID = 1L;
+
+ private final Map<Name, Property> properties;
+ private final Path pathInSource;
+
+ /**
+ * Create a contribution of node properties from the source with the supplied name.
+ *
+ * @param sourceName the name of the source, which may not be null or blank
+ * @param pathInSource the path in the source for this contributed information; may not be null
+ * @param properties the properties from the source; may not be null
+ */
+ public PropertyContribution( String sourceName,
+ Path pathInSource,
+ Iterable<Property> properties ) {
+ super(sourceName);
+ assert pathInSource != null;
+ this.properties = new HashMap<Name, Property>();
+ this.pathInSource = pathInSource;
+ for (Property property : properties) {
+ this.properties.put(property.getName(), property);
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public Map<Name, Property> getProperties() {
+ return this.properties;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.jboss.dna.connector.federation.contribution.Contribution#getPathInSource()
+ */
+ public Path getPathInSource() {
+ return pathInSource;
+ }
+
+}
Added: trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/executor/ActsOnProjectedPathCommand.java
===================================================================
--- trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/executor/ActsOnProjectedPathCommand.java (rev 0)
+++ trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/executor/ActsOnProjectedPathCommand.java 2008-07-24 19:52:13 UTC (rev 369)
@@ -0,0 +1,105 @@
+/*
+ * 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.connector.federation.executor;
+
+import org.jboss.dna.spi.graph.Path;
+import org.jboss.dna.spi.graph.commands.ActsOnPath;
+import org.jboss.dna.spi.graph.commands.GraphCommand;
+
+/**
+ * @author Randall Hauch
+ * @param <T> the command type
+ */
+public class ActsOnProjectedPathCommand<T extends GraphCommand> implements ActsOnPath, GraphCommand {
+
+ private final T delegate;
+ private final Path projectedPath;
+
+ protected ActsOnProjectedPathCommand( T delegate,
+ Path projectedPath ) {
+ assert delegate != null;
+ assert projectedPath != null;
+ this.delegate = delegate;
+ this.projectedPath = projectedPath;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.jboss.dna.spi.graph.commands.ActsOnPath#getPath()
+ */
+ public Path getPath() {
+ return projectedPath;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.jboss.dna.spi.graph.commands.GraphCommand#getError()
+ */
+ public Throwable getError() {
+ return delegate.getError();
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.jboss.dna.spi.graph.commands.GraphCommand#hasError()
+ */
+ public boolean hasError() {
+ return delegate.hasError();
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.jboss.dna.spi.graph.commands.GraphCommand#hasNoError()
+ */
+ public boolean hasNoError() {
+ return delegate.hasNoError();
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.jboss.dna.spi.graph.commands.GraphCommand#isCancelled()
+ */
+ public boolean isCancelled() {
+ return delegate.isCancelled();
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.jboss.dna.spi.graph.commands.GraphCommand#setError(java.lang.Throwable)
+ */
+ public void setError( Throwable error ) {
+ delegate.setError(error);
+ }
+
+ /**
+ * @return delegate
+ */
+ protected T getOriginalCommand() {
+ return delegate;
+ }
+}
Added: trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/executor/FederatingCommandExecutor.java
===================================================================
--- trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/executor/FederatingCommandExecutor.java (rev 0)
+++ trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/executor/FederatingCommandExecutor.java 2008-07-24 19:52:13 UTC (rev 369)
@@ -0,0 +1,331 @@
+/*
+ * 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.connector.federation.executor;
+
+import java.io.ObjectInputStream;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import net.jcip.annotations.NotThreadSafe;
+import org.jboss.dna.common.i18n.I18n;
+import org.jboss.dna.common.util.Logger;
+import org.jboss.dna.connector.federation.FederationI18n;
+import org.jboss.dna.connector.federation.Projection;
+import org.jboss.dna.connector.federation.contribution.Contribution;
+import org.jboss.dna.connector.federation.merge.BasicMergePlan;
+import org.jboss.dna.spi.graph.Binary;
+import org.jboss.dna.spi.graph.DateTime;
+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.ValueFactory;
+import org.jboss.dna.spi.graph.commands.GetChildrenCommand;
+import org.jboss.dna.spi.graph.commands.GetNodeCommand;
+import org.jboss.dna.spi.graph.commands.GetPropertiesCommand;
+import org.jboss.dna.spi.graph.commands.executor.AbstractCommandExecutor;
+import org.jboss.dna.spi.graph.commands.impl.BasicGetNodeCommand;
+import org.jboss.dna.spi.graph.commands.impl.BasicGetPropertiesCommand;
+import org.jboss.dna.spi.graph.connection.ExecutionEnvironment;
+import org.jboss.dna.spi.graph.connection.RepositoryConnection;
+import org.jboss.dna.spi.graph.connection.RepositoryConnectionFactories;
+import org.jboss.dna.spi.graph.connection.RepositoryConnectionFactory;
+import org.jboss.dna.spi.graph.connection.RepositorySource;
+import org.jboss.dna.spi.graph.connection.RepositorySourceException;
+
+/**
+ * @author Randall Hauch
+ */
+@NotThreadSafe
+public class FederatingCommandExecutor extends AbstractCommandExecutor {
+
+ private final Name mergePlanPropertyName;
+ private final Projection cacheProjection;
+ private final List<Projection> sourceProjections;
+ private final Set<String> sourceNames;
+ private final RepositoryConnectionFactories connectionFactories;
+ /** The set of all connections, including the cache connection */
+ private final Map<String, RepositoryConnection> connectionsBySourceName;
+ /** A direct reference to the cache connection */
+ private RepositoryConnection cacheConnection;
+
+ /**
+ * Create a command executor that federates (merges) the information from multiple sources described by the source
+ * projections. The resulting command executor does not first consult a cache for the merged information; if a cache is
+ * desired, see
+ * {@link #FederatingCommandExecutor(ExecutionEnvironment, String, Projection, List, RepositoryConnectionFactories)
+ * constructor} that takes a {@link Projection cache projection}.
+ *
+ * @param env the execution environment in which the executor will be run; may not be null
+ * @param sourceName the name of the {@link RepositorySource} that is making use of this executor; may not be null or empty
+ * @param sourceProjections the source projections; may not be null
+ * @param connectionFactories the factory for connection factory instances
+ */
+ public FederatingCommandExecutor( ExecutionEnvironment env,
+ String sourceName,
+ List<Projection> sourceProjections,
+ RepositoryConnectionFactories connectionFactories ) {
+ this(env, sourceName, null, sourceProjections, connectionFactories);
+ }
+
+ /**
+ * Create a command executor that federates (merges) the information from multiple sources described by the source
+ * projections. The resulting command executor will use the supplied {@link Projection cache projection} to identify the
+ * {@link Projection#getSourceName() repository source} for the cache as well as the {@link Projection#getRules() rules} for
+ * how the paths are mapped in the cache. This cache will be consulted first for the requested information, and will be kept
+ * up to date as changes are made to the federated information.
+ *
+ * @param env the execution environment in which the executor will be run; may not be null
+ * @param sourceName the name of the {@link RepositorySource} that is making use of this executor; may not be null or empty
+ * @param cacheProjection the projection used for the cached information; may be null if there is no cache
+ * @param sourceProjections the source projections; may not be null
+ * @param connectionFactories the factory for connection factory instances
+ */
+ public FederatingCommandExecutor( ExecutionEnvironment env,
+ String sourceName,
+ Projection cacheProjection,
+ List<Projection> sourceProjections,
+ RepositoryConnectionFactories connectionFactories ) {
+ super(env, sourceName);
+ assert sourceProjections != null;
+ assert connectionFactories != null;
+ this.cacheProjection = cacheProjection;
+ this.sourceProjections = sourceProjections;
+ this.connectionFactories = connectionFactories;
+ this.connectionsBySourceName = new HashMap<String, RepositoryConnection>();
+ this.mergePlanPropertyName = env.getValueFactories().getNameFactory().create("dna:mergePlan");
+ this.sourceNames = new HashSet<String>();
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.jboss.dna.spi.graph.commands.executor.AbstractCommandExecutor#close()
+ */
+ @Override
+ public void close() throws InterruptedException {
+ try {
+ super.close();
+ } finally {
+ // Make sure to close ALL open connections ...
+ for (RepositoryConnection connection : connectionsBySourceName.values()) {
+ if (connection == null) continue;
+ try {
+ connection.close();
+ } catch (Throwable t) {
+ Logger.getLogger(getClass()).debug("Error while closing connection to {0}", connection.getSourceName());
+ }
+ }
+ connectionsBySourceName.clear();
+ }
+ }
+
+ protected RepositoryConnection getConnectionToCache() throws RepositorySourceException, InterruptedException {
+ if (this.cacheConnection == null) {
+ this.cacheConnection = getConnection(this.cacheProjection);
+ }
+ assert this.cacheConnection != null;
+ return this.cacheConnection;
+ }
+
+ protected RepositoryConnection getConnection( Projection projection ) throws RepositorySourceException, InterruptedException {
+ String sourceName = projection.getSourceName();
+ RepositoryConnection connection = connectionsBySourceName.get(sourceName);
+ if (connection == null) {
+ RepositoryConnectionFactory connectionFactory = connectionFactories.getConnectionFactory(sourceName);
+ if (connectionFactory != null) {
+ connection = connectionFactory.getConnection();
+ }
+ connectionsBySourceName.put(sourceName, connection);
+ }
+ return connection;
+ }
+
+ /**
+ * {@inheritDoc}
+ * <p>
+ * This class overrides the {@link AbstractCommandExecutor#execute(GetNodeCommand) default behavior} and instead processes the
+ * command in a more efficient manner.
+ * </p>
+ *
+ * @see org.jboss.dna.spi.graph.commands.executor.AbstractCommandExecutor#execute(org.jboss.dna.spi.graph.commands.GetNodeCommand)
+ */
+ @Override
+ public void execute( GetNodeCommand command ) throws RepositorySourceException, InterruptedException {
+ BasicGetNodeCommand nodeInfo = getNode(command.getPath());
+ for (Property property : nodeInfo.getProperties().values()) {
+ command.setProperty(property);
+ }
+ command.setChildren(nodeInfo.getChildren());
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.jboss.dna.spi.graph.commands.executor.AbstractCommandExecutor#execute(org.jboss.dna.spi.graph.commands.GetPropertiesCommand)
+ */
+ @Override
+ public void execute( GetPropertiesCommand command ) throws RepositorySourceException, InterruptedException {
+ BasicGetNodeCommand nodeInfo = getNode(command.getPath());
+ for (Property property : nodeInfo.getProperties().values()) {
+ command.setProperty(property);
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.jboss.dna.spi.graph.commands.executor.AbstractCommandExecutor#execute(org.jboss.dna.spi.graph.commands.GetChildrenCommand)
+ */
+ @Override
+ public void execute( GetChildrenCommand command ) throws RepositorySourceException, InterruptedException {
+ BasicGetNodeCommand nodeInfo = getNode(command.getPath());
+ command.setChildren(nodeInfo.getChildren());
+ }
+
+ /**
+ * Get the node information from the underlying sources or, if possible, from the cache.
+ *
+ * @param path the path of the node to be returned
+ * @return the node information
+ * @throws RepositorySourceException
+ * @throws InterruptedException
+ */
+ protected BasicGetNodeCommand getNode( Path path ) throws RepositorySourceException, InterruptedException {
+ // Check the cache first ...
+ RepositoryConnection cacheConnection = getConnectionToCache();
+ BasicGetNodeCommand fromCache = new BasicGetNodeCommand(path);
+ cacheConnection.execute(getEnvironment(), fromCache);
+ if (fromCache.hasError()) return fromCache;
+
+ // Look up the merge plan ...
+ BasicMergePlan basicMergePlan = getMergePlan(fromCache);
+ if (basicMergePlan != null) {
+ if (isCurrent(path, basicMergePlan)) return fromCache;
+ // Some of the merge plan is out of date, so we need to read the information from those regions that are expired ...
+ BasicMergePlan newMergePlan = new BasicMergePlan();
+ // for (Projection projection : sourceProjections) {
+ // // Does this region apply to the path ...
+ // if (projection.appliesTo(path)) {
+ // // Get any existing contribution ...
+ // Contribution contribution = mergePlan.getContributionFrom(region.getSourceName());
+ // if (contribution == null || contribution.isExpired(getCurrentTimeInUtc())) {
+ // contribution = getContribution(contribution.getSourceName(), path);
+ // }
+ // newMergePlan.addContribution(contribution);
+ // }
+ // }
+ // for ( Contribution contribution : mergePlan.getContributions() ) {
+ // // Is the contribution still represented by a region?
+ //
+ // if ( contribution.isExpired(getCurrentTimeInUtc())) {
+ // contribution = getContribution(contribution.getSourceName(),path);
+ // }
+ // newMergePlan.addContribution(contribution);
+ // }
+
+ // What about other (new) regions?
+ } else {
+ // At this point, there is no merge plan, so read information from the sources ...
+ // for (FederatedRegion region : regions) {
+ // if (!region.appliesTo(path)) continue;
+ // // Issue a command to get the node from the
+ // // BasicGetNode
+ // }
+ }
+ // And read the information from any new region ...
+ return null;
+ }
+
+ protected Contribution getContribution( String sourceName,
+ Path path ) {
+ return null;
+ }
+
+ protected BasicMergePlan getMergePlan( BasicGetPropertiesCommand command ) {
+ Property mergePlanProperty = command.getProperties().get(mergePlanPropertyName);
+ if (mergePlanProperty == null || mergePlanProperty.isEmpty()) {
+ return null;
+ }
+ ValueFactory<Binary> binaryFactory = getEnvironment().getValueFactories().getBinaryFactory();
+ Binary binaryValue = binaryFactory.create(mergePlanProperty.getValues().next());
+ binaryValue.acquire();
+ ObjectInputStream stream = null;
+ BasicMergePlan basicMergePlan = null;
+ RepositorySourceException error = null;
+ try {
+ stream = new ObjectInputStream(binaryValue.getStream());
+ basicMergePlan = (BasicMergePlan)stream.readObject();
+ } catch (Throwable err) {
+ I18n msg = FederationI18n.errorReadingMergePlan;
+ error = new RepositorySourceException(getSourceName(), msg.text(command.getPath()), err);
+ throw error;
+ } finally {
+ try {
+ if (stream != null) stream.close();
+ } catch (Throwable err) {
+ if (error == null) {
+ I18n msg = FederationI18n.errorReadingMergePlan;
+ error = new RepositorySourceException(getSourceName(), msg.text(command.getPath()), err);
+ throw error;
+ }
+ } finally {
+ binaryValue.release();
+ }
+ }
+ return basicMergePlan;
+ }
+
+ /**
+ * Determine if the supplied plan is considered current
+ *
+ * @param path the path of the node at which (or below which) the merge plan applies
+ * @param plan the merge plan
+ * @return true if the merge plan is current, or false if it needs to be (at least partially) rebuilt
+ */
+ protected boolean isCurrent( Path path,
+ BasicMergePlan plan ) {
+ // First check the time ...
+ DateTime now = getCurrentTimeInUtc();
+ if (plan.isExpired(now)) return false;
+
+ // Does the plan have any contributions from sources that don't exist ?
+ for (String contributingSource : plan.getNamesOfContributingSources()) {
+ if (!sourceNames.contains(contributingSource)) return false;
+ }
+
+ // Determine if any new source projections exists that aren't part of the plan ...
+ for (String sourceName : sourceNames) {
+ if (plan.isSource(sourceName)) continue;
+ // The source is new ... see whether there are any regions that apply ...
+ // for (FederatedRegion region : this.regionsBySourceName.get(sourceName)) {
+ // // If the region's path is not at/above the path, the region doesn't matter
+ // if (!region.appliesTo(path)) continue;
+ // // The region applies to the path ...
+ // return false;
+ // }
+ }
+ return true;
+ }
+
+}
Added: trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/executor/ProjectedCopyBranchCommand.java
===================================================================
--- trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/executor/ProjectedCopyBranchCommand.java (rev 0)
+++ trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/executor/ProjectedCopyBranchCommand.java 2008-07-24 19:52:13 UTC (rev 369)
@@ -0,0 +1,37 @@
+/*
+ * 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.connector.federation.executor;
+
+import org.jboss.dna.spi.graph.Path;
+import org.jboss.dna.spi.graph.commands.CopyBranchCommand;
+
+/**
+ * @author Randall Hauch
+ */
+public class ProjectedCopyBranchCommand extends ProjectedCopyNodeCommand implements CopyBranchCommand {
+
+ public ProjectedCopyBranchCommand( CopyBranchCommand delegate,
+ Path projectedPath,
+ Path newProjectedPath ) {
+ super(delegate, projectedPath, newProjectedPath);
+ }
+}
Added: trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/executor/ProjectedCopyNodeCommand.java
===================================================================
--- trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/executor/ProjectedCopyNodeCommand.java (rev 0)
+++ trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/executor/ProjectedCopyNodeCommand.java 2008-07-24 19:52:13 UTC (rev 369)
@@ -0,0 +1,51 @@
+/*
+ * 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.connector.federation.executor;
+
+import org.jboss.dna.spi.graph.Path;
+import org.jboss.dna.spi.graph.commands.CopyNodeCommand;
+
+/**
+ * @author Randall Hauch
+ */
+public class ProjectedCopyNodeCommand extends ActsOnProjectedPathCommand<CopyNodeCommand> implements CopyNodeCommand {
+
+ private final Path newProjectedPath;
+
+ public ProjectedCopyNodeCommand( CopyNodeCommand delegate,
+ Path projectedPath,
+ Path newProjectedPath ) {
+ super(delegate, projectedPath);
+ assert newProjectedPath != null;
+ this.newProjectedPath = newProjectedPath;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.jboss.dna.spi.graph.commands.CopyNodeCommand#getNewPath()
+ */
+ public Path getNewPath() {
+ return newProjectedPath;
+ }
+
+}
Added: trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/executor/ProjectedCreateNodeCommand.java
===================================================================
--- trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/executor/ProjectedCreateNodeCommand.java (rev 0)
+++ trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/executor/ProjectedCreateNodeCommand.java 2008-07-24 19:52:13 UTC (rev 369)
@@ -0,0 +1,67 @@
+/*
+ * 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.connector.federation.executor;
+
+import org.jboss.dna.spi.graph.Path;
+import org.jboss.dna.spi.graph.Property;
+import org.jboss.dna.spi.graph.commands.CreateNodeCommand;
+import org.jboss.dna.spi.graph.commands.NodeConflictBehavior;
+
+/**
+ * @author Randall Hauch
+ */
+public class ProjectedCreateNodeCommand extends ActsOnProjectedPathCommand<CreateNodeCommand> implements CreateNodeCommand {
+
+ public ProjectedCreateNodeCommand( CreateNodeCommand delegate,
+ Path projectedPath ) {
+ super(delegate, projectedPath);
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.jboss.dna.spi.graph.commands.CreateNodeCommand#getConflictBehavior()
+ */
+ public NodeConflictBehavior getConflictBehavior() {
+ return getOriginalCommand().getConflictBehavior();
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.jboss.dna.spi.graph.commands.CreateNodeCommand#getProperties()
+ */
+ public Iterable<Property> getProperties() {
+ return getOriginalCommand().getProperties();
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see java.lang.Comparable#compareTo(java.lang.Object)
+ */
+ public int compareTo( CreateNodeCommand that ) {
+ if (this == that) return 0;
+ return this.getPath().compareTo(that.getPath());
+ }
+
+}
Added: trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/executor/ProjectedDeleteBranchCommand.java
===================================================================
--- trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/executor/ProjectedDeleteBranchCommand.java (rev 0)
+++ trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/executor/ProjectedDeleteBranchCommand.java 2008-07-24 19:52:13 UTC (rev 369)
@@ -0,0 +1,37 @@
+/*
+ * 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.connector.federation.executor;
+
+import org.jboss.dna.spi.graph.Path;
+import org.jboss.dna.spi.graph.commands.DeleteBranchCommand;
+
+/**
+ * @author Randall Hauch
+ */
+public class ProjectedDeleteBranchCommand extends ActsOnProjectedPathCommand<DeleteBranchCommand> implements DeleteBranchCommand {
+
+ public ProjectedDeleteBranchCommand( DeleteBranchCommand delegate,
+ Path projectedPath ) {
+ super(delegate, projectedPath);
+ }
+
+}
Added: trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/executor/ProjectedGetChildrenCommand.java
===================================================================
--- trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/executor/ProjectedGetChildrenCommand.java (rev 0)
+++ trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/executor/ProjectedGetChildrenCommand.java 2008-07-24 19:52:13 UTC (rev 369)
@@ -0,0 +1,117 @@
+/*
+ * 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.connector.federation.executor;
+
+import java.util.Iterator;
+import org.jboss.dna.spi.cache.CachePolicy;
+import org.jboss.dna.spi.graph.Name;
+import org.jboss.dna.spi.graph.Path;
+import org.jboss.dna.spi.graph.Path.Segment;
+import org.jboss.dna.spi.graph.commands.GetChildrenCommand;
+
+/**
+ * @author Randall Hauch
+ */
+public class ProjectedGetChildrenCommand extends ActsOnProjectedPathCommand<GetChildrenCommand> implements GetChildrenCommand {
+
+ /**
+ */
+ private static final long serialVersionUID = 1L;
+
+ public ProjectedGetChildrenCommand( GetChildrenCommand delegate,
+ Path projectedPath ) {
+ super(delegate, projectedPath);
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.jboss.dna.spi.graph.commands.GetChildrenCommand#setChild(org.jboss.dna.spi.graph.Name)
+ */
+ public void setChild( Name nameOfChild ) {
+ getOriginalCommand().setChild(nameOfChild);
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.jboss.dna.spi.graph.commands.GetChildrenCommand#setChildren(java.util.Iterator)
+ */
+ public void setChildren( Iterator<Segment> namesOfChildren ) {
+ getOriginalCommand().setChildren(namesOfChildren);
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.jboss.dna.spi.graph.commands.GetChildrenCommand#setChildren(java.lang.Iterable)
+ */
+ public void setChildren( Iterable<Segment> namesOfChildren ) {
+ getOriginalCommand().setChildren(namesOfChildren);
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.jboss.dna.spi.graph.commands.GetChildrenCommand#setChildren(org.jboss.dna.spi.graph.Path.Segment[])
+ */
+ public void setChildren( Segment... namesOfChildren ) {
+ getOriginalCommand().setChildren(namesOfChildren);
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.jboss.dna.spi.graph.commands.GetChildrenCommand#setNoChildren()
+ */
+ public void setNoChildren() {
+ getOriginalCommand().setNoChildren();
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.jboss.dna.spi.cache.Cacheable#getCachePolicy()
+ */
+ public CachePolicy getCachePolicy() {
+ return getOriginalCommand().getCachePolicy();
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.jboss.dna.spi.cache.Cacheable#getTimeLoaded()
+ */
+ public long getTimeLoaded() {
+ return getOriginalCommand().getTimeLoaded();
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.jboss.dna.spi.cache.Cacheable#setCachePolicy(org.jboss.dna.spi.cache.CachePolicy)
+ */
+ public void setCachePolicy( CachePolicy cachePolicy ) {
+ getOriginalCommand().setCachePolicy(cachePolicy);
+ }
+
+}
Added: trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/executor/ProjectedGetNodeCommand.java
===================================================================
--- trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/executor/ProjectedGetNodeCommand.java (rev 0)
+++ trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/executor/ProjectedGetNodeCommand.java 2008-07-24 19:52:13 UTC (rev 369)
@@ -0,0 +1,52 @@
+/*
+ * 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.connector.federation.executor;
+
+import org.jboss.dna.spi.graph.Path;
+import org.jboss.dna.spi.graph.Property;
+import org.jboss.dna.spi.graph.commands.GetChildrenCommand;
+import org.jboss.dna.spi.graph.commands.GetNodeCommand;
+
+/**
+ * @author Randall Hauch
+ */
+public class ProjectedGetNodeCommand extends ProjectedGetChildrenCommand implements GetNodeCommand {
+
+ /**
+ */
+ private static final long serialVersionUID = 1L;
+
+ public ProjectedGetNodeCommand( GetChildrenCommand delegate,
+ Path projectedPath ) {
+ super(delegate, projectedPath);
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.jboss.dna.spi.graph.commands.GetPropertiesCommand#setProperty(org.jboss.dna.spi.graph.Property)
+ */
+ public void setProperty( Property property ) {
+ ((GetNodeCommand)getOriginalCommand()).setProperty(property);
+ }
+
+}
Added: trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/executor/ProjectedGetPropertiesCommand.java
===================================================================
--- trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/executor/ProjectedGetPropertiesCommand.java (rev 0)
+++ trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/executor/ProjectedGetPropertiesCommand.java 2008-07-24 19:52:13 UTC (rev 369)
@@ -0,0 +1,80 @@
+/*
+ * 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.connector.federation.executor;
+
+import org.jboss.dna.spi.cache.CachePolicy;
+import org.jboss.dna.spi.graph.Path;
+import org.jboss.dna.spi.graph.Property;
+import org.jboss.dna.spi.graph.commands.GetPropertiesCommand;
+
+/**
+ * @author Randall Hauch
+ */
+public class ProjectedGetPropertiesCommand extends ActsOnProjectedPathCommand<GetPropertiesCommand>
+ implements GetPropertiesCommand {
+
+ /**
+ */
+ private static final long serialVersionUID = 1L;
+
+ public ProjectedGetPropertiesCommand( GetPropertiesCommand delegate,
+ Path projectedPath ) {
+ super(delegate, projectedPath);
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.jboss.dna.spi.cache.Cacheable#getCachePolicy()
+ */
+ public CachePolicy getCachePolicy() {
+ return getOriginalCommand().getCachePolicy();
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.jboss.dna.spi.cache.Cacheable#getTimeLoaded()
+ */
+ public long getTimeLoaded() {
+ return getOriginalCommand().getTimeLoaded();
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.jboss.dna.spi.cache.Cacheable#setCachePolicy(org.jboss.dna.spi.cache.CachePolicy)
+ */
+ public void setCachePolicy( CachePolicy cachePolicy ) {
+ getOriginalCommand().setCachePolicy(cachePolicy);
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.jboss.dna.spi.graph.commands.GetPropertiesCommand#setProperty(org.jboss.dna.spi.graph.Property)
+ */
+ public void setProperty( Property property ) {
+ getOriginalCommand().setProperty(property);
+ }
+
+}
Added: trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/executor/ProjectedMoveBranchCommand.java
===================================================================
--- trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/executor/ProjectedMoveBranchCommand.java (rev 0)
+++ trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/executor/ProjectedMoveBranchCommand.java 2008-07-24 19:52:13 UTC (rev 369)
@@ -0,0 +1,61 @@
+/*
+ * 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.connector.federation.executor;
+
+import org.jboss.dna.spi.graph.Path;
+import org.jboss.dna.spi.graph.commands.MoveBranchCommand;
+import org.jboss.dna.spi.graph.commands.NodeConflictBehavior;
+
+/**
+ * @author Randall Hauch
+ */
+public class ProjectedMoveBranchCommand extends ActsOnProjectedPathCommand<MoveBranchCommand> implements MoveBranchCommand {
+
+ private final Path newProjectedPath;
+
+ public ProjectedMoveBranchCommand( MoveBranchCommand delegate,
+ Path projectedPath,
+ Path newProjectedPath ) {
+ super(delegate, projectedPath);
+ assert newProjectedPath != null;
+ this.newProjectedPath = newProjectedPath;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.jboss.dna.spi.graph.commands.MoveBranchCommand#getConflictBehavior()
+ */
+ public NodeConflictBehavior getConflictBehavior() {
+ return getOriginalCommand().getConflictBehavior();
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.jboss.dna.spi.graph.commands.MoveBranchCommand#getNewPath()
+ */
+ public Path getNewPath() {
+ return this.newProjectedPath;
+ }
+
+}
Added: trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/executor/ProjectedRecordBranchCommand.java
===================================================================
--- trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/executor/ProjectedRecordBranchCommand.java (rev 0)
+++ trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/executor/ProjectedRecordBranchCommand.java 2008-07-24 19:52:13 UTC (rev 369)
@@ -0,0 +1,82 @@
+/*
+ * 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.connector.federation.executor;
+
+import java.util.Iterator;
+import org.jboss.dna.spi.graph.Path;
+import org.jboss.dna.spi.graph.Property;
+import org.jboss.dna.spi.graph.commands.RecordBranchCommand;
+
+/**
+ * @author Randall Hauch
+ */
+public class ProjectedRecordBranchCommand extends ActsOnProjectedPathCommand<RecordBranchCommand> implements RecordBranchCommand {
+
+ public ProjectedRecordBranchCommand( RecordBranchCommand delegate,
+ Path projectedPath ) {
+ super(delegate, projectedPath);
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.jboss.dna.spi.graph.commands.RecordBranchCommand#record(org.jboss.dna.spi.graph.Path, java.lang.Iterable)
+ */
+ public boolean record( Path path,
+ Iterable<Property> properties ) {
+ path = relativePathFrom(path);
+ return getOriginalCommand().record(path, properties);
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.jboss.dna.spi.graph.commands.RecordBranchCommand#record(org.jboss.dna.spi.graph.Path, java.util.Iterator)
+ */
+ public boolean record( Path path,
+ Iterator<Property> properties ) {
+ path = relativePathFrom(path);
+ return getOriginalCommand().record(path, properties);
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.jboss.dna.spi.graph.commands.RecordBranchCommand#record(org.jboss.dna.spi.graph.Path,
+ * org.jboss.dna.spi.graph.Property[])
+ */
+ public boolean record( Path path,
+ Property... properties ) {
+ path = relativePathFrom(path);
+ return getOriginalCommand().record(path, properties);
+ }
+
+ protected Path relativePathFrom( Path path ) {
+ if (path == null) return null;
+ if (path.isAbsolute()) {
+ // The path is absolute, so compute the relative path w/r/t the new path ...
+ path = path.relativeTo(this.getPath());
+ }
+ return path;
+ }
+
+}
Added: trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/executor/ProjectedSetPropertiesCommand.java
===================================================================
--- trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/executor/ProjectedSetPropertiesCommand.java (rev 0)
+++ trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/executor/ProjectedSetPropertiesCommand.java 2008-07-24 19:52:13 UTC (rev 369)
@@ -0,0 +1,48 @@
+/*
+ * 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.connector.federation.executor;
+
+import org.jboss.dna.spi.graph.Path;
+import org.jboss.dna.spi.graph.Property;
+import org.jboss.dna.spi.graph.commands.SetPropertiesCommand;
+
+/**
+ * @author Randall Hauch
+ */
+public class ProjectedSetPropertiesCommand extends ActsOnProjectedPathCommand<SetPropertiesCommand>
+ implements SetPropertiesCommand {
+
+ public ProjectedSetPropertiesCommand( SetPropertiesCommand delegate,
+ Path projectedPath ) {
+ super(delegate, projectedPath);
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.jboss.dna.spi.graph.commands.ActsOnProperties#getProperties()
+ */
+ public Iterable<Property> getProperties() {
+ return getOriginalCommand().getProperties();
+ }
+
+}
Added: trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/executor/SingleProjectionCommandExecutor.java
===================================================================
--- trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/executor/SingleProjectionCommandExecutor.java (rev 0)
+++ trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/executor/SingleProjectionCommandExecutor.java 2008-07-24 19:52:13 UTC (rev 369)
@@ -0,0 +1,247 @@
+/*
+ * 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.connector.federation.executor;
+
+import java.util.Set;
+import net.jcip.annotations.NotThreadSafe;
+import org.jboss.dna.connector.federation.Projection;
+import org.jboss.dna.spi.graph.DateTime;
+import org.jboss.dna.spi.graph.Path;
+import org.jboss.dna.spi.graph.PathFactory;
+import org.jboss.dna.spi.graph.commands.CopyBranchCommand;
+import org.jboss.dna.spi.graph.commands.CopyNodeCommand;
+import org.jboss.dna.spi.graph.commands.CreateNodeCommand;
+import org.jboss.dna.spi.graph.commands.DeleteBranchCommand;
+import org.jboss.dna.spi.graph.commands.GetChildrenCommand;
+import org.jboss.dna.spi.graph.commands.GetNodeCommand;
+import org.jboss.dna.spi.graph.commands.GetPropertiesCommand;
+import org.jboss.dna.spi.graph.commands.MoveBranchCommand;
+import org.jboss.dna.spi.graph.commands.RecordBranchCommand;
+import org.jboss.dna.spi.graph.commands.SetPropertiesCommand;
+import org.jboss.dna.spi.graph.commands.executor.AbstractCommandExecutor;
+import org.jboss.dna.spi.graph.connection.ExecutionEnvironment;
+import org.jboss.dna.spi.graph.connection.RepositoryConnection;
+import org.jboss.dna.spi.graph.connection.RepositoryConnectionFactories;
+import org.jboss.dna.spi.graph.connection.RepositoryConnectionFactory;
+import org.jboss.dna.spi.graph.connection.RepositorySource;
+import org.jboss.dna.spi.graph.connection.RepositorySourceException;
+
+/**
+ * @author Randall Hauch
+ */
+@NotThreadSafe
+public class SingleProjectionCommandExecutor extends AbstractCommandExecutor {
+
+ private final Projection projection;
+ private final PathFactory pathFactory;
+ private final RepositoryConnectionFactories factories;
+ private RepositoryConnection connection;
+
+ /**
+ * @param env the execution environment in which the executor will be run; may not be null
+ * @param sourceName the name of the {@link RepositorySource} that is making use of this executor; may not be null or empty
+ * @param projection the projection used for the cached information; may not be null and must have exactly one
+ * {@link Projection#getRules() rule}
+ * @param connectionFactories the factory for connection factory instances
+ */
+ public SingleProjectionCommandExecutor( ExecutionEnvironment env,
+ String sourceName,
+ Projection projection,
+ RepositoryConnectionFactories connectionFactories ) {
+ this(env, sourceName, null, projection, connectionFactories);
+ }
+
+ /**
+ * @param env the execution environment in which the executor will be run; may not be null
+ * @param sourceName the name of the {@link RepositorySource} that is making use of this executor; may not be null or empty
+ * @param now the current time; may be null if the system time is to be used
+ * @param projection the projection used for the cached information; may not be null and must have exactly one
+ * {@link Projection#getRules() rule}
+ * @param connectionFactories the factory for connection factory instances
+ */
+ public SingleProjectionCommandExecutor( ExecutionEnvironment env,
+ String sourceName,
+ DateTime now,
+ Projection projection,
+ RepositoryConnectionFactories connectionFactories ) {
+ super(env, sourceName, now);
+ assert connectionFactories != null;
+ assert projection != null;
+ assert projection.getRules().size() == 1;
+ this.projection = projection;
+ this.factories = connectionFactories;
+ this.pathFactory = env.getValueFactories().getPathFactory();
+ assert this.pathFactory != null;
+ }
+
+ protected RepositoryConnection getConnection() throws RepositorySourceException, InterruptedException {
+ if (connection == null) {
+ // Create a connection ...
+ RepositoryConnectionFactory connectionFactory = this.factories.getConnectionFactory(this.projection.getSourceName());
+ connection = connectionFactory.getConnection();
+ }
+ return connection;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.jboss.dna.spi.graph.commands.executor.AbstractCommandExecutor#close()
+ */
+ @Override
+ public void close() throws InterruptedException {
+ if (this.connection != null) {
+ try {
+ this.connection.close();
+ } finally {
+ this.connection = null;
+ }
+ }
+ super.close();
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.jboss.dna.spi.graph.commands.executor.AbstractCommandExecutor#execute(org.jboss.dna.spi.graph.commands.GetChildrenCommand)
+ */
+ @Override
+ public void execute( GetChildrenCommand command ) throws RepositorySourceException, InterruptedException {
+ Path pathInSource = getPathInSource(command.getPath());
+ getConnection().execute(this.getEnvironment(), new ProjectedGetChildrenCommand(command, pathInSource));
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.jboss.dna.spi.graph.commands.executor.AbstractCommandExecutor#execute(org.jboss.dna.spi.graph.commands.GetPropertiesCommand)
+ */
+ @Override
+ public void execute( GetPropertiesCommand command ) throws RepositorySourceException, InterruptedException {
+ Path pathInSource = getPathInSource(command.getPath());
+ getConnection().execute(this.getEnvironment(), new ProjectedGetPropertiesCommand(command, pathInSource));
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.jboss.dna.spi.graph.commands.executor.AbstractCommandExecutor#execute(org.jboss.dna.spi.graph.commands.GetNodeCommand)
+ */
+ @Override
+ public void execute( GetNodeCommand command ) throws RepositorySourceException, InterruptedException {
+ Path pathInSource = getPathInSource(command.getPath());
+ getConnection().execute(this.getEnvironment(), new ProjectedGetNodeCommand(command, pathInSource));
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.jboss.dna.spi.graph.commands.executor.AbstractCommandExecutor#execute(org.jboss.dna.spi.graph.commands.CreateNodeCommand)
+ */
+ @Override
+ public void execute( CreateNodeCommand command ) throws RepositorySourceException, InterruptedException {
+ Path pathInSource = getPathInSource(command.getPath());
+ getConnection().execute(this.getEnvironment(), new ProjectedCreateNodeCommand(command, pathInSource));
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.jboss.dna.spi.graph.commands.executor.AbstractCommandExecutor#execute(org.jboss.dna.spi.graph.commands.SetPropertiesCommand)
+ */
+ @Override
+ public void execute( SetPropertiesCommand command ) throws RepositorySourceException, InterruptedException {
+ Path pathInSource = getPathInSource(command.getPath());
+ getConnection().execute(this.getEnvironment(), new ProjectedSetPropertiesCommand(command, pathInSource));
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.jboss.dna.spi.graph.commands.executor.AbstractCommandExecutor#execute(org.jboss.dna.spi.graph.commands.DeleteBranchCommand)
+ */
+ @Override
+ public void execute( DeleteBranchCommand command ) throws RepositorySourceException, InterruptedException {
+ Path pathInSource = getPathInSource(command.getPath());
+ getConnection().execute(this.getEnvironment(), new ProjectedDeleteBranchCommand(command, pathInSource));
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.jboss.dna.spi.graph.commands.executor.AbstractCommandExecutor#execute(org.jboss.dna.spi.graph.commands.MoveBranchCommand)
+ */
+ @Override
+ public void execute( MoveBranchCommand command ) throws RepositorySourceException, InterruptedException {
+ Path pathInSource = getPathInSource(command.getPath());
+ Path newPathInSource = getPathInSource(command.getNewPath());
+ getConnection().execute(this.getEnvironment(), new ProjectedMoveBranchCommand(command, pathInSource, newPathInSource));
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.jboss.dna.spi.graph.commands.executor.AbstractCommandExecutor#execute(org.jboss.dna.spi.graph.commands.RecordBranchCommand)
+ */
+ @Override
+ public void execute( RecordBranchCommand command ) throws RepositorySourceException, InterruptedException {
+ Path pathInSource = getPathInSource(command.getPath());
+ getConnection().execute(this.getEnvironment(), new ProjectedRecordBranchCommand(command, pathInSource));
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.jboss.dna.spi.graph.commands.executor.AbstractCommandExecutor#execute(org.jboss.dna.spi.graph.commands.CopyBranchCommand)
+ */
+ @Override
+ public void execute( CopyBranchCommand command ) throws RepositorySourceException, InterruptedException {
+ Path pathInSource = getPathInSource(command.getPath());
+ Path newPathInSource = getPathInSource(command.getNewPath());
+ getConnection().execute(this.getEnvironment(), new ProjectedCopyBranchCommand(command, pathInSource, newPathInSource));
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.jboss.dna.spi.graph.commands.executor.AbstractCommandExecutor#execute(org.jboss.dna.spi.graph.commands.CopyNodeCommand)
+ */
+ @Override
+ public void execute( CopyNodeCommand command ) throws RepositorySourceException, InterruptedException {
+ Path pathInSource = getPathInSource(command.getPath());
+ Path newPathInSource = getPathInSource(command.getNewPath());
+ getConnection().execute(this.getEnvironment(), new ProjectedCopyNodeCommand(command, pathInSource, newPathInSource));
+ }
+
+ protected Path getPathInSource( Path pathInRepository ) {
+ Set<Path> paths = this.projection.getPathsInSource(pathInRepository, pathFactory);
+ if (!paths.isEmpty()) {
+ return paths.iterator().next();
+ }
+ return this.projection.getPathsInSource(pathInRepository, pathFactory).iterator().next();
+ }
+
+ protected Path getPathInRepository( Path pathInSource ) {
+ return this.projection.getPathsInRepository(pathInSource, pathFactory).iterator().next();
+ }
+
+}
Added: trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/merge/BasicFederatedNode.java
===================================================================
--- trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/merge/BasicFederatedNode.java (rev 0)
+++ trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/merge/BasicFederatedNode.java 2008-07-24 19:52:13 UTC (rev 369)
@@ -0,0 +1,148 @@
+/*
+ * 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.connector.federation.merge;
+
+import java.util.HashSet;
+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
+ */
+@ThreadSafe
+public class BasicFederatedNode implements FederatedNode {
+
+ private final UUID uuid;
+
+ // private Name name;
+
+ /**
+ * Create a new federated node instance.
+ *
+ * @param uuid the UUID; may not be null
+ */
+ public BasicFederatedNode( UUID uuid ) {
+ assert uuid != null;
+ this.uuid = uuid;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public UUID getUuid() {
+ return uuid;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public Name getName() {
+ return null;
+ }
+
+ /**
+ * @param name Sets name to the specified value; may not be null
+ */
+ public void setName( Name name ) {
+ assert name != null;
+ // this.name = name;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public Set<String> getContributingSources() {
+ Set<String> names = new HashSet<String>();
+ return names;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public Iterator<Property> getProperties() {
+ // Compute merged properties ...
+ return null;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public Property getProperty( Name propertyName ) {
+ return null;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public int getPropertyCount() {
+ return 0;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public Iterator<Name> getPropertyNames() {
+ return null;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void removeAllProperties() {
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void setAllProperties( Property... properties ) {
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void setAllProperties( Iterable<Property> properties ) {
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void setProperties( Property... properties ) {
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void setProperties( Iterable<Property> properties ) {
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public Property setPropertyIfAbsent( Property property ) {
+ return null;
+ }
+
+}
Added: trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/merge/BasicMergePlan.java
===================================================================
--- trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/merge/BasicMergePlan.java (rev 0)
+++ trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/merge/BasicMergePlan.java 2008-07-24 19:52:13 UTC (rev 369)
@@ -0,0 +1,205 @@
+/*
+ * 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.connector.federation.merge;
+
+import java.io.InvalidClassException;
+import java.io.Serializable;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+import net.jcip.annotations.NotThreadSafe;
+import org.jboss.dna.connector.federation.contribution.Contribution;
+import org.jboss.dna.connector.federation.contribution.EmptyContribution;
+import org.jboss.dna.spi.graph.DateTime;
+import org.jboss.dna.spi.graph.Name;
+import org.jboss.dna.spi.graph.Property;
+
+/**
+ * This class represents the details about how information from different sources are merged into a single federated node.
+ * <p>
+ * A merge plan basically consists of the individual contribution from each source and the information about how these
+ * contributions were merged into the single federated node.
+ * </p>
+ * <p>
+ * Merge plans are designed to be {@link Serializable serializable}, as they are persisted on the federated node and deserialized
+ * to assist in the management of the federated node.
+ * </p>
+ *
+ * @author Randall Hauch
+ */
+@NotThreadSafe
+public class BasicMergePlan implements Serializable {
+
+ /**
+ * Define the earliest version of this class that is supported. The Java runtime, upon deserialization, compares the
+ * serialized object's version to this, and if less than this version will throw a {@link InvalidClassException}. If, however,
+ * the serialized object's version is compatible with this class, it will be deserialized successfully.
+ * <p>
+ * <a href="http://java.sun.com/j2se/1.5.0/docs/guide/serialization/spec/version.html...">Sun's documentation</a> describes
+ * the following changes can be made without negatively affecting the deserialization of older versions:
+ * <ul>
+ * <li>Adding fields - When the class being reconstituted has a field that does not occur in the stream, that field in the
+ * object will be initialized to the default value for its type. If class-specific initialization is needed, the class may
+ * provide a readObject method that can initialize the field to nondefault values.</i>
+ * <li>Adding classes - The stream will contain the type hierarchy of each object in the stream. Comparing this hierarchy in
+ * the stream with the current class can detect additional classes. Since there is no information in the stream from which to
+ * initialize the object, the class's fields will be initialized to the default values.</i>
+ * <li>Removing classes - Comparing the class hierarchy in the stream with that of the current class can detect that a class
+ * has been deleted. In this case, the fields and objects corresponding to that class are read from the stream. Primitive
+ * fields are discarded, but the objects referenced by the deleted class are created, since they may be referred to later in
+ * the stream. They will be garbage-collected when the stream is garbage-collected or reset.</i>
+ * <li>Adding writeObject/readObject methods - If the version reading the stream has these methods then readObject is
+ * expected, as usual, to read the required data written to the stream by the default serialization. It should call
+ * defaultReadObject first before reading any optional data. The writeObject method is expected as usual to call
+ * defaultWriteObject to write the required data and then may write optional data.</i>
+ * <li>Removing writeObject/readObject methods - If the class reading the stream does not have these methods, the required
+ * data will be read by default serialization, and the optional data will be discarded.</i>
+ * <li>Adding java.io.Serializable - This is equivalent to adding types. There will be no values in the stream for this class
+ * so its fields will be initialized to default values. The support for subclassing nonserializable classes requires that the
+ * class's supertype have a no-arg constructor and the class itself will be initialized to default values. If the no-arg
+ * constructor is not available, the InvalidClassException is thrown.</i>
+ * <li>Changing the access to a field - The access modifiers public, package, protected, and private have no effect on the
+ * ability of serialization to assign values to the fields.</i>
+ * <li>Changing a field from static to nonstatic or transient to nontransient - When relying on default serialization to
+ * compute the serializable fields, this change is equivalent to adding a field to the class. The new field will be written to
+ * the stream but earlier classes will ignore the value since serialization will not assign values to static or transient
+ * fields.</i>
+ * </ul>
+ * All other kinds of modifications should be avoided.
+ * </p>
+ */
+ private static final long serialVersionUID = 1L;
+
+ private final Map<String, Contribution> contributions = new HashMap<String, Contribution>();
+ private Map<Name, Property> annotations = null;
+ private DateTime expirationTimeInUtc;
+
+ /**
+ * Create this version
+ */
+ public BasicMergePlan() {
+ }
+
+ /**
+ * Determine whether this merge plan has expired given the supplied current time. The {@link #getExpirationTimeInUtc()
+ * expiration time} is the earliest time that any of the {@link #getContributionFrom(String) contributions}
+ * {@link Contribution#getExpirationTimeInUtc()}.
+ *
+ * @param utcTime the current time expressed in UTC; may not be null
+ * @return true if at least one contribution has expired, or false otherwise
+ */
+ public boolean isExpired( DateTime utcTime ) {
+ assert utcTime != null;
+ assert utcTime.toUtcTimeZone().equals(utcTime); // check that it is passed UTC time
+ return !expirationTimeInUtc.isAfter(utcTime);
+ }
+
+ /**
+ * Get the expiration time (in UTC) that is the earliest time that any of the {@link #getContributionFrom(String)
+ * contributions} {@link Contribution#getExpirationTimeInUtc()}.
+ *
+ * @return the expiration time in UTC, or null if there is no known expiration time
+ */
+ public DateTime getExpirationTimeInUtc() {
+ return expirationTimeInUtc;
+ }
+
+ /**
+ * Get the contribution from the source with the supplied name. Note that contributions always include sources that contribute
+ * information and sources that contribute no information. If a source is not included in this list, its contributions are
+ * <i>unknown</i>; that is, it is unknown whether that source does or does not contribute to the node.
+ *
+ * @param sourceName the name of the source
+ * @return the contribution, or null if the contribution of the source is unknown
+ */
+ public Contribution getContributionFrom( String sourceName ) {
+ return contributions.get(sourceName);
+ }
+
+ /**
+ * Return whether the named source was consulted for a contribution.
+ *
+ * @param sourceName the name of the source
+ * @return true if the source has some {@link Contribution contribution} (even if it is an {@link EmptyContribution})
+ */
+ public boolean isSource( String sourceName ) {
+ return contributions.containsKey(sourceName);
+ }
+
+ /**
+ * Get the names of the contributing sources.
+ *
+ * @return the names of the sources that have some contribution
+ */
+ public Set<String> getNamesOfContributingSources() {
+ return contributions.keySet();
+ }
+
+ /**
+ * Add the supplied contribution, replacing and returning any previous contribution for the same source.
+ *
+ * @param contribution the new contribution
+ * @return the previous contribution for the source, or null if there was no previous contribution.
+ */
+ public Contribution addContribution( Contribution contribution ) {
+ assert contribution != null;
+ Contribution previous = contributions.put(contribution.getSourceName(), contribution);
+ DateTime contributionExpirationInUtc = contribution.getExpirationTimeInUtc();
+ if (expirationTimeInUtc == null || contributionExpirationInUtc.isBefore(expirationTimeInUtc)) {
+ expirationTimeInUtc = contributionExpirationInUtc;
+ }
+ return previous;
+ }
+
+ /**
+ * Get the plan annotation property with the given name. Plan annotations are custom properties that may be set by
+ * MergeProcessor implementations to store custom properties on the plan. This method does nothing if the supplied name is
+ * null
+ *
+ * @param name the name of the annotation
+ * @return the existing annotation, or null if there is no annotation with the supplied name
+ * @see #setAnnotation(Property)
+ */
+ public Property getAnnotation( Name name ) {
+ if (name == null) return null;
+ if (this.annotations == null) return null;
+ return this.annotations.get(name);
+ }
+
+ /**
+ * Set the plan annotation property. This method replaces and returns any existing annotation property with the same name.
+ * This method also returns immediately if the supplied annotation is null.
+ *
+ * @param annotation the new annotation
+ * @return the previous annotation property with the same name, or null if there was no previous annotation property for the
+ * name
+ * @see #getAnnotation(Name)
+ */
+ public Property setAnnotation( Property annotation ) {
+ if (annotation == null) return null;
+ if (this.annotations == null) {
+ this.annotations = new HashMap<Name, Property>();
+ }
+ return this.annotations.put(annotation.getName(), annotation);
+ }
+
+}
Added: trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/merge/DoubleContributionMergePlan.java
===================================================================
--- trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/merge/DoubleContributionMergePlan.java (rev 0)
+++ trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/merge/DoubleContributionMergePlan.java 2008-07-24 19:52:13 UTC (rev 369)
@@ -0,0 +1,115 @@
+/*
+ * 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.connector.federation.merge;
+
+import java.util.Iterator;
+import java.util.NoSuchElementException;
+import net.jcip.annotations.ThreadSafe;
+import org.jboss.dna.connector.federation.contribution.Contribution;
+
+/**
+ * @author Randall Hauch
+ */
+@ThreadSafe
+public class DoubleContributionMergePlan extends MergePlan {
+
+ private static final long serialVersionUID = 1L;
+ private final Contribution contribution1;
+ private final Contribution contribution2;
+
+ /**
+ * @param contribution1 the first contribution for this merge plan
+ * @param contribution2 the second contribution for this merge plan
+ */
+ public DoubleContributionMergePlan( Contribution contribution1,
+ Contribution contribution2 ) {
+ assert contribution1 != null;
+ assert contribution2 != null;
+ this.contribution1 = contribution1;
+ this.contribution2 = contribution2;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.jboss.dna.connector.federation.merge.MergePlan#getContributionCount()
+ */
+ @Override
+ public int getContributionCount() {
+ return 2;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.jboss.dna.connector.federation.merge.MergePlan#getContributionFrom(java.lang.String)
+ */
+ @Override
+ public Contribution getContributionFrom( String sourceName ) {
+ if (contribution1.getSourceName().equals(sourceName)) return contribution1;
+ if (contribution2.getSourceName().equals(sourceName)) return contribution2;
+ return null;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see java.lang.Iterable#iterator()
+ */
+ public Iterator<Contribution> iterator() {
+ return new Iterator<Contribution>() {
+ private int next = 2;
+
+ public boolean hasNext() {
+ return next > 0;
+ }
+
+ @SuppressWarnings( "synthetic-access" )
+ public Contribution next() {
+ if (next == 2) {
+ next = 1;
+ return contribution2;
+ }
+ if (next == 1) {
+ next = 0;
+ return contribution1;
+ }
+ throw new NoSuchElementException();
+ }
+
+ public void remove() {
+ throw new UnsupportedOperationException();
+ }
+ };
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.jboss.dna.connector.federation.merge.MergePlan#isSource(java.lang.String)
+ */
+ @Override
+ public boolean isSource( String sourceName ) {
+ return contribution1.getSourceName().equals(sourceName) || contribution2.getSourceName().equals(sourceName);
+ }
+
+}
Added: trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/merge/FederatedNode.java
===================================================================
--- trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/merge/FederatedNode.java (rev 0)
+++ trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/merge/FederatedNode.java 2008-07-24 19:52:13 UTC (rev 369)
@@ -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.connector.federation.merge;
+
+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
+ */
+@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/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/merge/MergePlan.java
===================================================================
--- trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/merge/MergePlan.java (rev 0)
+++ trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/merge/MergePlan.java 2008-07-24 19:52:13 UTC (rev 369)
@@ -0,0 +1,228 @@
+/*
+ * 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.connector.federation.merge;
+
+import java.io.InvalidClassException;
+import java.io.Serializable;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+import net.jcip.annotations.ThreadSafe;
+import org.jboss.dna.common.util.ArgCheck;
+import org.jboss.dna.connector.federation.contribution.Contribution;
+import org.jboss.dna.connector.federation.contribution.EmptyContribution;
+import org.jboss.dna.spi.graph.DateTime;
+import org.jboss.dna.spi.graph.Name;
+import org.jboss.dna.spi.graph.Property;
+
+/**
+ * This class represents the details about how information from different sources are merged into a single federated node.
+ * <p>
+ * A merge plan basically consists of the individual contribution from each source and the information about how these
+ * contributions were merged into the single federated node.
+ * </p>
+ * <p>
+ * Merge plans are designed to be {@link Serializable serializable}, as they are persisted on the federated node and deserialized
+ * to assist in the management of the federated node.
+ * </p>
+ *
+ * @author Randall Hauch
+ */
+@ThreadSafe
+public abstract class MergePlan implements Serializable, Iterable<Contribution> {
+
+ public static MergePlan create( Contribution... contributions ) {
+ ArgCheck.isNotNull(contributions, "contributions");
+ switch (contributions.length) {
+ case 1:
+ return new SingleContributionMergePlan(contributions[0]);
+ case 2:
+ return new DoubleContributionMergePlan(contributions[0], contributions[1]);
+ case 3:
+ return new TripleContributionMergePlan(contributions[0], contributions[1], contributions[2]);
+ default:
+ return new MultipleContributionMergePlan(contributions);
+ }
+ }
+
+ public static MergePlan addContribution( MergePlan plan,
+ Contribution contribution ) {
+ if (plan instanceof MultipleContributionMergePlan) {
+ MultipleContributionMergePlan multiPlan = (MultipleContributionMergePlan)plan;
+ multiPlan.addContribution(contribution);
+ return multiPlan;
+ }
+ if (plan instanceof SingleContributionMergePlan) {
+ MergePlan newPlan = new DoubleContributionMergePlan(plan.iterator().next(), contribution);
+ newPlan.setAnnotations(plan.getAnnotations());
+ }
+ if (plan instanceof DoubleContributionMergePlan) {
+ Iterator<Contribution> iterator = plan.iterator();
+ MergePlan newPlan = new TripleContributionMergePlan(iterator.next(), iterator.next(), contribution);
+ newPlan.setAnnotations(plan.getAnnotations());
+ }
+ MultipleContributionMergePlan newPlan = new MultipleContributionMergePlan();
+ for (Contribution existingContribution : plan) {
+ newPlan.addContribution(existingContribution);
+ }
+ newPlan.addContribution(contribution);
+ newPlan.setAnnotations(plan.getAnnotations());
+ return newPlan;
+ }
+
+ /**
+ * Define the earliest version of this class that is supported. The Java runtime, upon deserialization, compares the
+ * serialized object's version to this, and if less than this version will throw a {@link InvalidClassException}. If, however,
+ * the serialized object's version is compatible with this class, it will be deserialized successfully.
+ * <p>
+ * <a href="http://java.sun.com/j2se/1.5.0/docs/guide/serialization/spec/version.html...">Sun's documentation</a> describes
+ * the following changes can be made without negatively affecting the deserialization of older versions:
+ * <ul>
+ * <li>Adding fields - When the class being reconstituted has a field that does not occur in the stream, that field in the
+ * object will be initialized to the default value for its type. If class-specific initialization is needed, the class may
+ * provide a readObject method that can initialize the field to nondefault values.</i>
+ * <li>Adding classes - The stream will contain the type hierarchy of each object in the stream. Comparing this hierarchy in
+ * the stream with the current class can detect additional classes. Since there is no information in the stream from which to
+ * initialize the object, the class's fields will be initialized to the default values.</i>
+ * <li>Removing classes - Comparing the class hierarchy in the stream with that of the current class can detect that a class
+ * has been deleted. In this case, the fields and objects corresponding to that class are read from the stream. Primitive
+ * fields are discarded, but the objects referenced by the deleted class are created, since they may be referred to later in
+ * the stream. They will be garbage-collected when the stream is garbage-collected or reset.</i>
+ * <li>Adding writeObject/readObject methods - If the version reading the stream has these methods then readObject is
+ * expected, as usual, to read the required data written to the stream by the default serialization. It should call
+ * defaultReadObject first before reading any optional data. The writeObject method is expected as usual to call
+ * defaultWriteObject to write the required data and then may write optional data.</i>
+ * <li>Removing writeObject/readObject methods - If the class reading the stream does not have these methods, the required
+ * data will be read by default serialization, and the optional data will be discarded.</i>
+ * <li>Adding java.io.Serializable - This is equivalent to adding types. There will be no values in the stream for this class
+ * so its fields will be initialized to default values. The support for subclassing nonserializable classes requires that the
+ * class's supertype have a no-arg constructor and the class itself will be initialized to default values. If the no-arg
+ * constructor is not available, the InvalidClassException is thrown.</i>
+ * <li>Changing the access to a field - The access modifiers public, package, protected, and private have no effect on the
+ * ability of serialization to assign values to the fields.</i>
+ * <li>Changing a field from static to nonstatic or transient to nontransient - When relying on default serialization to
+ * compute the serializable fields, this change is equivalent to adding a field to the class. The new field will be written to
+ * the stream but earlier classes will ignore the value since serialization will not assign values to static or transient
+ * fields.</i>
+ * </ul>
+ * All other kinds of modifications should be avoided.
+ * </p>
+ */
+ private static final long serialVersionUID = 1L;
+
+ private Map<Name, Property> annotations = null;
+ private DateTime expirationTimeInUtc;
+
+ /**
+ * Create an empty merge plan
+ */
+ protected MergePlan() {
+ }
+
+ /**
+ * Determine whether this merge plan has expired given the supplied current time. The {@link #getExpirationTimeInUtc()
+ * expiration time} is the earliest time that any of the {@link #getContributionFrom(String) contributions}
+ * {@link Contribution#getExpirationTimeInUtc()}.
+ *
+ * @param utcTime the current time expressed in UTC; may not be null
+ * @return true if at least one contribution has expired, or false otherwise
+ */
+ public boolean isExpired( DateTime utcTime ) {
+ assert utcTime != null;
+ assert utcTime.toUtcTimeZone().equals(utcTime); // check that it is passed UTC time
+ return !expirationTimeInUtc.isAfter(utcTime);
+ }
+
+ /**
+ * Get the expiration time (in UTC) that is the earliest time that any of the {@link #getContributionFrom(String)
+ * contributions} {@link Contribution#getExpirationTimeInUtc()}.
+ *
+ * @return the expiration time in UTC, or null if there is no known expiration time
+ */
+ public DateTime getExpirationTimeInUtc() {
+ return expirationTimeInUtc;
+ }
+
+ /**
+ * Get the contribution from the source with the supplied name. Note that contributions always include sources that contribute
+ * information and sources that contribute no information. If a source is not included in this list, its contributions are
+ * <i>unknown</i>; that is, it is unknown whether that source does or does not contribute to the node.
+ *
+ * @param sourceName the name of the source
+ * @return the contribution, or null if the contribution of the source is unknown
+ */
+ public abstract Contribution getContributionFrom( String sourceName );
+
+ /**
+ * Return whether the named source was consulted for a contribution.
+ *
+ * @param sourceName the name of the source
+ * @return true if the source has some {@link Contribution contribution} (even if it is an {@link EmptyContribution})
+ */
+ public abstract boolean isSource( String sourceName );
+
+ public abstract int getContributionCount();
+
+ /**
+ * Get the plan annotation property with the given name. Plan annotations are custom properties that may be set by
+ * MergeProcessor implementations to store custom properties on the plan. This method does nothing if the supplied name is
+ * null
+ *
+ * @param name the name of the annotation
+ * @return the existing annotation, or null if there is no annotation with the supplied name
+ * @see #setAnnotation(Property)
+ */
+ public Property getAnnotation( Name name ) {
+ if (name == null) return null;
+ if (this.annotations == null) return null;
+ return this.annotations.get(name);
+ }
+
+ /**
+ * Set the plan annotation property. This method replaces and returns any existing annotation property with the same name.
+ * This method also returns immediately if the supplied annotation is null.
+ *
+ * @param annotation the new annotation
+ * @return the previous annotation property with the same name, or null if there was no previous annotation property for the
+ * name
+ * @see #getAnnotation(Name)
+ */
+ public Property setAnnotation( Property annotation ) {
+ if (annotation == null) return null;
+ if (this.annotations == null) {
+ this.annotations = new HashMap<Name, Property>();
+ }
+ return this.annotations.put(annotation.getName(), annotation);
+ }
+
+ protected void setAnnotations( Map<Name, Property> annotations ) {
+ this.annotations = annotations;
+ }
+
+ /**
+ * @return annotations
+ */
+ protected Map<Name, Property> getAnnotations() {
+ return annotations;
+ }
+
+}
Added: trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/merge/MultipleContributionMergePlan.java
===================================================================
--- trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/merge/MultipleContributionMergePlan.java (rev 0)
+++ trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/merge/MultipleContributionMergePlan.java 2008-07-24 19:52:13 UTC (rev 369)
@@ -0,0 +1,116 @@
+/*
+ * 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.connector.federation.merge;
+
+import java.util.Iterator;
+import java.util.List;
+import java.util.concurrent.CopyOnWriteArrayList;
+import net.jcip.annotations.ThreadSafe;
+import org.jboss.dna.connector.federation.contribution.Contribution;
+
+/**
+ * @author Randall Hauch
+ */
+@ThreadSafe
+public class MultipleContributionMergePlan extends MergePlan {
+
+ private static final long serialVersionUID = 1L;
+ private final List<Contribution> contributions;
+
+ /**
+ * @param contributions the contributions for this merge plan
+ */
+ public MultipleContributionMergePlan( Contribution... contributions ) {
+ assert contributions != null;
+ this.contributions = new CopyOnWriteArrayList<Contribution>();
+ for (int i = 0; i != contributions.length; ++i) {
+ assert contributions[i] != null;
+ this.contributions.add(contributions[i]);
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.jboss.dna.connector.federation.merge.MergePlan#getContributionCount()
+ */
+ @Override
+ public int getContributionCount() {
+ return contributions.size();
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.jboss.dna.connector.federation.merge.MergePlan#getContributionFrom(java.lang.String)
+ */
+ @Override
+ public Contribution getContributionFrom( String sourceName ) {
+ for (Contribution contribution : contributions) {
+ if (contribution.getSourceName().equals(sourceName)) return contribution;
+ }
+ return null;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see java.lang.Iterable#iterator()
+ */
+ public Iterator<Contribution> iterator() {
+ final Iterator<Contribution> iterator = this.contributions.iterator();
+ return new Iterator<Contribution>() {
+ public boolean hasNext() {
+ return iterator.hasNext();
+ }
+
+ public Contribution next() {
+ return iterator.next();
+ }
+
+ public void remove() {
+ throw new UnsupportedOperationException();
+ }
+ };
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.jboss.dna.connector.federation.merge.MergePlan#isSource(java.lang.String)
+ */
+ @Override
+ public boolean isSource( String sourceName ) {
+ for (Contribution contribution : contributions) {
+ if (contribution.getSourceName().equals(sourceName)) return true;
+ }
+ return false;
+ }
+
+ /**
+ * @param contribution
+ */
+ public void addContribution( Contribution contribution ) {
+ this.contributions.add(contribution);
+ }
+
+}
Added: trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/merge/SingleContributionMergePlan.java
===================================================================
--- trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/merge/SingleContributionMergePlan.java (rev 0)
+++ trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/merge/SingleContributionMergePlan.java 2008-07-24 19:52:13 UTC (rev 369)
@@ -0,0 +1,104 @@
+/*
+ * 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.connector.federation.merge;
+
+import java.util.Iterator;
+import java.util.NoSuchElementException;
+import net.jcip.annotations.ThreadSafe;
+import org.jboss.dna.connector.federation.contribution.Contribution;
+
+/**
+ * @author Randall Hauch
+ */
+@ThreadSafe
+public class SingleContributionMergePlan extends MergePlan {
+
+ private static final long serialVersionUID = 1L;
+ private final Contribution contribution;
+
+ /**
+ * @param contribution the contribution for this merge plan
+ */
+ public SingleContributionMergePlan( Contribution contribution ) {
+ assert contribution != null;
+ this.contribution = contribution;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.jboss.dna.connector.federation.merge.MergePlan#getContributionCount()
+ */
+ @Override
+ public int getContributionCount() {
+ return 1;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.jboss.dna.connector.federation.merge.MergePlan#getContributionFrom(java.lang.String)
+ */
+ @Override
+ public Contribution getContributionFrom( String sourceName ) {
+ return isSource(sourceName) ? contribution : null;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see java.lang.Iterable#iterator()
+ */
+ public Iterator<Contribution> iterator() {
+ return new Iterator<Contribution>() {
+ private boolean next = true;
+
+ public boolean hasNext() {
+ return next;
+ }
+
+ @SuppressWarnings( "synthetic-access" )
+ public Contribution next() {
+ if (next) {
+ next = false;
+ return contribution;
+ }
+ throw new NoSuchElementException();
+ }
+
+ public void remove() {
+ throw new UnsupportedOperationException();
+ }
+ };
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.jboss.dna.connector.federation.merge.MergePlan#isSource(java.lang.String)
+ */
+ @Override
+ public boolean isSource( String sourceName ) {
+ return contribution.getSourceName().equals(sourceName);
+ }
+
+}
Added: trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/merge/TripleContributionMergePlan.java
===================================================================
--- trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/merge/TripleContributionMergePlan.java (rev 0)
+++ trunk/connectors/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/merge/TripleContributionMergePlan.java 2008-07-24 19:52:13 UTC (rev 369)
@@ -0,0 +1,126 @@
+/*
+ * 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.connector.federation.merge;
+
+import java.util.Iterator;
+import java.util.NoSuchElementException;
+import net.jcip.annotations.ThreadSafe;
+import org.jboss.dna.connector.federation.contribution.Contribution;
+
+/**
+ * @author Randall Hauch
+ */
+@ThreadSafe
+public class TripleContributionMergePlan extends MergePlan {
+
+ private static final long serialVersionUID = 1L;
+ private final Contribution contribution1;
+ private final Contribution contribution2;
+ private final Contribution contribution3;
+
+ /**
+ * @param contribution1 the first contribution for this merge plan
+ * @param contribution2 the second contribution for this merge plan
+ * @param contribution3 the third contribution for this merge plan
+ */
+ public TripleContributionMergePlan( Contribution contribution1,
+ Contribution contribution2,
+ Contribution contribution3 ) {
+ assert contribution1 != null;
+ assert contribution2 != null;
+ assert contribution3 != null;
+ this.contribution1 = contribution1;
+ this.contribution2 = contribution2;
+ this.contribution3 = contribution3;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.jboss.dna.connector.federation.merge.MergePlan#getContributionCount()
+ */
+ @Override
+ public int getContributionCount() {
+ return 3;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.jboss.dna.connector.federation.merge.MergePlan#getContributionFrom(java.lang.String)
+ */
+ @Override
+ public Contribution getContributionFrom( String sourceName ) {
+ if (contribution1.getSourceName().equals(sourceName)) return contribution1;
+ if (contribution2.getSourceName().equals(sourceName)) return contribution2;
+ if (contribution3.getSourceName().equals(sourceName)) return contribution3;
+ return null;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see java.lang.Iterable#iterator()
+ */
+ public Iterator<Contribution> iterator() {
+ return new Iterator<Contribution>() {
+ private int next = 3;
+
+ public boolean hasNext() {
+ return next > 0;
+ }
+
+ @SuppressWarnings( "synthetic-access" )
+ public Contribution next() {
+ if (next == 3) {
+ next = 2;
+ return contribution3;
+ }
+ if (next == 2) {
+ next = 1;
+ return contribution2;
+ }
+ if (next == 1) {
+ next = 0;
+ return contribution1;
+ }
+ throw new NoSuchElementException();
+ }
+
+ public void remove() {
+ throw new UnsupportedOperationException();
+ }
+ };
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.jboss.dna.connector.federation.merge.MergePlan#isSource(java.lang.String)
+ */
+ @Override
+ public boolean isSource( String sourceName ) {
+ return contribution1.getSourceName().equals(sourceName) || contribution2.getSourceName().equals(sourceName)
+ || contribution3.getSourceName().equals(sourceName);
+ }
+
+}
Added: trunk/connectors/dna-connector-federation/src/main/resources/org/jboss/dna/connector/federation/FederationI18n.properties
===================================================================
--- trunk/connectors/dna-connector-federation/src/main/resources/org/jboss/dna/connector/federation/FederationI18n.properties (rev 0)
+++ trunk/connectors/dna-connector-federation/src/main/resources/org/jboss/dna/connector/federation/FederationI18n.properties 2008-07-24 19:52:13 UTC (rev 369)
@@ -0,0 +1,38 @@
+#
+# 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.
+#
+requiredNodeDoesNotExistRelativeToNode = The required node {0} does not exist relative to {1}
+propertyIsRequired = The {0} property is required but has no value
+
+interruptedWhileUsingFederationConfigurationRepository = Interrupted while using federation configuration repository "{0}"
+unableToFindFederatedRepositoryInJndi = Unable to find a FederatedRepository instance in JNDI under "{1}" when creating connection to federated source "{0}"
+unableToFindExecutionContextFactoryInJndi = Unable to find an ExecutionContextFactory instance in JNDI under "{1}" when creating connection to federated source "{0}"
+unableToCreateExecutionContext = Unable to create ExecutionContext for connection to federated source "{0}" when using factory in JNDI under "{1}" and security domain "{2}"
+unableToFindRepositoryConnectionFactoriesInJndi = Unable to find an RepositoryConnectionFactories instance in JNDI under "{1}" when creating connection to federated source "{0}"
+noRepositoryConnectionFactories = No RepositoryConnectionFactories instance was specified directly or indirectly found in JNDI when creating connection to federated source "{0}"
+federatedRepositoryCannotBeFound = The federated repository "{0}" cannot be found
+unableToFindRepositorySourceByName = Unable to find the repository source "{0}"
+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}"
+errorReadingMergePlan = Error while reading merge plan for {0}
+errorAddingProjectionRuleParseMethod = Error while adding a parsing method for a federation projection rule
\ No newline at end of file
Added: trunk/connectors/dna-connector-federation/src/test/java/org/jboss/dna/connector/federation/FederatedRepositoryConnectionTest.java
===================================================================
--- trunk/connectors/dna-connector-federation/src/test/java/org/jboss/dna/connector/federation/FederatedRepositoryConnectionTest.java (rev 0)
+++ trunk/connectors/dna-connector-federation/src/test/java/org/jboss/dna/connector/federation/FederatedRepositoryConnectionTest.java 2008-07-24 19:52:13 UTC (rev 369)
@@ -0,0 +1,132 @@
+/*
+ * 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.connector.federation;
+
+import static org.hamcrest.core.Is.is;
+import static org.hamcrest.core.IsNull.nullValue;
+import static org.junit.Assert.assertThat;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.stub;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import java.util.concurrent.TimeUnit;
+import org.jboss.dna.spi.graph.commands.GraphCommand;
+import org.jboss.dna.spi.graph.commands.executor.CommandExecutor;
+import org.jboss.dna.spi.graph.connection.ExecutionEnvironment;
+import org.jboss.dna.spi.graph.connection.RepositorySourceException;
+import org.jboss.dna.spi.graph.connection.RepositorySourceListener;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.MockitoAnnotations;
+import org.mockito.MockitoAnnotations.Mock;
+
+/**
+ * @author Randall Hauch
+ */
+public class FederatedRepositoryConnectionTest {
+
+ private FederatedRepositoryConnection connection;
+ private String sourceName;
+ @Mock
+ private FederatedRepositorySource source;
+ @Mock
+ private FederatedRepository repository;
+
+ @Before
+ public void beforeEach() {
+ MockitoAnnotations.initMocks(this);
+ sourceName = "Source X";
+ stub(source.getName()).toReturn(sourceName);
+ connection = new FederatedRepositoryConnection(repository, sourceName);
+ }
+
+ @Test
+ public void shouldHaveRepository() {
+ assertThat(connection.getRepository(), is(repository));
+ }
+
+ @Test
+ public void shouldHaveNoXaResource() {
+ assertThat(connection.getXAResource(), is(nullValue()));
+ }
+
+ @Test
+ public void shouldCheckRepositoryAdminsStartedStateForPingResult() {
+ stub(repository.isRunning()).toReturn(true);
+ assertThat(connection.ping(1, TimeUnit.SECONDS), is(true));
+ verify(repository, times(1)).isRunning();
+ }
+
+ @Test( expected = RepositorySourceException.class )
+ public void shouldFailExecutionIfRepositoryAdminsIsNotStarted() throws Exception {
+ stub(repository.isRunning()).toReturn(false);
+ ExecutionEnvironment env = mock(ExecutionEnvironment.class);
+ GraphCommand command = mock(GraphCommand.class);
+ connection.execute(env, command);
+ }
+
+ @Test
+ public void shouldReturnImmediatelyWhenExecutingNullOrEmptyCommandArray() throws Exception {
+ stub(repository.isRunning()).toReturn(true);
+ ExecutionEnvironment env = mock(ExecutionEnvironment.class);
+ connection.execute(env, (GraphCommand[])null);
+ verify(repository, times(1)).isRunning();
+ connection.execute(env, new GraphCommand[0]);
+ verify(repository, times(2)).isRunning();
+ }
+
+ @Test
+ public void shouldSkipNullCommandReferencesWhenExecuting() throws Exception {
+ stub(repository.isRunning()).toReturn(true);
+ ExecutionEnvironment env = mock(ExecutionEnvironment.class);
+ CommandExecutor executor = mock(CommandExecutor.class);
+ stub(repository.getExecutor(env, sourceName)).toReturn(executor);
+ connection.execute(env, new GraphCommand[] {null, null, null});
+ verify(repository, times(1)).isRunning();
+ }
+
+ @Test
+ public void shouldAddListenerToRepositoryWhenSetOnConnection() {
+ // Old listener is no-op, so it is not removed from repository ...
+ RepositorySourceListener listener = mock(RepositorySourceListener.class);
+ connection.setListener(listener);
+ verify(repository, times(1)).addListener(listener);
+
+ // Old listener is NOT no-op, so it is removed from repository ...
+ RepositorySourceListener listener2 = mock(RepositorySourceListener.class);
+ connection.setListener(listener2);
+ verify(repository, times(1)).removeListener(listener);
+ verify(repository, times(1)).addListener(listener2);
+ }
+
+ @Test
+ public void shouldRemoveListenerFromRepositoryWhenConnectionIsClosed() {
+ // Old listener is NOT no-op, so it is removed from repository ...
+ RepositorySourceListener listener2 = mock(RepositorySourceListener.class);
+ connection.setListener(listener2);
+ verify(repository, times(1)).addListener(listener2);
+
+ // Closing connection will remove listener ...
+ connection.close();
+ verify(repository, times(1)).removeListener(listener2);
+ }
+}
Added: trunk/connectors/dna-connector-federation/src/test/java/org/jboss/dna/connector/federation/FederatedRepositorySourceTest.java
===================================================================
--- trunk/connectors/dna-connector-federation/src/test/java/org/jboss/dna/connector/federation/FederatedRepositorySourceTest.java (rev 0)
+++ trunk/connectors/dna-connector-federation/src/test/java/org/jboss/dna/connector/federation/FederatedRepositorySourceTest.java 2008-07-24 19:52:13 UTC (rev 369)
@@ -0,0 +1,309 @@
+/*
+ * 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.connector.federation;
+
+import static org.hamcrest.core.Is.is;
+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.mockito.Matchers.argThat;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.stub;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.Hashtable;
+import java.util.Map;
+import javax.naming.Context;
+import javax.naming.Name;
+import javax.naming.RefAddr;
+import javax.naming.Reference;
+import javax.security.auth.callback.CallbackHandler;
+import javax.security.auth.login.LoginException;
+import org.jboss.dna.spi.ExecutionContextFactory;
+import org.jboss.dna.spi.graph.connection.BasicExecutionEnvironment;
+import org.jboss.dna.spi.graph.connection.ExecutionEnvironment;
+import org.jboss.dna.spi.graph.connection.RepositoryConnectionFactories;
+import org.jboss.dna.spi.graph.connection.RepositorySourceException;
+import org.jboss.dna.spi.graph.connection.SimpleRepository;
+import org.jboss.dna.spi.graph.connection.SimpleRepositorySource;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.ArgumentMatcher;
+import org.mockito.MockitoAnnotations;
+import org.mockito.MockitoAnnotations.Mock;
+
+/**
+ * @author Randall Hauch
+ */
+public class FederatedRepositorySourceTest {
+
+ private FederatedRepositorySource source;
+ private String sourceName;
+ private String repositoryName;
+ private String username;
+ private String credentials;
+ private String executionContextFactoryJndiName;
+ private String connectionFactoriesJndiName;
+ private String configurationSourceName;
+ private String securityDomain;
+ private SimpleRepository configRepository;
+ private SimpleRepositorySource configRepositorySource;
+ private ExecutionEnvironment env;
+ @Mock
+ private FederatedRepositoryConnection connection;
+ @Mock
+ private Context jndiContext;
+ @Mock
+ private RepositoryConnectionFactories connectionFactories;
+ @Mock
+ private ExecutionContextFactory executionContextFactory;
+
+ /**
+ * @throws java.lang.Exception
+ */
+ @Before
+ public void beforeEach() throws Exception {
+ MockitoAnnotations.initMocks(this);
+ env = new BasicExecutionEnvironment();
+ env.getNamespaceRegistry().register("dna", "http://www.jboss.org/dna");
+ executionContextFactoryJndiName = "context factory jndi name";
+ connectionFactoriesJndiName = "connection factories jndi name";
+ configurationSourceName = "configuration source name";
+ repositoryName = "Test Repository";
+ securityDomain = "security domain";
+ source = new FederatedRepositorySource(repositoryName);
+ sourceName = "federated source";
+ username = "valid username";
+ credentials = "valid password";
+ source.setName(sourceName);
+ source.setUsername(username);
+ source.setPassword(credentials);
+ source.setConfigurationSourceName(configurationSourceName);
+ source.setConfigurationSourceProjectionRules(new String[] {"/dna:system/dna:federation/ => /dna:repositories/Test Repository"});
+ source.setConnectionFactoriesJndiName(connectionFactoriesJndiName);
+ source.setExecutionContextFactoryJndiName(executionContextFactoryJndiName);
+ source.setContext(jndiContext);
+ source.setSecurityDomain(securityDomain);
+ configRepository = new SimpleRepository("Configuration Repository");
+ configRepository.setProperty(env, "/dna:repositories/Test Repository", "dna:timeToExpire", "100000");
+ configRepository.setProperty(env, "/dna:repositories/Test Repository", "dna:timeToCache", "100000");
+ configRepository.setProperty(env, "/dna:repositories/Test Repository/dna:cache", "dna:projectionRules", "/ => /");
+ configRepository.setProperty(env,
+ "/dna:repositories/Test Repository/dna:projections/source 1/",
+ "dna:projectionRules",
+ "/ => /s1");
+ configRepository.setProperty(env,
+ "/dna:repositories/Test Repository/dna:projections/source 2/",
+ "dna:projectionRules",
+ "/ => /s1");
+ configRepositorySource = new SimpleRepositorySource();
+ configRepositorySource.setRepositoryName(configRepository.getRepositoryName());
+ configRepositorySource.setName(configurationSourceName);
+ stub(connectionFactories.getConnectionFactory(configurationSourceName)).toReturn(configRepositorySource);
+ stub(jndiContext.lookup(executionContextFactoryJndiName)).toReturn(executionContextFactory);
+ stub(jndiContext.lookup(connectionFactoriesJndiName)).toReturn(connectionFactories);
+ stub(executionContextFactory.create(eq(securityDomain), anyCallbackHandler())).toReturn(env);
+ }
+
+ protected static CallbackHandler anyCallbackHandler() {
+ return argThat(new ArgumentMatcher<CallbackHandler>() {
+ @Override
+ public boolean matches( Object callback ) {
+ return callback != null;
+ }
+ });
+ }
+
+ @After
+ public void afterEach() throws Exception {
+ SimpleRepository.shutdownAll();
+ }
+
+ @Test
+ public void shouldCreateConnectionsByAuthenticateUsingFederationRepository() throws Exception {
+ connection = (FederatedRepositoryConnection)source.getConnection();
+ assertThat(connection, is(sameInstance(connection)));
+ }
+
+ @Test( expected = RepositorySourceException.class )
+ public void shouldNotCreateConnectionWhenAuthenticationFails() throws Exception {
+ // Stub the execution context factory to throw a LoginException to simulate failed authentication
+ stub(executionContextFactory.create(eq(securityDomain), anyCallbackHandler())).toThrow(new LoginException());
+ source.getConnection();
+ }
+
+ @Test( expected = NullPointerException.class )
+ public void shouldPropogateAllExceptionsExceptLoginExceptionThrownFromExecutionContextFactory() throws Exception {
+ // Stub the execution context factory to throw a LoginException to simulate failed authentication
+ stub(executionContextFactory.create(eq(securityDomain), anyCallbackHandler())).toThrow(new NullPointerException());
+ source.getConnection();
+ }
+
+ @Test
+ public void shouldHaveNameSuppliedInConstructor() {
+ source = new FederatedRepositorySource(repositoryName);
+ assertThat(source.getRepositoryName(), is(repositoryName));
+ }
+
+ @Test
+ public void shouldHaveNullSourceNameUponConstruction() {
+ source = new FederatedRepositorySource(repositoryName);
+ assertThat(source.getName(), is(nullValue()));
+ }
+
+ @Test
+ public void shouldAllowSettingName() {
+ source.setName("Something");
+ assertThat(source.getName(), is("Something"));
+ source.setName("another name");
+ assertThat(source.getName(), is("another name"));
+ }
+
+ @Test
+ public void shouldAllowSettingNameToNull() {
+ source.setName("some name");
+ source.setName(null);
+ assertThat(source.getName(), is(nullValue()));
+ }
+
+ @Test
+ public void shouldAllowSettingUsername() {
+ source.setUsername("Something");
+ assertThat(source.getUsername(), is("Something"));
+ source.setUsername("another name");
+ assertThat(source.getUsername(), is("another name"));
+ }
+
+ @Test
+ public void shouldAllowSettingUsernameToNull() {
+ source.setUsername("some name");
+ source.setUsername(null);
+ assertThat(source.getUsername(), is(nullValue()));
+ }
+
+ @Test
+ public void shouldAllowSettingCredentials() {
+ source.setPassword("Something");
+ assertThat(source.getPassword(), is("Something"));
+ source.setPassword("another name");
+ assertThat(source.getPassword(), is("another name"));
+ }
+
+ @Test
+ public void shouldAllowSettingCredentialsToNull() {
+ source.setPassword("some name");
+ source.setPassword(null);
+ assertThat(source.getPassword(), is(nullValue()));
+ }
+
+ @Test
+ public void shouldHaveDefaultRetryLimit() {
+ assertThat(source.getRetryLimit(), is(FederatedRepositorySource.DEFAULT_RETRY_LIMIT));
+ }
+
+ @Test
+ public void shouldSetRetryLimitToZeroWhenSetWithNonPositiveValue() {
+ source.setRetryLimit(0);
+ assertThat(source.getRetryLimit(), is(0));
+ source.setRetryLimit(-1);
+ assertThat(source.getRetryLimit(), is(0));
+ source.setRetryLimit(-100);
+ assertThat(source.getRetryLimit(), is(0));
+ }
+
+ @Test
+ public void shouldAllowRetryLimitToBeSet() {
+ for (int i = 0; i != 100; ++i) {
+ source.setRetryLimit(i);
+ assertThat(source.getRetryLimit(), is(i));
+ }
+ }
+
+ @Test
+ public void shouldCreateJndiReferenceAndRecreatedObjectFromReference() throws Exception {
+ int retryLimit = 100;
+ source.setPassword(credentials);
+ source.setUsername(username);
+ source.setRetryLimit(retryLimit);
+ source.setName("Some source");
+ source.setConfigurationSourceName("config source");
+ source.setConfigurationSourceProjectionRules(new String[] {"/dna:system => /a/b/c"});
+ source.setConnectionFactoriesJndiName("connection factories jndi name");
+ source.setRepositoryJndiName("repository jndi name");
+ source.setExecutionContextFactoryJndiName("env jndi name");
+
+ Reference ref = source.getReference();
+ assertThat(ref.getClassName(), is(FederatedRepositorySource.class.getName()));
+ assertThat(ref.getFactoryClassName(), is(FederatedRepositorySource.NamingContextObjectFactory.class.getName()));
+
+ Map<String, Object> refAttributes = new HashMap<String, Object>();
+ Enumeration<RefAddr> enumeration = ref.getAll();
+ while (enumeration.hasMoreElements()) {
+ RefAddr addr = enumeration.nextElement();
+ refAttributes.put(addr.getType(), addr.getContent());
+ }
+
+ assertThat((String)refAttributes.remove(FederatedRepositorySource.USERNAME), is(username));
+ assertThat((String)refAttributes.remove(FederatedRepositorySource.PASSWORD), is(credentials));
+ assertThat((String)refAttributes.remove(FederatedRepositorySource.SOURCE_NAME), is(source.getName()));
+ assertThat((String)refAttributes.remove(FederatedRepositorySource.REPOSITORY_NAME), is(repositoryName));
+ assertThat((String)refAttributes.remove(FederatedRepositorySource.RETRY_LIMIT), is(Integer.toString(retryLimit)));
+ assertThat((String)refAttributes.remove(FederatedRepositorySource.CONFIGURATION_SOURCE_NAME),
+ is(source.getConfigurationSourceName()));
+ assertThat((String)refAttributes.remove(FederatedRepositorySource.CONFIGURATION_SOURCE_PROJECTION_RULES),
+ is("/dna:system => /a/b/c"));
+ assertThat((String)refAttributes.remove(FederatedRepositorySource.CONNECTION_FACTORIES_JNDI_NAME),
+ is(source.getConnectionFactoriesJndiName()));
+ assertThat((String)refAttributes.remove(FederatedRepositorySource.EXECUTION_CONTEXT_FACTORY_JNDI_NAME),
+ is(source.getExecutionContextFactoryJndiName()));
+ assertThat((String)refAttributes.remove(FederatedRepositorySource.REPOSITORY_JNDI_NAME),
+ is(source.getRepositoryJndiName()));
+ assertThat((String)refAttributes.remove(FederatedRepositorySource.SECURITY_DOMAIN), is(securityDomain));
+ assertThat(refAttributes.isEmpty(), is(true));
+
+ // Recreate the object, use a newly constructed source ...
+ FederatedRepositorySource.NamingContextObjectFactory factory = new FederatedRepositorySource.NamingContextObjectFactory();
+ Name name = mock(Name.class);
+ Context context = mock(Context.class);
+ Hashtable<?, ?> env = new Hashtable<Object, Object>();
+ FederatedRepositorySource recoveredSource = (FederatedRepositorySource)factory.getObjectInstance(ref, name, context, env);
+ assertThat(recoveredSource, is(notNullValue()));
+
+ assertThat(recoveredSource.getName(), is(source.getName()));
+ assertThat(recoveredSource.getUsername(), is(source.getUsername()));
+ assertThat(recoveredSource.getPassword(), is(source.getPassword()));
+ assertThat(recoveredSource.getRepositoryName(), is(source.getRepositoryName()));
+ assertThat(recoveredSource.getRetryLimit(), is(source.getRetryLimit()));
+ assertThat(recoveredSource.getConfigurationSourceName(), is(source.getConfigurationSourceName()));
+ assertThat(recoveredSource.getConfigurationSourceProjectionRules(), is(source.getConfigurationSourceProjectionRules()));
+ assertThat(recoveredSource.getConnectionFactoriesJndiName(), is(source.getConnectionFactoriesJndiName()));
+ assertThat(recoveredSource.getExecutionContextFactoryJndiName(), is(source.getExecutionContextFactoryJndiName()));
+ assertThat(recoveredSource.getRepositoryJndiName(), is(source.getRepositoryJndiName()));
+ assertThat(recoveredSource.getSecurityDomain(), is(source.getSecurityDomain()));
+
+ assertThat(recoveredSource.equals(source), is(true));
+ assertThat(source.equals(recoveredSource), is(true));
+ }
+}
Added: trunk/connectors/dna-connector-federation/src/test/java/org/jboss/dna/connector/federation/FederatedRepositoryTest.java
===================================================================
--- trunk/connectors/dna-connector-federation/src/test/java/org/jboss/dna/connector/federation/FederatedRepositoryTest.java (rev 0)
+++ trunk/connectors/dna-connector-federation/src/test/java/org/jboss/dna/connector/federation/FederatedRepositoryTest.java 2008-07-24 19:52:13 UTC (rev 369)
@@ -0,0 +1,146 @@
+/*
+ * 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.connector.federation;
+
+import static org.hamcrest.core.Is.is;
+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 org.jboss.dna.spi.graph.connection.BasicExecutionEnvironment;
+import org.jboss.dna.spi.graph.connection.ExecutionEnvironment;
+import org.jboss.dna.spi.graph.connection.RepositoryConnectionFactories;
+import org.jboss.dna.spi.graph.connection.RepositorySourceListener;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.MockitoAnnotations;
+import org.mockito.MockitoAnnotations.Mock;
+
+/**
+ * @author Randall Hauch
+ */
+public class FederatedRepositoryTest {
+
+ private ExecutionEnvironment env;
+ private FederatedRepository repository;
+ @Mock
+ private FederatedRepositoryConfig config;
+ @Mock
+ private RepositorySourceListener listener1;
+ @Mock
+ private RepositorySourceListener listener2;
+ @Mock
+ private RepositoryConnectionFactories connectionFactories;
+
+ // private BasicRepositoryConnectionPool connectionPool;
+
+ @Before
+ public void beforeEach() {
+ MockitoAnnotations.initMocks(this);
+ env = new BasicExecutionEnvironment();
+ repository = new FederatedRepository(env, connectionFactories, config);
+ }
+
+ @Test
+ public void shouldHaveNoNameUponCreation() {
+ assertThat(repository.getName(), is(nullValue()));
+ }
+
+ @Test
+ public void shouldHaveNoListenersUponCreation() {
+ assertThat(repository.getListeners(), is(notNullValue()));
+ assertThat(repository.getListeners().isEmpty(), is(true));
+ }
+
+ @Test
+ public void shouldNotAddNullListener() {
+ assertThat(repository.addListener(null), is(false));
+ }
+
+ @Test
+ public void shouldNotAddListenerIfAlreadyInList() {
+ assertThat(repository.getListeners().size(), is(0));
+ assertThat(repository.addListener(listener1), is(true));
+ assertThat(repository.getListeners().size(), is(1));
+ assertThat(repository.addListener(listener1), is(false));
+ assertThat(repository.getListeners().size(), is(1));
+ }
+
+ @Test
+ public void shouldAddDifferentListeners() {
+ assertThat(repository.getListeners().size(), is(0));
+ assertThat(repository.addListener(listener1), is(true));
+ assertThat(repository.getListeners().size(), is(1));
+ assertThat(repository.addListener(listener2), is(true));
+ assertThat(repository.getListeners().size(), is(2));
+ assertThat(repository.getListeners(), hasItems(listener1, listener2));
+ assertThat(repository.getListeners().get(0), is(sameInstance(listener1)));
+ assertThat(repository.getListeners().get(1), is(sameInstance(listener2)));
+ }
+
+ @Test
+ public void shouldAllowReorderingOfListeners() {
+ assertThat(repository.getListeners().size(), is(0));
+ assertThat(repository.addListener(listener1), is(true));
+ assertThat(repository.addListener(listener2), is(true));
+ assertThat(repository.getListeners().size(), is(2));
+ assertThat(repository.getListeners(), hasItems(listener1, listener2));
+ repository.getListeners().remove(0);
+ repository.getListeners().add(1, listener1);
+ assertThat(repository.getListeners(), hasItems(listener2, listener1));
+ assertThat(repository.getListeners().get(0), is(sameInstance(listener2)));
+ assertThat(repository.getListeners().get(1), is(sameInstance(listener1)));
+ }
+
+ @Test
+ public void shouldAllowRemovalOfListeners() {
+ assertThat(repository.getListeners().size(), is(0));
+ assertThat(repository.addListener(listener1), is(true));
+ assertThat(repository.addListener(listener2), is(true));
+ assertThat(repository.getListeners(), hasItems(listener1, listener2));
+ assertThat(repository.removeListener(listener1), is(true));
+ assertThat(repository.getListeners(), hasItems(listener2));
+ assertThat(repository.removeListener(listener2), is(true));
+ assertThat(repository.getListeners(), hasItems(new RepositorySourceListener[] {}));
+ }
+
+ @Test
+ public void shouldNotRemoveListenerThatIsNotAlreadyRegistered() {
+ assertThat(repository.getListeners().size(), is(0));
+ assertThat(repository.addListener(listener1), is(true));
+ assertThat(repository.getListeners().size(), is(1));
+ assertThat(repository.removeListener(listener2), is(false));
+ }
+
+ @Test
+ public void shouldHaveConfigurationAfterInitialization() {
+ assertThat(repository.getConfiguration(), is(notNullValue()));
+ assertThat(repository.getConfiguration(), is(sameInstance(config)));
+ }
+
+ @Test( expected = IllegalArgumentException.class )
+ public void shouldNotAllowSettingConfigurationToNull() {
+ repository.setConfiguration(null);
+ }
+
+}
Added: trunk/connectors/dna-connector-federation/src/test/java/org/jboss/dna/connector/federation/FederationI18nTest.java
===================================================================
--- trunk/connectors/dna-connector-federation/src/test/java/org/jboss/dna/connector/federation/FederationI18nTest.java (rev 0)
+++ trunk/connectors/dna-connector-federation/src/test/java/org/jboss/dna/connector/federation/FederationI18nTest.java 2008-07-24 19:52:13 UTC (rev 369)
@@ -0,0 +1,34 @@
+/*
+ * 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.connector.federation;
+
+import org.jboss.dna.common.AbstractI18nTest;
+
+/**
+ * @author Randall Hauch
+ */
+public class FederationI18nTest extends AbstractI18nTest {
+
+ public FederationI18nTest() {
+ super(FederationI18n.class);
+ }
+}
Added: trunk/connectors/dna-connector-federation/src/test/java/org/jboss/dna/connector/federation/ProjectionParserTest.java
===================================================================
--- trunk/connectors/dna-connector-federation/src/test/java/org/jboss/dna/connector/federation/ProjectionParserTest.java (rev 0)
+++ trunk/connectors/dna-connector-federation/src/test/java/org/jboss/dna/connector/federation/ProjectionParserTest.java 2008-07-24 19:52:13 UTC (rev 369)
@@ -0,0 +1,41 @@
+/*
+ * 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.connector.federation;
+
+import static org.hamcrest.core.Is.is;
+import static org.junit.Assert.assertThat;
+import org.junit.Test;
+
+/**
+ * @author Randall Hauch
+ */
+public class ProjectionParserTest {
+
+ private ProjectionParser parser;
+
+ @Test
+ public void shouldInitializeSingletonWithParserMethods() {
+ parser = ProjectionParser.getInstance();
+ assertThat(parser.getParserMethods().size(), is(1));
+ }
+
+}
Added: trunk/connectors/dna-connector-federation/src/test/java/org/jboss/dna/connector/federation/ProjectionPathRuleTest.java
===================================================================
--- trunk/connectors/dna-connector-federation/src/test/java/org/jboss/dna/connector/federation/ProjectionPathRuleTest.java (rev 0)
+++ trunk/connectors/dna-connector-federation/src/test/java/org/jboss/dna/connector/federation/ProjectionPathRuleTest.java 2008-07-24 19:52:13 UTC (rev 369)
@@ -0,0 +1,249 @@
+/*
+ * 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.connector.federation;
+
+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.junit.matchers.JUnitMatchers.hasItems;
+import org.jboss.dna.common.text.TextEncoder;
+import org.jboss.dna.common.text.UrlEncoder;
+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.connection.BasicExecutionEnvironment;
+import org.jboss.dna.spi.graph.connection.ExecutionEnvironment;
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * @author Randall Hauch
+ */
+public class ProjectionPathRuleTest {
+
+ private ExecutionEnvironment env;
+ private Projection.PathRule rule;
+ private PathFactory pathFactory;
+ private Path repositoryPath;
+ private Path sourcePath;
+ private Path[] validExceptions;
+ private NamespaceRegistry registry;
+ private TextEncoder encoder;
+
+ @Before
+ public void beforeEach() {
+ env = new BasicExecutionEnvironment();
+ pathFactory = env.getValueFactories().getPathFactory();
+ registry = env.getNamespaceRegistry();
+ encoder = new UrlEncoder();
+ repositoryPath = pathFactory.create("/a/b/c");
+ sourcePath = pathFactory.create("/x/y");
+ validExceptions = new Path[] {pathFactory.create("e/f"), pathFactory.create("e/g")};
+ rule = new Projection.PathRule(repositoryPath, sourcePath, validExceptions);
+ }
+
+ @Test
+ public void shouldCreateInstanceWithValidRepositoryPathAndValidSourcePathAndNoExceptions() {
+ rule = new Projection.PathRule(repositoryPath, sourcePath);
+ assertThat(rule.getPathInRepository(), is(sameInstance(repositoryPath)));
+ assertThat(rule.getPathInSource(), is(sameInstance(sourcePath)));
+ assertThat(rule.hasExceptionsToRule(), is(false));
+ }
+
+ @Test
+ public void shouldCreateInstanceWithValidRepositoryPathAndValidSourcePathAndValidExceptions() {
+ rule = new Projection.PathRule(repositoryPath, sourcePath, validExceptions);
+ assertThat(rule.getPathInRepository(), is(sameInstance(repositoryPath)));
+ assertThat(rule.getPathInSource(), is(sameInstance(sourcePath)));
+ assertThat(rule.hasExceptionsToRule(), is(true));
+ assertThat(rule.getExceptionsToRule(), hasItems(validExceptions));
+ }
+
+ @Test( expected = AssertionError.class )
+ public void shouldFailToCreateInstanceWithNullRepositoryPathAndValidSourcePathAndNoExceptions() {
+ repositoryPath = null;
+ new Projection.PathRule(repositoryPath, sourcePath);
+ }
+
+ @Test( expected = AssertionError.class )
+ public void shouldFailToCreateInstanceWithValidRepositoryPathAndNullSourcePathAndNoExceptions() {
+ sourcePath = null;
+ new Projection.PathRule(repositoryPath, sourcePath);
+ }
+
+ @Test( expected = AssertionError.class )
+ public void shouldFailToCreateInstanceWithValidRepositoryPathAndValidSourcePathAndAbsoluteExceptions() {
+ Path relativePath = validExceptions[0];
+ Path absolutePath = pathFactory.create("/j/k/l/m");
+ new Projection.PathRule(repositoryPath, sourcePath, relativePath, absolutePath);
+ }
+
+ @Test
+ public void shouldIncludeRepositoryPathsAtPathInRepository() {
+ assertThat(rule.includes(sourcePath), is(true));
+ }
+
+ @Test
+ public void shouldIncludeRepositoryPathsBelowPathInRepositoryThatAreNotExcluded() {
+ assertThat(rule.includes(pathFactory.create(sourcePath, "m")), is(true));
+ assertThat(rule.includes(pathFactory.create(sourcePath, "m/n")), is(true));
+ assertThat(rule.includes(pathFactory.create(sourcePath, "o/p")), is(true));
+ assertThat(rule.includes(pathFactory.create(sourcePath, "e/e")), is(true));
+ assertThat(rule.includes(pathFactory.create(sourcePath, "e")), is(true));
+ }
+
+ @Test
+ public void shouldNotIncludeRepositoryPathsBelowPathInRepositoryThatAreExcluded() {
+ assertThat(rule.includes(pathFactory.create(sourcePath, "e/f")), is(false));
+ assertThat(rule.includes(pathFactory.create(sourcePath, "e/g")), is(false));
+ assertThat(rule.includes(pathFactory.create(sourcePath, "e/f/g")), is(false));
+ assertThat(rule.includes(pathFactory.create(sourcePath, "e/g/h")), is(false));
+ }
+
+ @Test
+ public void shouldNotIncludeRepositoryPathsNotBelowPathInRepository() {
+ assertThat(rule.includes(pathFactory.create("/m/n")), is(false));
+ assertThat(rule.includes(pathFactory.create("/x/y[3]")), is(false));
+ }
+
+ @Test
+ public void shouldProjectRepositoryPathIntoSourcePath() {
+ assertThat(rule.projectPathInRepositoryToPathInSource(repositoryPath, pathFactory), is(sourcePath));
+ }
+
+ @Test
+ public void shouldProjectPathBelowRepositoryPathIntoPathBelowSourcePath() {
+ Path pathInRepository = pathFactory.create(repositoryPath, "m/n");
+ Path pathInSource = pathFactory.create(sourcePath, "m/n");
+ assertThat(rule.projectPathInRepositoryToPathInSource(pathInRepository, pathFactory), is(pathInSource));
+
+ pathInRepository = pathFactory.create(repositoryPath, "m");
+ pathInSource = pathFactory.create(sourcePath, "m");
+ assertThat(rule.projectPathInRepositoryToPathInSource(pathInRepository, pathFactory), is(pathInSource));
+
+ pathInRepository = pathFactory.create(repositoryPath, "m/n[3]");
+ pathInSource = pathFactory.create(sourcePath, "m/n[3]");
+ assertThat(rule.projectPathInRepositoryToPathInSource(pathInRepository, pathFactory), is(pathInSource));
+ }
+
+ @Test
+ public void shouldProjectSourcePathIntoRepositoryPath() {
+ assertThat(rule.projectPathInSourceToPathInRepository(sourcePath, pathFactory), is(repositoryPath));
+ }
+
+ @Test
+ public void shouldProjectPathBelowSourcePathIntoPathBelowRepositoryPath() {
+ Path pathInRepository = pathFactory.create(repositoryPath, "m/n");
+ Path pathInSource = pathFactory.create(sourcePath, "m/n");
+ assertThat(rule.projectPathInSourceToPathInRepository(pathInSource, pathFactory), is(pathInRepository));
+
+ pathInRepository = pathFactory.create(repositoryPath, "m");
+ pathInSource = pathFactory.create(sourcePath, "m");
+ assertThat(rule.projectPathInSourceToPathInRepository(pathInSource, pathFactory), is(pathInRepository));
+
+ pathInRepository = pathFactory.create(repositoryPath, "m/n[3]");
+ pathInSource = pathFactory.create(sourcePath, "m/n[3]");
+ assertThat(rule.projectPathInSourceToPathInRepository(pathInSource, pathFactory), is(pathInRepository));
+ }
+
+ @Test
+ public void shouldGetPathsInRepositoryGivenPathsInSourceAtOrBelowSourcePathIfNotExcluded() {
+ assertThat(rule.getPathInRepository(sourcePath, pathFactory), is(repositoryPath));
+ assertThatGetPathInRepositoryReturnsCorrectPathInSource("");
+ assertThatGetPathInRepositoryReturnsCorrectPathInSource("m/n");
+ assertThatGetPathInRepositoryReturnsCorrectPathInSource("m[0]");
+ assertThatGetPathInRepositoryReturnsCorrectPathInSource("m[0]/n/o/p");
+ }
+
+ protected void assertThatGetPathInRepositoryReturnsCorrectPathInSource( String subpath ) {
+ assertThat(rule.getPathInRepository(pathFactory.create(sourcePath, subpath), pathFactory),
+ is(pathFactory.create(repositoryPath, subpath)));
+ }
+
+ @Test
+ public void shouldGetNullPathInRepositoryGivenPathsInSourceAtOrBelowSourcePathIfExcluded() {
+ assertThat(rule.getPathInRepository(pathFactory.create(sourcePath, "e/f"), pathFactory), is(nullValue()));
+ assertThat(rule.getPathInRepository(pathFactory.create(sourcePath, "e/g"), pathFactory), is(nullValue()));
+ assertThat(rule.getPathInRepository(pathFactory.create(sourcePath, "e/f/h"), pathFactory), is(nullValue()));
+ assertThat(rule.getPathInRepository(pathFactory.create(sourcePath, "e/g/h"), pathFactory), is(nullValue()));
+ }
+
+ @Test
+ public void shouldGetNullPathInRepositoryGivenPathsInRepositoryNotAtOrBelowSourcePath() {
+ assertThat(rule.getPathInRepository(pathFactory.create("/m/n"), pathFactory), is(nullValue()));
+ }
+
+ @Test
+ public void shouldGetPathsInSourceGivenPathsInRepositoryAtOrBelowRepositoryPathIfNotExcluded() {
+ assertThat(rule.getPathInSource(repositoryPath, pathFactory), is(sourcePath));
+ assertThatGetPathInSourceReturnsCorrectPathInRepository("");
+ assertThatGetPathInSourceReturnsCorrectPathInRepository("m/n");
+ assertThatGetPathInSourceReturnsCorrectPathInRepository("m[0]");
+ assertThatGetPathInSourceReturnsCorrectPathInRepository("m[0]/n/o/p");
+
+ }
+
+ protected void assertThatGetPathInSourceReturnsCorrectPathInRepository( String subpath ) {
+ assertThat(rule.getPathInSource(pathFactory.create(repositoryPath, subpath), pathFactory),
+ is(pathFactory.create(sourcePath, subpath)));
+ }
+
+ @Test
+ public void shouldGetNullPathInSourceGivenPathsInRepositoryAtOrBelowRepositoryPathIfExcluded() {
+ assertThat(rule.getPathInSource(pathFactory.create(repositoryPath, "e/f"), pathFactory), is(nullValue()));
+ assertThat(rule.getPathInSource(pathFactory.create(repositoryPath, "e/g"), pathFactory), is(nullValue()));
+ assertThat(rule.getPathInSource(pathFactory.create(repositoryPath, "e/f/h"), pathFactory), is(nullValue()));
+ assertThat(rule.getPathInSource(pathFactory.create(repositoryPath, "e/g/h"), pathFactory), is(nullValue()));
+ }
+
+ @Test
+ public void shouldGetNullPathInSourceGivenPathsInRepositoryNotAtOrBelowRepositoryPath() {
+ assertThat(rule.getPathInSource(pathFactory.create("/m/n"), pathFactory), is(nullValue()));
+ }
+
+ @Test
+ public void shouldConvertToString() {
+ assertThat(rule.getString(registry, encoder), is("/a/b/c => /x/y $ e/f $ e/g"));
+
+ repositoryPath = pathFactory.create("/a/b/c");
+ sourcePath = pathFactory.create("/");
+ rule = new Projection.PathRule(repositoryPath, sourcePath, validExceptions);
+ assertThat(rule.getString(registry, encoder), is("/a/b/c => / $ e/f $ e/g"));
+
+ repositoryPath = pathFactory.create("/");
+ sourcePath = pathFactory.create("/");
+ rule = new Projection.PathRule(repositoryPath, sourcePath, validExceptions);
+ assertThat(rule.getString(registry, encoder), is("/ => / $ e/f $ e/g"));
+ }
+
+ @Test
+ public void shouldHaveToString() {
+ assertThat(rule.toString(), is("/{}a/{}b/{}c => /{}x/{}y $ {}e/{}f $ {}e/{}g"));
+
+ repositoryPath = pathFactory.create("/a/b/c");
+ sourcePath = pathFactory.create("/");
+ rule = new Projection.PathRule(repositoryPath, sourcePath, validExceptions);
+ assertThat(rule.toString(), is("/{}a/{}b/{}c => / $ {}e/{}f $ {}e/{}g"));
+ }
+
+}
Added: trunk/connectors/dna-connector-federation/src/test/java/org/jboss/dna/connector/federation/ProjectionTest.java
===================================================================
--- trunk/connectors/dna-connector-federation/src/test/java/org/jboss/dna/connector/federation/ProjectionTest.java (rev 0)
+++ trunk/connectors/dna-connector-federation/src/test/java/org/jboss/dna/connector/federation/ProjectionTest.java 2008-07-24 19:52:13 UTC (rev 369)
@@ -0,0 +1,231 @@
+/*
+ * 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.connector.federation;
+
+import static org.hamcrest.core.Is.is;
+import static org.junit.Assert.assertThat;
+import static org.junit.matchers.JUnitMatchers.hasItems;
+import static org.mockito.Mockito.stub;
+import java.util.Set;
+import org.jboss.dna.connector.federation.Projection;
+import org.jboss.dna.spi.graph.Path;
+import org.jboss.dna.spi.graph.PathFactory;
+import org.jboss.dna.spi.graph.connection.BasicExecutionEnvironment;
+import org.jboss.dna.spi.graph.connection.ExecutionEnvironment;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.MockitoAnnotations;
+import org.mockito.MockitoAnnotations.Mock;
+
+/**
+ * @author Randall Hauch
+ */
+public class ProjectionTest {
+
+ private ExecutionEnvironment env;
+ private String sourceName;
+ private Projection.Rule[] rules;
+ private Projection projection;
+ private PathFactory pathFactory;
+ @Mock
+ private Projection.Rule mockRule1;
+ @Mock
+ private Projection.Rule mockRule2;
+ @Mock
+ private Projection.Rule mockRule3;
+
+ @Before
+ public void beforeEach() {
+ MockitoAnnotations.initMocks(this);
+ env = new BasicExecutionEnvironment();
+ pathFactory = env.getValueFactories().getPathFactory();
+ sourceName = "Valid name";
+ rules = new Projection.Rule[] {mockRule1, mockRule2, mockRule3};
+ projection = new Projection(sourceName, rules);
+ }
+
+ @Test
+ public void shouldCreateInstanceWithValidNameAndValidRules() {
+ projection = new Projection(sourceName, rules);
+ assertThat(projection.getSourceName(), is(sourceName));
+ assertThat(projection.getRules().size(), is(rules.length));
+ assertThat(projection.getRules(), hasItems(mockRule1, mockRule2, mockRule3));
+ }
+
+ @Test( expected = IllegalArgumentException.class )
+ public void shouldFailToCreateInstanceWithNullNameAndValidRules() {
+ sourceName = null;
+ projection = new Projection(sourceName, rules);
+ }
+
+ @Test( expected = IllegalArgumentException.class )
+ public void shouldFailToCreateInstanceWithEmptyNameAndValidRules() {
+ sourceName = "";
+ projection = new Projection(sourceName, rules);
+ }
+
+ @Test( expected = IllegalArgumentException.class )
+ public void shouldFailToCreateInstanceWithBlankNameAndValidRules() {
+ sourceName = " \t ";
+ projection = new Projection(sourceName, rules);
+ }
+
+ @Test( expected = IllegalArgumentException.class )
+ public void shouldFailToCreateInstanceWithValidNameAndNullRules() {
+ rules = null;
+ projection = new Projection(sourceName, rules);
+ }
+
+ @Test( expected = IllegalArgumentException.class )
+ public void shouldFailToCreateInstanceWithValidNameAndEmptyRules() {
+ rules = new Projection.Rule[] {};
+ projection = new Projection(sourceName, rules);
+ }
+
+ @Test( expected = IllegalArgumentException.class )
+ public void shouldFailToCreateInstanceWithValidNameAndRulesArrayContainingAllNulls() {
+ projection = new Projection(sourceName, null, null, null);
+ }
+
+ @Test
+ public void shouldCreateInstanceWithValidNameAndRulesAndShouldPruneNullRuleReferences() {
+ projection = new Projection(sourceName, mockRule1, null, mockRule3);
+ assertThat(projection.getRules().size(), is(2));
+ assertThat(projection.getRules(), hasItems(mockRule1, mockRule3));
+ }
+
+ @Test( expected = IllegalArgumentException.class )
+ public void shouldFailToGetPathsInSourceGivenValidPathAndNullPathFactory() {
+ Path pathInRepository = pathFactory.create("/a/b/c");
+ projection.getPathsInSource(pathInRepository, null);
+ }
+
+ @Test
+ public void shouldGetNoPathsInSourceGivenNullPathInRepository() {
+ Set<Path> pathsInSource = projection.getPathsInSource(null, pathFactory);
+ assertThat(pathsInSource.isEmpty(), is(true));
+ }
+
+ @Test
+ public void shouldGetNoPathsInSourceGivenPathInRepositoryAndNoApplicableRules() {
+ Path pathInRepository = pathFactory.create("/a/b/c");
+ stub(mockRule1.getPathInSource(pathInRepository, pathFactory)).toReturn(null);
+ stub(mockRule2.getPathInSource(pathInRepository, pathFactory)).toReturn(null);
+ stub(mockRule3.getPathInSource(pathInRepository, pathFactory)).toReturn(null);
+ Set<Path> pathsInSource = projection.getPathsInSource(pathInRepository, pathFactory);
+ assertThat(pathsInSource.isEmpty(), is(true));
+ }
+
+ @Test
+ public void shouldGetPathInSourceGivenPathInRepositoryAndOneApplicableRules() {
+ Path pathInRepository = pathFactory.create("/a/b/c");
+ Path pathInSource = pathFactory.create("/d/e/f");
+ stub(mockRule1.getPathInSource(pathInRepository, pathFactory)).toReturn(pathInSource);
+ stub(mockRule2.getPathInSource(pathInRepository, pathFactory)).toReturn(null);
+ stub(mockRule3.getPathInSource(pathInRepository, pathFactory)).toReturn(null);
+ Set<Path> pathsInSource = projection.getPathsInSource(pathInRepository, pathFactory);
+ assertThat(pathsInSource, hasItems(pathInSource));
+ }
+
+ @Test
+ public void shouldGetPathsInSourceGivenPathInRepositoryAndMultipleApplicableRules() {
+ Path pathInRepository = pathFactory.create("/a/b/c");
+ Path pathInSource1 = pathFactory.create("/d/e/f");
+ Path pathInSource2 = pathFactory.create("/d/e/g");
+ Path pathInSource3 = pathFactory.create("/d/e/h");
+ stub(mockRule1.getPathInSource(pathInRepository, pathFactory)).toReturn(pathInSource1);
+ stub(mockRule2.getPathInSource(pathInRepository, pathFactory)).toReturn(pathInSource2);
+ stub(mockRule3.getPathInSource(pathInRepository, pathFactory)).toReturn(pathInSource3);
+ Set<Path> pathsInSource = projection.getPathsInSource(pathInRepository, pathFactory);
+ assertThat(pathsInSource, hasItems(pathInSource1, pathInSource2, pathInSource3));
+ }
+
+ @Test
+ public void shouldGetPathsInSourceGivenPathInRepositoryAndMultipleApplicableRulesReturningDuplicatePathsInSource() {
+ Path pathInRepository = pathFactory.create("/a/b/c");
+ Path pathInSource1 = pathFactory.create("/d/e/f");
+ Path pathInSource23 = pathFactory.create("/d/e/g");
+ stub(mockRule1.getPathInSource(pathInRepository, pathFactory)).toReturn(pathInSource1);
+ stub(mockRule2.getPathInSource(pathInRepository, pathFactory)).toReturn(pathInSource23);
+ stub(mockRule3.getPathInSource(pathInRepository, pathFactory)).toReturn(pathInSource23);
+ Set<Path> pathsInSource = projection.getPathsInSource(pathInRepository, pathFactory);
+ assertThat(pathsInSource, hasItems(pathInSource1, pathInSource23));
+ }
+
+ @Test( expected = IllegalArgumentException.class )
+ public void shouldFailToGetPathsInRepositoryGivenValidPathAndNullPathFactory() {
+ Path pathInSource = pathFactory.create("/a/b/c");
+ projection.getPathsInRepository(pathInSource, null);
+ }
+
+ @Test
+ public void shouldGetNoPathsInRepositoryGivenNullPathInSource() {
+ Set<Path> pathsInRepository = projection.getPathsInRepository(null, pathFactory);
+ assertThat(pathsInRepository.isEmpty(), is(true));
+ }
+
+ @Test
+ public void shouldGetNoPathsInRepositoryGivenPathInSourceAndNoApplicableRules() {
+ Path pathInSource = pathFactory.create("/d/e/f");
+ stub(mockRule1.getPathInRepository(pathInSource, pathFactory)).toReturn(null);
+ stub(mockRule2.getPathInRepository(pathInSource, pathFactory)).toReturn(null);
+ stub(mockRule3.getPathInRepository(pathInSource, pathFactory)).toReturn(null);
+ Set<Path> pathsInRepository = projection.getPathsInRepository(pathInSource, pathFactory);
+ assertThat(pathsInRepository.isEmpty(), is(true));
+ }
+
+ @Test
+ public void shouldGetPathInRepositoryGivenPathInSourceAndOneApplicableRules() {
+ Path pathInRepository = pathFactory.create("/a/b/c");
+ Path pathInSource = pathFactory.create("/d/e/f");
+ stub(mockRule1.getPathInRepository(pathInSource, pathFactory)).toReturn(pathInRepository);
+ stub(mockRule2.getPathInRepository(pathInSource, pathFactory)).toReturn(null);
+ stub(mockRule3.getPathInRepository(pathInSource, pathFactory)).toReturn(null);
+ Set<Path> pathsInRepository = projection.getPathsInRepository(pathInSource, pathFactory);
+ assertThat(pathsInRepository, hasItems(pathInRepository));
+ }
+
+ @Test
+ public void shouldGetPathsInRepositoryGivenPathInSourceAndMultipleApplicableRules() {
+ Path pathInSource = pathFactory.create("/a/b/c");
+ Path pathInRepository1 = pathFactory.create("/d/e/f");
+ Path pathInRepository2 = pathFactory.create("/d/e/g");
+ Path pathInRepository3 = pathFactory.create("/d/e/h");
+ stub(mockRule1.getPathInRepository(pathInSource, pathFactory)).toReturn(pathInRepository1);
+ stub(mockRule2.getPathInRepository(pathInSource, pathFactory)).toReturn(pathInRepository2);
+ stub(mockRule3.getPathInRepository(pathInSource, pathFactory)).toReturn(pathInRepository3);
+ Set<Path> pathsInRepository = projection.getPathsInRepository(pathInSource, pathFactory);
+ assertThat(pathsInRepository, hasItems(pathInRepository1, pathInRepository2, pathInRepository3));
+ }
+
+ @Test
+ public void shouldGetPathsInRepositoryGivenPathInSourceAndMultipleApplicableRulesReturningDuplicatePathsInRepository() {
+ Path pathInSource = pathFactory.create("/a/b/c");
+ Path pathInRepository1 = pathFactory.create("/d/e/f");
+ Path pathInRepository23 = pathFactory.create("/d/e/g");
+ stub(mockRule1.getPathInRepository(pathInSource, pathFactory)).toReturn(pathInRepository1);
+ stub(mockRule2.getPathInRepository(pathInSource, pathFactory)).toReturn(pathInRepository23);
+ stub(mockRule3.getPathInRepository(pathInSource, pathFactory)).toReturn(pathInRepository23);
+ Set<Path> pathsInRepository = projection.getPathsInRepository(pathInSource, pathFactory);
+ assertThat(pathsInRepository, hasItems(pathInRepository1, pathInRepository23));
+ }
+}
Added: trunk/connectors/dna-connector-federation/src/test/java/org/jboss/dna/connector/federation/merge/BasicFederatedNodeTest.java
===================================================================
--- trunk/connectors/dna-connector-federation/src/test/java/org/jboss/dna/connector/federation/merge/BasicFederatedNodeTest.java (rev 0)
+++ trunk/connectors/dna-connector-federation/src/test/java/org/jboss/dna/connector/federation/merge/BasicFederatedNodeTest.java 2008-07-24 19:52:13 UTC (rev 369)
@@ -0,0 +1,41 @@
+/*
+ * 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.connector.federation.merge;
+
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * @author Randall Hauch
+ */
+public class BasicFederatedNodeTest {
+
+ @Before
+ public void beforeEach() {
+ }
+
+ @Test
+ public void shouldDoSomething() {
+
+ }
+
+}
Modified: trunk/dna-repository/pom.xml
===================================================================
--- trunk/dna-repository/pom.xml 2008-07-23 17:17:39 UTC (rev 368)
+++ trunk/dna-repository/pom.xml 2008-07-24 19:52:13 UTC (rev 369)
@@ -43,6 +43,17 @@
<type>test-jar</type>
<scope>test</scope>
</dependency>
+ <dependency>
+ <groupId>org.jboss.dna</groupId>
+ <artifactId>dna-connector-federation</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.jboss.dna</groupId>
+ <artifactId>dna-connector-federation</artifactId>
+ <version>${dna-version}</version>
+ <type>test-jar</type>
+ <scope>test</scope>
+ </dependency>
<!--
Rules
-->
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-23 17:17:39 UTC (rev 368)
+++ trunk/dna-repository/src/main/java/org/jboss/dna/repository/RepositoryI18n.java 2008-07-24 19:52:13 UTC (rev 369)
@@ -41,6 +41,7 @@
public static I18n unableToUnregisterRepositoryInJndi;
public static I18n unableToRemoveRepository;
public static I18n unableToFindRepositoryWithName;
+ public static I18n unableToFindRepositorySourceWithName;
public static I18n errorProcessingEvents;
public static I18n errorFindingPropertyNameInPropertyAddedEvent;
public static I18n errorFindingPropertyNameInPropertyChangedEvent;
@@ -122,17 +123,7 @@
public static I18n warningSequencingXmlDocument;
// Federation
- 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;
- public static I18n repositoryHasBeenShutDown;
- public static I18n repositoryPathInFederationBindingIsNotAbsolute;
- public static I18n errorReadingMergePlan;
+ public static I18n errorStartingRepositoryService;
static {
try {
Copied: trunk/dna-repository/src/main/java/org/jboss/dna/repository/RepositoryService.java (from rev 346, trunk/dna-repository/src/main/java/org/jboss/dna/repository/federation/FederationService.java)
===================================================================
--- trunk/dna-repository/src/main/java/org/jboss/dna/repository/RepositoryService.java (rev 0)
+++ trunk/dna-repository/src/main/java/org/jboss/dna/repository/RepositoryService.java 2008-07-24 19:52:13 UTC (rev 369)
@@ -0,0 +1,368 @@
+/*
+ * 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;
+
+import java.lang.reflect.InvocationTargetException;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicBoolean;
+import net.jcip.annotations.ThreadSafe;
+import org.jboss.dna.common.collection.Problems;
+import org.jboss.dna.common.collection.SimpleProblems;
+import org.jboss.dna.common.component.ClassLoaderFactory;
+import org.jboss.dna.common.component.StandardClassLoaderFactory;
+import org.jboss.dna.common.util.ArgCheck;
+import org.jboss.dna.common.util.Reflection;
+import org.jboss.dna.connector.federation.FederatedRepositorySource;
+import org.jboss.dna.connector.federation.FederationException;
+import org.jboss.dna.connector.federation.Projection;
+import org.jboss.dna.connector.federation.executor.FederatingCommandExecutor;
+import org.jboss.dna.connector.federation.executor.SingleProjectionCommandExecutor;
+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.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.ValueFactories;
+import org.jboss.dna.spi.graph.ValueFactory;
+import org.jboss.dna.spi.graph.commands.GraphCommand;
+import org.jboss.dna.spi.graph.commands.executor.CommandExecutor;
+import org.jboss.dna.spi.graph.commands.executor.NoOpCommandExecutor;
+import org.jboss.dna.spi.graph.commands.impl.BasicCompositeCommand;
+import org.jboss.dna.spi.graph.commands.impl.BasicGetChildrenCommand;
+import org.jboss.dna.spi.graph.commands.impl.BasicGetNodeCommand;
+import org.jboss.dna.spi.graph.connection.ExecutionEnvironment;
+import org.jboss.dna.spi.graph.connection.RepositoryConnectionFactory;
+import org.jboss.dna.spi.graph.connection.RepositorySource;
+
+/**
+ * @author Randall Hauch
+ */
+@ThreadSafe
+public class RepositoryService implements AdministeredService {
+
+ protected static final String CLASSNAME_PROPERTY_NAME = "dna:classname";
+ protected static final String CLASSPATH_PROPERTY_NAME = "dna:classpath";
+ protected static final String PROJECTION_RULES_PROPERTY_NAME = "dna:projectionRules";
+ 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.
+ *
+ * @author Randall Hauch
+ */
+ protected class Administrator extends AbstractServiceAdministrator {
+
+ protected Administrator() {
+ super(RepositoryI18n.federationServiceName, State.PAUSED);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ protected boolean doCheckIsTerminated() {
+ return true;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ protected void doStart( State fromState ) {
+ super.doStart(fromState);
+ startService();
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.jboss.dna.repository.services.ServiceAdministrator#awaitTermination(long, java.util.concurrent.TimeUnit)
+ */
+ public boolean awaitTermination( long timeout,
+ TimeUnit unit ) {
+ return true;
+ }
+ }
+
+ private final ClassLoaderFactory classLoaderFactory;
+ private final ExecutionEnvironment env;
+ private final RepositorySourceManager sources;
+ private final Projection configurationProjection;
+ private final Administrator administrator = new Administrator();
+ private final AtomicBoolean started = new AtomicBoolean(false);
+
+ /**
+ * Create a federation service instance
+ *
+ * @param sources the source manager
+ * @param configurationProjection the projection defining where the service can find configuration information for the
+ * different repositories that it is to manage
+ * @param env the execution environment in which this service should run
+ * @param classLoaderFactory the class loader factory used to instantiate {@link RepositorySource} instances; may be null if
+ * this instance should use a default factory that attempts to load classes first from the
+ * {@link Thread#getContextClassLoader() thread's current context class loader} and then from the class loader that
+ * loaded this class.
+ * @throws IllegalArgumentException if the bootstrap source is null or the execution context is null
+ */
+ public RepositoryService( RepositorySourceManager sources,
+ Projection configurationProjection,
+ ExecutionEnvironment env,
+ ClassLoaderFactory classLoaderFactory ) {
+ ArgCheck.isNotNull(configurationProjection, "configurationProjection");
+ ArgCheck.isNotNull(sources, "sources");
+ ArgCheck.isNotNull(env, "env");
+ this.sources = sources;
+ this.configurationProjection = configurationProjection;
+ this.env = env;
+ this.classLoaderFactory = classLoaderFactory != null ? classLoaderFactory : new StandardClassLoaderFactory();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public ServiceAdministrator getAdministrator() {
+ return this.administrator;
+ }
+
+ /**
+ * @return configurationProjection
+ */
+ public Projection getConfigurationProjection() {
+ return configurationProjection;
+ }
+
+ /**
+ * @return sources
+ */
+ public RepositorySourceManager getRepositorySourceManager() {
+ return sources;
+ }
+
+ /**
+ * @return env
+ */
+ public ExecutionEnvironment getExecutionEnvironment() {
+ return env;
+ }
+
+ /**
+ * @return classLoaderFactory
+ */
+ public ClassLoaderFactory getClassLoaderFactory() {
+ return this.classLoaderFactory;
+ }
+
+ public String getJndiName() {
+ // TODO
+ return null;
+ }
+
+ protected synchronized void startService() {
+ if (this.started.get() == false) {
+ Problems problems = new SimpleProblems();
+
+ // ------------------------------------------------------------------------------------
+ // Read the configuration ...
+ // ------------------------------------------------------------------------------------
+ ValueFactories valueFactories = env.getValueFactories();
+ PathFactory pathFactory = valueFactories.getPathFactory();
+ NameFactory nameFactory = valueFactories.getNameFactory();
+
+ final String configurationSourceName = configurationProjection.getSourceName();
+ RepositoryConnectionFactory factory = sources.getConnectionFactory(configurationSourceName);
+ if (factory == null) {
+ throw new FederationException(RepositoryI18n.unableToFindRepositorySourceWithName.text(configurationSourceName));
+ }
+
+ // Create a federating command executor to execute the commands and merge the results into a single set of
+ // commands.
+ List<Projection> projections = Collections.singletonList(configurationProjection);
+ CommandExecutor executor = null;
+ if (configurationProjection.getRules().size() == 1) {
+ // There is just a single projection for the configuration repository, so just use an executor that
+ // translates the paths using the projection
+ executor = new SingleProjectionCommandExecutor(env, configurationSourceName, configurationProjection, sources);
+ } else if (configurationProjection.getRules().size() == 0) {
+ // There is no projection for the configuration repository, so just use a no-op executor
+ executor = new NoOpCommandExecutor(env, configurationSourceName);
+ } else {
+ // The configuration repository has more than one projection, so we need to merge the results
+ executor = new FederatingCommandExecutor(env, configurationSourceName, null, projections, sources);
+ }
+
+ // 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
+ Path configurationRoot = pathFactory.create("/");
+ try {
+ Path sourcesNode = pathFactory.create(configurationRoot, nameFactory.create("dna:sources"));
+ BasicGetChildrenCommand getSources = new BasicGetChildrenCommand(sourcesNode);
+ executor.execute(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));
+ }
+ executor.execute(commands);
+
+ // 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, true);
+ }
+ }
+ }
+ }
+ } catch (Throwable err) {
+ throw new FederationException(RepositoryI18n.errorStartingRepositoryService.text());
+ }
+ this.started.set(true);
+ }
+ }
+
+ /**
+ * Instantiate the {@link RepositorySource} 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 repository source instance, or null if it could not be created
+ */
+ @SuppressWarnings( "null" )
+ protected RepositorySource createRepositorySource( Path path,
+ Map<Name, Property> properties,
+ Problems problems ) {
+ ValueFactories valueFactories = env.getValueFactories();
+ NameFactory nameFactory = valueFactories.getNameFactory();
+ ValueFactory<String> stringFactory = valueFactories.getStringFactory();
+
+ // Get the classname and classpath ...
+ Property classnameProperty = properties.get(nameFactory.create(CLASSNAME_PROPERTY_NAME));
+ Property classpathProperty = properties.get(nameFactory.create(CLASSPATH_PROPERTY_NAME));
+ if (classnameProperty == null) {
+ problems.addError(RepositoryI18n.requiredPropertyIsMissingFromNode, CLASSNAME_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 = classpathProperty == null ? new String[] {} : stringFactory.create(classpathProperty.getValuesAsArray());
+ ClassLoader classLoader = this.classLoaderFactory.getClassLoader(classpath);
+ RepositorySource source = null;
+ try {
+ Class<?> sourceClass = classLoader.loadClass(classname);
+ source = (RepositorySource)sourceClass.newInstance();
+ } catch (ClassNotFoundException err) {
+ problems.addError(err, RepositoryI18n.unableToLoadClassUsingClasspath, classname, classpath);
+ } catch (IllegalAccessException err) {
+ problems.addError(err, RepositoryI18n.unableToAccessClassUsingClasspath, classname, classpath);
+ } catch (Throwable err) {
+ 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 ...
+ for (Map.Entry<Name, Property> entry : properties.entrySet()) {
+ Name propertyName = entry.getKey();
+ Property property = entry.getValue();
+ String javaPropertyName = propertyName.getLocalName();
+ if (property.isEmpty()) continue;
+ Object value = null;
+ if (property.isSingle()) {
+ value = property.getValues().next();
+ } else if (property.isMultiple()) {
+ value = property.getValuesAsArray();
+ }
+ try {
+ reflection.invokeSetterMethodOnTarget(javaPropertyName, source, value);
+ } 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
+ }
+ }
+ return source;
+ }
+
+ /**
+ * Get the current set of federated repository names.
+ *
+ * @return the names of the repository, which is a mutable copy of the names that is not backed by the actual sources
+ */
+ public Set<String> getFederatedRepositoryNames() {
+ Set<String> repositoryNames = new HashSet<String>();
+ for (RepositorySource source : sources.getSources()) {
+ if (source instanceof FederatedRepositorySource) {
+ repositoryNames.add(source.getName());
+ }
+ }
+ return repositoryNames;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public boolean equals( Object obj ) {
+ if (obj == this) return true;
+ return false;
+ }
+}
Property changes on: trunk/dna-repository/src/main/java/org/jboss/dna/repository/RepositoryService.java
___________________________________________________________________
Name: svn:mime-type
+ text/plain
Copied: trunk/dna-repository/src/main/java/org/jboss/dna/repository/RepositorySourceManager.java (from rev 339, trunk/dna-repository/src/main/java/org/jboss/dna/repository/federation/RepositorySourceManager.java)
===================================================================
--- trunk/dna-repository/src/main/java/org/jboss/dna/repository/RepositorySourceManager.java (rev 0)
+++ trunk/dna-repository/src/main/java/org/jboss/dna/repository/RepositorySourceManager.java 2008-07-24 19:52:13 UTC (rev 369)
@@ -0,0 +1,348 @@
+/*
+ * 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;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.concurrent.CopyOnWriteArrayList;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.locks.ReadWriteLock;
+import java.util.concurrent.locks.ReentrantReadWriteLock;
+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.RepositoryConnectionFactories;
+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 ReadWriteLock sourcesLock = new ReentrantReadWriteLock();
+ private final CopyOnWriteArrayList<RepositorySource> sources = new CopyOnWriteArrayList<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.sourcesLock.readLock().lock();
+ for (RepositorySource source : this.sources) {
+ if (source instanceof RepositoryConnectionPool) {
+ RepositoryConnectionPool pool = (RepositoryConnectionPool)source;
+ pool.shutdown();
+ }
+ }
+ } finally {
+ this.sourcesLock.readLock().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.sourcesLock.readLock().lock();
+ for (RepositorySource source : this.sources) {
+ if (source instanceof RepositoryConnectionPool) {
+ RepositoryConnectionPool pool = (RepositoryConnectionPool)source;
+ if (!pool.awaitTermination(timeout, unit)) {
+ return false;
+ }
+ }
+ }
+ return true;
+ } finally {
+ this.sourcesLock.readLock().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.sourcesLock.readLock().lock();
+ for (RepositorySource source : this.sources) {
+ if (source instanceof RepositoryConnectionPool) {
+ RepositoryConnectionPool pool = (RepositoryConnectionPool)source;
+ if (pool.isTerminating()) {
+ return true;
+ }
+ }
+ }
+ return false;
+ } finally {
+ this.sourcesLock.readLock().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.sourcesLock.readLock().lock();
+ for (RepositorySource source : this.sources) {
+ if (source instanceof RepositoryConnectionPool) {
+ RepositoryConnectionPool pool = (RepositoryConnectionPool)source;
+ if (!pool.isTerminated()) {
+ return false;
+ }
+ }
+ }
+ return true;
+ } finally {
+ this.sourcesLock.readLock().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);
+ }
+
+ /**
+ * 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
+ * @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,
+ boolean force ) {
+ if (source == null) return false;
+ try {
+ this.sourcesLock.writeLock().lock();
+ for (RepositorySource existingSource : this.sources) {
+ if (existingSource.getName().equals(source.getName())) return false;
+ }
+ return force ? this.sources.add(source) : this.sources.addIfAbsent(source);
+ } finally {
+ this.sourcesLock.writeLock().unlock();
+ }
+ }
+
+ /**
+ * 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.sourcesLock.writeLock().lock();
+ for (RepositorySource existingSource : this.sources) {
+ if (existingSource.getName().equals(name)) {
+ // 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.sourcesLock.writeLock().unlock();
+ }
+ return null;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.jboss.dna.spi.graph.connection.RepositoryConnectionFactories#getConnectionFactory(java.lang.String)
+ */
+ public RepositoryConnectionFactory getConnectionFactory( String sourceName ) {
+ try {
+ this.sourcesLock.readLock().lock();
+ for (RepositorySource existingSource : this.sources) {
+ if (existingSource.getName().equals(sourceName)) return existingSource;
+ }
+ RepositoryConnectionFactories delegate = this.delegate;
+ if (delegate != null) {
+ return delegate.getConnectionFactory(sourceName);
+ }
+ } finally {
+ this.sourcesLock.readLock().unlock();
+ }
+ return null;
+ }
+
+}
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-23 17:17:39 UTC (rev 368)
+++ trunk/dna-repository/src/main/resources/org/jboss/dna/repository/RepositoryI18n.properties 2008-07-24 19:52:13 UTC (rev 369)
@@ -23,11 +23,12 @@
serviceShutdowAndMayNotBeStarted = The {0} has been shutdown and may not be (re)started
serviceShutdowAndMayNotBePaused = The {0} has been shutdown and my not be paused
serviceNotShutdowAndMayNotBeTerminated = The {0} has not been shutdown and may not be terminated
-unableToFindRepositoryInJndi = Unable to find a JCR repository in JNDI at "{0}"
-unableToRegisterRepositoryInJndi = Unable to register a JCR repository in JNDI at "{0}"
-unableToUnregisterRepositoryInJndi = Unable to unregister a JCR repository at JNDI at "{0}"
-unableToRemoveRepository = Unable to remove a JCR repository named "{0}"
-unableToFindRepositoryWithName = Unable to find a JCR repository named "{0}"
+unableToFindRepositoryInJndi = Unable to find a repository in JNDI at "{0}"
+unableToRegisterRepositoryInJndi = Unable to register a repository in JNDI at "{0}"
+unableToUnregisterRepositoryInJndi = Unable to unregister a repository at JNDI at "{0}"
+unableToRemoveRepository = Unable to remove a repository named "{0}"
+unableToFindRepositoryWithName = Unable to find a repository named "{0}"
+unableToFindRepositorySourceWithName = Unable to find a repository source named "{0}"
errorProcessingEvents = Error processing events from {0}
errorFindingPropertyNameInPropertyAddedEvent = Error finding the name of the added property in the event path {0}
errorFindingPropertyNameInPropertyChangedEvent = Error finding the name of the changed property in the event path {0}
@@ -101,14 +102,4 @@
canceledSequencingXmlDocument = Canceled sequencing XML
warningSequencingXmlDocument = A warning was received while sequencing XML: {0}
-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 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}"
-errorReadingMergePlan = Error while reading merge plan for {0}
\ No newline at end of file
+errorStartingRepositoryService = Error while starting repository service
Copied: trunk/dna-repository/src/test/java/org/jboss/dna/repository/RepositoryServiceTest.java (from rev 346, trunk/dna-repository/src/test/java/org/jboss/dna/repository/federation/FederationServiceTest.java)
===================================================================
--- trunk/dna-repository/src/test/java/org/jboss/dna/repository/RepositoryServiceTest.java (rev 0)
+++ trunk/dna-repository/src/test/java/org/jboss/dna/repository/RepositoryServiceTest.java 2008-07-24 19:52:13 UTC (rev 369)
@@ -0,0 +1,293 @@
+/*
+ * 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;
+
+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 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.common.util.Logger;
+import org.jboss.dna.connector.federation.FederationException;
+import org.jboss.dna.connector.federation.Projection;
+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.connection.SimpleRepository;
+import org.jboss.dna.spi.graph.connection.SimpleRepositorySource;
+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.Test;
+import org.mockito.MockitoAnnotations;
+import org.mockito.MockitoAnnotations.Mock;
+
+/**
+ * @author Randall Hauch
+ */
+public class RepositoryServiceTest {
+
+ public static final String CLASSNAME = RepositoryService.CLASSNAME_PROPERTY_NAME;
+ public static final String CLASSPATH = RepositoryService.CLASSPATH_PROPERTY_NAME;
+ public static final String PROJECTION_RULES = RepositoryService.PROJECTION_RULES_PROPERTY_NAME;
+ public static final String TIME_TO_EXPIRE = RepositoryService.CACHE_POLICY_TIME_TO_EXPIRE;
+ public static final String TIME_TO_CACHE = RepositoryService.CACHE_POLICY_TIME_TO_CACHE;
+
+ private RepositoryService service;
+ private Projection configProjection;
+ private StandardValueFactories valueFactories;
+ private PropertyFactory propertyFactory;
+ private PathFactory pathFactory;
+ private String configSourceName;
+ private SimpleRepository configRepository;
+ private SimpleRepositorySource configRepositorySource;
+ @Mock
+ 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";
+ Projection.Rule configProjectionRule = new Projection.PathRule(pathInRepository, pathInSource);
+ configProjection = new Projection(configSourceName, configProjectionRule);
+ 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 RepositoryService(sources, configProjection, env, null);
+ }
+
+ @After
+ public void afterEach() throws Exception {
+ service.getAdministrator().shutdown();
+ service.getAdministrator().awaitTermination(4, TimeUnit.SECONDS);
+ SimpleRepository.shutdownAll();
+ Logger.getLogger(getClass()).trace("");
+ }
+
+ @Test
+ public void shouldHaveServiceAdministratorAfterInstantiation() {
+ assertThat(service.getAdministrator(), is(notNullValue()));
+ }
+
+ @Test
+ public void shouldHaveConfigurationRegionAfterInstantiation() {
+ assertThat(service.getConfigurationProjection(), is(notNullValue()));
+ assertThat(service.getConfigurationProjection(), is(sameInstance(configProjection)));
+ }
+
+ @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 RepositoryService(sources, configProjection, 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 RepositoryService(sources, configProjection, 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(2)).getConnectionFactory(configSourceName); // once for checking source, second for getting
+
+ // 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/source A", PROJECTION_RULES, "/a/b/c => /sx/sy");
+ configRepository.setProperty(env, fedReposPath + "dna:regions/source B", PROJECTION_RULES, "/ => /");
+ configRepository.setProperty(env, fedReposPath + "dna:regions/source C", PROJECTION_RULES, "/d/e/f => /");
+ configRepository.setProperty(env, fedReposPath + "dna:regions/source D", PROJECTION_RULES, "/ => /x/y/z");
+
+ // Now, start up the service ...
+ service.getAdministrator().start();
+
+ // // Create the repository ...
+ // FederatedRepositorySource repository = (FederatedRepositorySource)sources.getConnectionFactory("fed repos");
+ // assertThat(repository, is(notNullValue()));
+ // assertThat(repository.getName(), is("fed repos"));
+ // assertThat(repository.getDefaultCachePolicy().getTimeToCache(), is(10000l));
+ // assertThat(repository.getDefaultCachePolicy().getTimeToExpire(), is(20000l));
+ // assertThat(repository.getCacheProjection(), is(sameInstance(configProjection)));
+ // assertThat(repository.getConfiguration().getSourceProjections().get(0).getPathsInSource(pathFactory.create("/a/b/c"),
+ // pathFactory),
+ // hasItems(pathFactory.create("/sx/sy")));
+ // assertThat(repository.getConfiguration().getSourceProjections().get(0).getSourceName(), is("source A"));
+ // assertThat(repository.getConfiguration().getSourceProjections().get(1).getPathsInSource(pathFactory.create("/"),
+ // pathFactory),
+ // hasItems(pathFactory.create("/")));
+ // assertThat(repository.getConfiguration().getSourceProjections().get(1).getSourceName(), is("source B"));
+ // assertThat(repository.getConfiguration().getSourceProjections().get(2).getPathsInSource(pathFactory.create("/d/e/f"),
+ // pathFactory),
+ // hasItems(pathFactory.create("/")));
+ // assertThat(repository.getConfiguration().getSourceProjections().get(2).getSourceName(), is("source C"));
+ // assertThat(repository.getConfiguration().getSourceProjections().get(3).getPathsInSource(pathFactory.create("/"),
+ // pathFactory),
+ // hasItems(pathFactory.create("/x/y/z")));
+ // assertThat(repository.getConfiguration().getSourceProjections().get(3).getSourceName(), is("source A"));
+ //
+ // for (int i = 0; i != 10; ++i) {
+ // assertThat(service.getRepository("fed repos"), is(sameInstance(repository)));
+ // }
+ }
+
+}
Added: trunk/dna-spi/src/main/java/org/jboss/dna/spi/ExecutionContextFactory.java
===================================================================
--- trunk/dna-spi/src/main/java/org/jboss/dna/spi/ExecutionContextFactory.java (rev 0)
+++ trunk/dna-spi/src/main/java/org/jboss/dna/spi/ExecutionContextFactory.java 2008-07-24 19:52:13 UTC (rev 369)
@@ -0,0 +1,91 @@
+/*
+ * 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;
+
+import javax.security.auth.Subject;
+import javax.security.auth.callback.CallbackHandler;
+import javax.security.auth.login.LoginContext;
+import javax.security.auth.login.LoginException;
+import javax.security.auth.spi.LoginModule;
+import org.jboss.dna.spi.graph.connection.ExecutionEnvironment;
+
+/**
+ * A factory for creating {@link ExecutionEnvironment} instances. Each execution environment is affiliated with a JAAS
+ * {@link Subject}, and thus the factory methods take the same parameters that the JAAS {@link LoginContext} take.
+ *
+ * @author Randall Hauch
+ */
+public interface ExecutionContextFactory {
+
+ /**
+ * Create an {@link ExecutionEnvironment} for the supplied {@link LoginContext}.
+ *
+ * @param loginContext the JAAS login context
+ * @return the execution context
+ * @throws IllegalArgumentException if the <code>loginContext</code> is null
+ */
+ ExecutionEnvironment create( LoginContext loginContext );
+
+ /**
+ * @param name the name of the JAAS login context
+ * @return the execution context
+ * @throws IllegalArgumentException if the <code>name</code> is null
+ * @throws LoginException if there <code>name</code> is invalid (or there is no login context named "other"), or if the
+ * default callback handler JAAS property was not set or could not be loaded
+ */
+ ExecutionEnvironment create( String name ) throws LoginException;
+
+ /**
+ * @param name the name of the JAAS login context
+ * @param subject the subject to authenticate
+ * @return the execution context
+ * @throws LoginException if there <code>name</code> is invalid (or there is no login context named "other"), if the default
+ * callback handler JAAS property was not set or could not be loaded, or if the <code>subject</code> is null or
+ * unknown
+ */
+ ExecutionEnvironment create( String name,
+ Subject subject ) throws LoginException;
+
+ /**
+ * @param name the name of the JAAS login context
+ * @param callbackHandler the callback handler that will be used by {@link LoginModule}s to communicate with the user.
+ * @return the execution context
+ * @throws LoginException if there <code>name</code> is invalid (or there is no login context named "other"), or if the
+ * <code>callbackHandler</code> is null
+ */
+ ExecutionEnvironment create( String name,
+ CallbackHandler callbackHandler ) throws LoginException;
+
+ /**
+ * @param name the name of the JAAS login context
+ * @param subject the subject to authenticate
+ * @param callbackHandler the callback handler that will be used by {@link LoginModule}s to communicate with the user.
+ * @return the execution context
+ * @throws LoginException if there <code>name</code> is invalid (or there is no login context named "other"), if the default
+ * callback handler JAAS property was not set or could not be loaded, if the <code>subject</code> is null or unknown,
+ * or if the <code>callbackHandler</code> is null
+ */
+ ExecutionEnvironment create( String name,
+ Subject subject,
+ CallbackHandler callbackHandler ) throws LoginException;
+
+}
Modified: trunk/dna-spi/src/main/java/org/jboss/dna/spi/SpiI18n.java
===================================================================
--- trunk/dna-spi/src/main/java/org/jboss/dna/spi/SpiI18n.java 2008-07-23 17:17:39 UTC (rev 368)
+++ trunk/dna-spi/src/main/java/org/jboss/dna/spi/SpiI18n.java 2008-07-24 19:52:13 UTC (rev 369)
@@ -59,6 +59,11 @@
public static I18n pathExpressionHasInvalidSelect;
public static I18n pathExpressionHasInvalidMatch;
+ public static I18n executingGraphCommand;
+ public static I18n executedGraphCommand;
+ public static I18n closingCommandExecutor;
+ public static I18n closedCommandExecutor;
+
static {
try {
I18n.initialize(SpiI18n.class);
Modified: trunk/dna-spi/src/main/java/org/jboss/dna/spi/graph/Path.java
===================================================================
--- trunk/dna-spi/src/main/java/org/jboss/dna/spi/graph/Path.java 2008-07-23 17:17:39 UTC (rev 368)
+++ trunk/dna-spi/src/main/java/org/jboss/dna/spi/graph/Path.java 2008-07-24 19:52:13 UTC (rev 369)
@@ -105,14 +105,14 @@
public static final TextDecoder URL_DECODER = new UrlEncoder().setSlashEncoded(true);
/**
- * The default text encoder to be used when none is otherwise specified. This is currently the
- * {@link #JSR283_ENCODER JSR-283 encoder}.
+ * The default text encoder to be used when none is otherwise specified. This is currently the {@link #JSR283_ENCODER JSR-283
+ * encoder}.
*/
public static final TextEncoder DEFAULT_ENCODER = JSR283_ENCODER;
/**
- * The default text decoder to be used when none is otherwise specified. This is currently the
- * {@link #JSR283_ENCODER JSR-283 encoder}.
+ * The default text decoder to be used when none is otherwise specified. This is currently the {@link #JSR283_ENCODER JSR-283
+ * encoder}.
*/
public static final TextDecoder DEFAULT_DECODER = JSR283_DECODER;
@@ -274,20 +274,40 @@
public boolean isRoot();
/**
- * Determine whether this path represents the same as the supplied path. This is equivalent to calling
- * <code>this.compareTo(other) == 0 </code>.
+ * Determine whether this path represents the same as the supplied path. This is equivalent to calling <code>
+ * this.compareTo(other) == 0 </code>.
*
- * @param other the other path to compare with this path
+ * @param other the other path to compare with this path; may be null
* @return true if the paths are equivalent, or false otherwise
*/
- public boolean isSame( Path other );
+ public boolean isSameAs( Path other );
/**
+ * Determine whether this path is the {@link #isSameAs(Path) same as} to or a {@link #isAncestorOf(Path) ancestor of} the
+ * supplied path. This method is equivalent to (but may be more efficient than) calling <code>isSame(other) ||
+ * isAncestor(other)</code>, and is a convenience method that is identical to calling <code>other.isAtOrBelow(this)</code>.
+ *
+ * @param other the other path to compare with this path; may be null
+ * @return true if the paths are equivalent or if this path is considered an ancestor of the other path, or false otherwise
+ */
+ public boolean isAtOrAbove( Path other );
+
+ /**
+ * Determine whether this path is the {@link #isSameAs(Path) same as} to or a {@link #isDecendantOf(Path) decendant of} the
+ * supplied path. This method is equivalent to (but may be more efficient than) calling <code>isSame(other) ||
+ * isAncestor(other)</code>.
+ *
+ * @param other the other path to compare with this path; may be null
+ * @return true if the paths are equivalent or if this path is considered a decendant of the other path, or false otherwise
+ */
+ public boolean isAtOrBelow( Path other );
+
+ /**
* Determine whether this path is an ancestor of the supplied path. A path is considered an ancestor of another path if the
* the ancestor path appears in its entirety at the beginning of the decendant path, and where the decendant path contains at
* least one additional segment.
*
- * @param decendant the path that may be the decendant
+ * @param decendant the path that may be the decendant; may be null
* @return true if this path is an ancestor of the supplied path, or false otherwise
*/
public boolean isAncestorOf( Path decendant );
@@ -296,14 +316,14 @@
* Determine whether this path is an decendant of the supplied path. A path is considered a decendant of another path if the
* the decendant path starts exactly with the entire ancestor path but contains at least one additional segment.
*
- * @param ancestor the path that may be the ancestor
+ * @param ancestor the path that may be the ancestor; may be null
* @return true if this path is an decendant of the supplied path, or false otherwise
*/
public boolean isDecendantOf( Path ancestor );
/**
- * Return whether this path is an absolute path. A path is either relative or {@link #isAbsolute() absolute}. An absolute
- * path starts with a "/".
+ * Return whether this path is an absolute path. A path is either relative or {@link #isAbsolute() absolute}. An absolute path
+ * starts with a "/".
*
* @return true if the path is absolute, or false otherwise
*/
@@ -372,11 +392,11 @@
public Path getAncestor();
/**
- * Return the path to the ancestor of the supplied degree. An ancestor of degree <code>x</code> is the path that is
- * <code>x</code> levels up along the path. For example, <code>degree = 0</code> returns this path, while
- * <code>degree = 1</code> returns the parent of this path, <code>degree = 2</code> returns the grandparent of this path,
- * and so on. Note that the result may be unexpected if this path is not {@link #isNormalized() normalized}, as a
- * non-normalized path contains ".." and "." segments.
+ * Return the path to the ancestor of the supplied degree. An ancestor of degree <code>x</code> is the path that is <code>x
+ * </code> levels up along the path. For example, <code>degree = 0</code> returns this path, while <code>degree = 1</code>
+ * returns the parent of this path, <code>degree = 2</code> returns the grandparent of this path, and so on. Note that the
+ * result may be unexpected if this path is not {@link #isNormalized() normalized}, as a non-normalized path contains ".." and
+ * "." segments.
*
* @param degree
* @return the ancestor of the supplied degree
@@ -426,21 +446,20 @@
*
* @param beginIndex the beginning index, inclusive.
* @return the specified subpath
- * @exception IndexOutOfBoundsException if the <code>beginIndex</code> is negative or larger than the length of this
- * <code>Path</code> object
+ * @exception IndexOutOfBoundsException if the <code>beginIndex</code> is negative or larger than the length of this <code>
+ * Path</code> object
*/
public Path subpath( int beginIndex );
/**
- * Return a new path consisting of the segments between the <code>beginIndex</code> index (inclusive) and the
- * <code>endIndex</code> index (exclusive).
+ * Return a new path consisting of the segments between the <code>beginIndex</code> index (inclusive) and the <code>endIndex
+ * </code> index (exclusive).
*
* @param beginIndex the beginning index, inclusive.
* @param endIndex the ending index, exclusive.
* @return the specified subpath
- * @exception IndexOutOfBoundsException if the <code>beginIndex</code> is negative, or <code>endIndex</code> is larger
- * than the length of this <code>Path</code> object, or <code>beginIndex</code> is larger than
- * <code>endIndex</code>.
+ * @exception IndexOutOfBoundsException if the <code>beginIndex</code> is negative, or <code>endIndex</code> is larger than
+ * the length of this <code>Path</code> object, or <code>beginIndex</code> is larger than <code>endIndex</code>.
*/
public Path subpath( int beginIndex,
int endIndex );
Modified: trunk/dna-spi/src/main/java/org/jboss/dna/spi/graph/PathFactory.java
===================================================================
--- trunk/dna-spi/src/main/java/org/jboss/dna/spi/graph/PathFactory.java 2008-07-23 17:17:39 UTC (rev 368)
+++ trunk/dna-spi/src/main/java/org/jboss/dna/spi/graph/PathFactory.java 2008-07-24 19:52:13 UTC (rev 369)
@@ -60,8 +60,8 @@
Path createAbsolutePath( Path.Segment... segments );
/**
- * Create an empty relative path (i.e., equivalent to {@link #createRelativePath(Path.Segment...) createRelativePath}({@link Path#SELF_SEGMENT})).
- * Subsequent calls will always return the same instance.
+ * Create an empty relative path (i.e., equivalent to {@link #createRelativePath(Path.Segment...) createRelativePath}(
+ * {@link Path#SELF_SEGMENT})). Subsequent calls will always return the same instance.
*
* @return the new path
*/
@@ -136,12 +136,23 @@
Path.Segment... segments );
/**
+ * Create a path by appending the supplied names to the parent path.
+ *
+ * @param parentPath the path that is to provide the basis for the new path
+ * @param subpath the subpath to be appended to the parent path, which must be in the form of a relative path
+ * @return the new path
+ * @throws IllegalArgumentException if the parent path reference or the segment name is null, or if the index is invalid
+ */
+ Path create( Path parentPath,
+ String subpath );
+
+ /**
* Create a path segment given the supplied segment name. The resulting segment will have no index.
*
* @param segmentName the name of the segment
* @return the segment
- * @throws IllegalArgumentException if the segment name reference is <code>null</code> or the value could not be created
- * from the supplied string
+ * @throws IllegalArgumentException if the segment name reference is <code>null</code> or the value could not be created from
+ * the supplied string
*/
Path.Segment createSegment( String segmentName );
@@ -151,8 +162,8 @@
* @param segmentName the name of the segment
* @param decoder the decoder that should be used to decode the qualified name
* @return the segment
- * @throws IllegalArgumentException if the segment name reference is <code>null</code> or the value could not be created
- * from the supplied string
+ * @throws IllegalArgumentException if the segment name reference is <code>null</code> or the value could not be created from
+ * the supplied string
*/
Path.Segment createSegment( String segmentName,
TextDecoder decoder );
Modified: trunk/dna-spi/src/main/java/org/jboss/dna/spi/graph/commands/executor/AbstractCommandExecutor.java
===================================================================
--- trunk/dna-spi/src/main/java/org/jboss/dna/spi/graph/commands/executor/AbstractCommandExecutor.java 2008-07-23 17:17:39 UTC (rev 368)
+++ trunk/dna-spi/src/main/java/org/jboss/dna/spi/graph/commands/executor/AbstractCommandExecutor.java 2008-07-24 19:52:13 UTC (rev 369)
@@ -21,6 +21,7 @@
*/
package org.jboss.dna.spi.graph.commands.executor;
+import org.jboss.dna.spi.graph.DateTime;
import org.jboss.dna.spi.graph.commands.CompositeCommand;
import org.jboss.dna.spi.graph.commands.CopyBranchCommand;
import org.jboss.dna.spi.graph.commands.CopyNodeCommand;
@@ -58,13 +59,21 @@
private final ExecutionEnvironment env;
private final String sourceName;
+ private final DateTime nowInUtc;
protected AbstractCommandExecutor( ExecutionEnvironment env,
String sourceName ) {
+ this(env, sourceName, null);
+ }
+
+ protected AbstractCommandExecutor( ExecutionEnvironment env,
+ String sourceName,
+ DateTime now ) {
assert env != null;
assert sourceName != null && sourceName.trim().length() != 0;
this.env = env;
this.sourceName = sourceName;
+ this.nowInUtc = now != null ? now.toUtcTimeZone() : env.getValueFactories().getDateFactory().createUtc();
}
/**
@@ -86,6 +95,15 @@
}
/**
+ * Get the current time associated with this executor. All calls to this method will result in the same time.
+ *
+ * @return the current time expressed in UTC
+ */
+ public DateTime getCurrentTimeInUtc() {
+ return nowInUtc;
+ }
+
+ /**
* {@inheritDoc}
* <p>
* This implementation examines the instance to see which {@link GraphCommand command interfaces} are implemented by the
@@ -101,6 +119,9 @@
return;
}
// The command could implement multiple "get" behaviors
+ if (command instanceof GetNodeCommand) {
+ execute((GetNodeCommand)command);
+ }
if (command instanceof GetPropertiesCommand) {
execute((GetPropertiesCommand)command);
}
@@ -145,7 +166,22 @@
/**
* {@inheritDoc}
+ * <p>
+ * This method implementation simply delegates to both the {@link #execute(GetPropertiesCommand)} and
+ * {@link #execute(GetChildrenCommand)} methods, and should be overridden by subclasses that can process
+ * {@link GetNodeCommand} more efficiently as a single command.
+ * </p>
*
+ * @see org.jboss.dna.spi.graph.commands.executor.CommandExecutor#execute(org.jboss.dna.spi.graph.commands.GetNodeCommand)
+ */
+ public void execute( GetNodeCommand command ) throws RepositorySourceException, InterruptedException {
+ execute((GetPropertiesCommand)command);
+ execute((GetChildrenCommand)command);
+ }
+
+ /**
+ * {@inheritDoc}
+ *
* @see org.jboss.dna.spi.graph.commands.executor.CommandExecutor#execute(org.jboss.dna.spi.graph.commands.GetPropertiesCommand)
*/
@SuppressWarnings( "unused" )
Modified: trunk/dna-spi/src/main/java/org/jboss/dna/spi/graph/commands/executor/CommandExecutor.java
===================================================================
--- trunk/dna-spi/src/main/java/org/jboss/dna/spi/graph/commands/executor/CommandExecutor.java 2008-07-23 17:17:39 UTC (rev 368)
+++ trunk/dna-spi/src/main/java/org/jboss/dna/spi/graph/commands/executor/CommandExecutor.java 2008-07-24 19:52:13 UTC (rev 369)
@@ -27,6 +27,7 @@
import org.jboss.dna.spi.graph.commands.CreateNodeCommand;
import org.jboss.dna.spi.graph.commands.DeleteBranchCommand;
import org.jboss.dna.spi.graph.commands.GetChildrenCommand;
+import org.jboss.dna.spi.graph.commands.GetNodeCommand;
import org.jboss.dna.spi.graph.commands.GetPropertiesCommand;
import org.jboss.dna.spi.graph.commands.GraphCommand;
import org.jboss.dna.spi.graph.commands.MoveBranchCommand;
@@ -60,6 +61,17 @@
void execute( CompositeCommand command ) throws RepositorySourceException, InterruptedException;
/**
+ * Execute a command to get the properties and children of a node. {@link GetNodeCommand} is a subtype of both
+ * {@link GetPropertiesCommand} and {@link GetChildrenCommand}, so this method will be called in place of the
+ * {@link #execute(GetPropertiesCommand)} and {@link #execute(GetChildrenCommand)} methods.
+ *
+ * @param command the command to be executed; may not be null
+ * @throws RepositorySourceException if there is an error executing the command
+ * @throws InterruptedException if the thread is interrupted during execution
+ */
+ void execute( GetNodeCommand command ) throws RepositorySourceException, InterruptedException;
+
+ /**
* Execute a command to get the properties of a node.
*
* @param command the command to be executed; may not be null
Added: trunk/dna-spi/src/main/java/org/jboss/dna/spi/graph/commands/executor/DelegatingCommandExecutor.java
===================================================================
--- trunk/dna-spi/src/main/java/org/jboss/dna/spi/graph/commands/executor/DelegatingCommandExecutor.java (rev 0)
+++ trunk/dna-spi/src/main/java/org/jboss/dna/spi/graph/commands/executor/DelegatingCommandExecutor.java 2008-07-24 19:52:13 UTC (rev 369)
@@ -0,0 +1,167 @@
+/*
+ * 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.executor;
+
+import org.jboss.dna.spi.graph.commands.CompositeCommand;
+import org.jboss.dna.spi.graph.commands.CopyBranchCommand;
+import org.jboss.dna.spi.graph.commands.CopyNodeCommand;
+import org.jboss.dna.spi.graph.commands.CreateNodeCommand;
+import org.jboss.dna.spi.graph.commands.DeleteBranchCommand;
+import org.jboss.dna.spi.graph.commands.GetChildrenCommand;
+import org.jboss.dna.spi.graph.commands.GetNodeCommand;
+import org.jboss.dna.spi.graph.commands.GetPropertiesCommand;
+import org.jboss.dna.spi.graph.commands.GraphCommand;
+import org.jboss.dna.spi.graph.commands.MoveBranchCommand;
+import org.jboss.dna.spi.graph.commands.RecordBranchCommand;
+import org.jboss.dna.spi.graph.commands.SetPropertiesCommand;
+import org.jboss.dna.spi.graph.connection.RepositorySourceException;
+
+/**
+ * @author Randall Hauch
+ */
+public class DelegatingCommandExecutor implements CommandExecutor {
+
+ private final CommandExecutor delegate;
+
+ public DelegatingCommandExecutor( CommandExecutor delegate ) {
+ assert delegate != null;
+ this.delegate = delegate;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.jboss.dna.spi.graph.commands.executor.CommandExecutor#close()
+ */
+ public void close() throws InterruptedException {
+ delegate.close();
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.jboss.dna.spi.graph.commands.executor.CommandExecutor#execute(org.jboss.dna.spi.graph.commands.GraphCommand)
+ */
+ public void execute( GraphCommand command ) throws RepositorySourceException, InterruptedException {
+ delegate.execute(command);
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.jboss.dna.spi.graph.commands.executor.CommandExecutor#execute(org.jboss.dna.spi.graph.commands.CompositeCommand)
+ */
+ public void execute( CompositeCommand command ) throws RepositorySourceException, InterruptedException {
+ delegate.execute(command);
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.jboss.dna.spi.graph.commands.executor.CommandExecutor#execute(org.jboss.dna.spi.graph.commands.GetNodeCommand)
+ */
+ public void execute( GetNodeCommand command ) throws RepositorySourceException, InterruptedException {
+ delegate.execute(command);
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.jboss.dna.spi.graph.commands.executor.CommandExecutor#execute(org.jboss.dna.spi.graph.commands.GetPropertiesCommand)
+ */
+ public void execute( GetPropertiesCommand command ) throws RepositorySourceException, InterruptedException {
+ delegate.execute(command);
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.jboss.dna.spi.graph.commands.executor.CommandExecutor#execute(org.jboss.dna.spi.graph.commands.GetChildrenCommand)
+ */
+ public void execute( GetChildrenCommand command ) throws RepositorySourceException, InterruptedException {
+ delegate.execute(command);
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.jboss.dna.spi.graph.commands.executor.CommandExecutor#execute(org.jboss.dna.spi.graph.commands.CreateNodeCommand)
+ */
+ public void execute( CreateNodeCommand command ) throws RepositorySourceException, InterruptedException {
+ delegate.execute(command);
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.jboss.dna.spi.graph.commands.executor.CommandExecutor#execute(org.jboss.dna.spi.graph.commands.SetPropertiesCommand)
+ */
+ public void execute( SetPropertiesCommand command ) throws RepositorySourceException, InterruptedException {
+ delegate.execute(command);
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.jboss.dna.spi.graph.commands.executor.CommandExecutor#execute(org.jboss.dna.spi.graph.commands.CopyNodeCommand)
+ */
+ public void execute( CopyNodeCommand command ) throws RepositorySourceException, InterruptedException {
+ delegate.execute(command);
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.jboss.dna.spi.graph.commands.executor.CommandExecutor#execute(org.jboss.dna.spi.graph.commands.CopyBranchCommand)
+ */
+ public void execute( CopyBranchCommand command ) throws RepositorySourceException, InterruptedException {
+ delegate.execute(command);
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.jboss.dna.spi.graph.commands.executor.CommandExecutor#execute(org.jboss.dna.spi.graph.commands.RecordBranchCommand)
+ */
+ public void execute( RecordBranchCommand command ) throws RepositorySourceException, InterruptedException {
+ delegate.execute(command);
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.jboss.dna.spi.graph.commands.executor.CommandExecutor#execute(org.jboss.dna.spi.graph.commands.DeleteBranchCommand)
+ */
+ public void execute( DeleteBranchCommand command ) throws RepositorySourceException, InterruptedException {
+ delegate.execute(command);
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.jboss.dna.spi.graph.commands.executor.CommandExecutor#execute(org.jboss.dna.spi.graph.commands.MoveBranchCommand)
+ */
+ public void execute( MoveBranchCommand command ) throws RepositorySourceException, InterruptedException {
+ delegate.execute(command);
+ }
+
+}
Added: trunk/dna-spi/src/main/java/org/jboss/dna/spi/graph/commands/executor/LoggingCommandExecutor.java
===================================================================
--- trunk/dna-spi/src/main/java/org/jboss/dna/spi/graph/commands/executor/LoggingCommandExecutor.java (rev 0)
+++ trunk/dna-spi/src/main/java/org/jboss/dna/spi/graph/commands/executor/LoggingCommandExecutor.java 2008-07-24 19:52:13 UTC (rev 369)
@@ -0,0 +1,233 @@
+/*
+ * 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.executor;
+
+import org.jboss.dna.common.util.Logger;
+import org.jboss.dna.spi.SpiI18n;
+import org.jboss.dna.spi.graph.commands.CompositeCommand;
+import org.jboss.dna.spi.graph.commands.CopyBranchCommand;
+import org.jboss.dna.spi.graph.commands.CopyNodeCommand;
+import org.jboss.dna.spi.graph.commands.CreateNodeCommand;
+import org.jboss.dna.spi.graph.commands.DeleteBranchCommand;
+import org.jboss.dna.spi.graph.commands.GetChildrenCommand;
+import org.jboss.dna.spi.graph.commands.GetNodeCommand;
+import org.jboss.dna.spi.graph.commands.GetPropertiesCommand;
+import org.jboss.dna.spi.graph.commands.GraphCommand;
+import org.jboss.dna.spi.graph.commands.MoveBranchCommand;
+import org.jboss.dna.spi.graph.commands.RecordBranchCommand;
+import org.jboss.dna.spi.graph.commands.SetPropertiesCommand;
+import org.jboss.dna.spi.graph.connection.RepositorySourceException;
+
+/**
+ * @author Randall Hauch
+ */
+public class LoggingCommandExecutor extends DelegatingCommandExecutor {
+
+ private final Logger logger;
+ private final Logger.Level level;
+
+ /**
+ * Create a command executor that logs before and after each method call, logging messages at the {@link Logger.Level#TRACE
+ * trace} level.
+ *
+ * @param delegate the delegate executor
+ * @param logger the logger
+ */
+ public LoggingCommandExecutor( CommandExecutor delegate,
+ Logger logger ) {
+ this(delegate, logger, Logger.Level.TRACE);
+ }
+
+ /**
+ * Create a command executor that logs before and after each method call, logging messages at the supplied
+ * {@link Logger.Level level}.
+ *
+ * @param delegate the delegate executor
+ * @param logger the logger
+ * @param level the logging level, or null if {@link Logger.Level#TRACE trace-level} logging should be used.
+ */
+ public LoggingCommandExecutor( CommandExecutor delegate,
+ Logger logger,
+ Logger.Level level ) {
+ super(delegate);
+ assert logger != null;
+ this.logger = logger;
+ this.level = level != null ? level : Logger.Level.TRACE;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.jboss.dna.spi.graph.commands.executor.DelegatingCommandExecutor#close()
+ */
+ @Override
+ public void close() throws InterruptedException {
+ this.logger.log(level, SpiI18n.closingCommandExecutor);
+ super.close();
+ this.logger.log(level, SpiI18n.closedCommandExecutor);
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.jboss.dna.spi.graph.commands.executor.DelegatingCommandExecutor#execute(org.jboss.dna.spi.graph.commands.CompositeCommand)
+ */
+ @Override
+ public void execute( CompositeCommand command ) throws RepositorySourceException, InterruptedException {
+ this.logger.log(level, SpiI18n.executingGraphCommand, command);
+ super.execute(command);
+ this.logger.log(level, SpiI18n.executedGraphCommand, command);
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.jboss.dna.spi.graph.commands.executor.DelegatingCommandExecutor#execute(org.jboss.dna.spi.graph.commands.CopyBranchCommand)
+ */
+ @Override
+ public void execute( CopyBranchCommand command ) throws RepositorySourceException, InterruptedException {
+ this.logger.log(level, SpiI18n.executingGraphCommand, command);
+ super.execute(command);
+ this.logger.log(level, SpiI18n.executedGraphCommand, command);
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.jboss.dna.spi.graph.commands.executor.DelegatingCommandExecutor#execute(org.jboss.dna.spi.graph.commands.CopyNodeCommand)
+ */
+ @Override
+ public void execute( CopyNodeCommand command ) throws RepositorySourceException, InterruptedException {
+ this.logger.log(level, SpiI18n.executingGraphCommand, command);
+ super.execute(command);
+ this.logger.log(level, SpiI18n.executedGraphCommand, command);
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.jboss.dna.spi.graph.commands.executor.DelegatingCommandExecutor#execute(org.jboss.dna.spi.graph.commands.CreateNodeCommand)
+ */
+ @Override
+ public void execute( CreateNodeCommand command ) throws RepositorySourceException, InterruptedException {
+ this.logger.log(level, SpiI18n.executingGraphCommand, command);
+ super.execute(command);
+ this.logger.log(level, SpiI18n.executedGraphCommand, command);
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.jboss.dna.spi.graph.commands.executor.DelegatingCommandExecutor#execute(org.jboss.dna.spi.graph.commands.DeleteBranchCommand)
+ */
+ @Override
+ public void execute( DeleteBranchCommand command ) throws RepositorySourceException, InterruptedException {
+ this.logger.log(level, SpiI18n.executingGraphCommand, command);
+ super.execute(command);
+ this.logger.log(level, SpiI18n.executedGraphCommand, command);
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.jboss.dna.spi.graph.commands.executor.DelegatingCommandExecutor#execute(org.jboss.dna.spi.graph.commands.GetChildrenCommand)
+ */
+ @Override
+ public void execute( GetChildrenCommand command ) throws RepositorySourceException, InterruptedException {
+ this.logger.log(level, SpiI18n.executingGraphCommand, command);
+ super.execute(command);
+ this.logger.log(level, SpiI18n.executedGraphCommand, command);
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.jboss.dna.spi.graph.commands.executor.DelegatingCommandExecutor#execute(org.jboss.dna.spi.graph.commands.GetNodeCommand)
+ */
+ @Override
+ public void execute( GetNodeCommand command ) throws RepositorySourceException, InterruptedException {
+ this.logger.log(level, SpiI18n.executingGraphCommand, command);
+ super.execute(command);
+ this.logger.log(level, SpiI18n.executedGraphCommand, command);
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.jboss.dna.spi.graph.commands.executor.DelegatingCommandExecutor#execute(org.jboss.dna.spi.graph.commands.GetPropertiesCommand)
+ */
+ @Override
+ public void execute( GetPropertiesCommand command ) throws RepositorySourceException, InterruptedException {
+ this.logger.log(level, SpiI18n.executingGraphCommand, command);
+ super.execute(command);
+ this.logger.log(level, SpiI18n.executedGraphCommand, command);
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.jboss.dna.spi.graph.commands.executor.DelegatingCommandExecutor#execute(org.jboss.dna.spi.graph.commands.GraphCommand)
+ */
+ @Override
+ public void execute( GraphCommand command ) throws RepositorySourceException, InterruptedException {
+ this.logger.log(level, SpiI18n.executingGraphCommand, command);
+ super.execute(command);
+ this.logger.log(level, SpiI18n.executedGraphCommand, command);
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.jboss.dna.spi.graph.commands.executor.DelegatingCommandExecutor#execute(org.jboss.dna.spi.graph.commands.MoveBranchCommand)
+ */
+ @Override
+ public void execute( MoveBranchCommand command ) throws RepositorySourceException, InterruptedException {
+ this.logger.log(level, SpiI18n.executingGraphCommand, command);
+ super.execute(command);
+ this.logger.log(level, SpiI18n.executedGraphCommand, command);
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.jboss.dna.spi.graph.commands.executor.DelegatingCommandExecutor#execute(org.jboss.dna.spi.graph.commands.RecordBranchCommand)
+ */
+ @Override
+ public void execute( RecordBranchCommand command ) throws RepositorySourceException, InterruptedException {
+ this.logger.log(level, SpiI18n.executingGraphCommand, command);
+ super.execute(command);
+ this.logger.log(level, SpiI18n.executedGraphCommand, command);
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.jboss.dna.spi.graph.commands.executor.DelegatingCommandExecutor#execute(org.jboss.dna.spi.graph.commands.SetPropertiesCommand)
+ */
+ @Override
+ public void execute( SetPropertiesCommand command ) throws RepositorySourceException, InterruptedException {
+ this.logger.log(level, SpiI18n.executingGraphCommand, command);
+ super.execute(command);
+ this.logger.log(level, SpiI18n.executedGraphCommand, command);
+ }
+
+}
Added: trunk/dna-spi/src/main/java/org/jboss/dna/spi/graph/commands/executor/NoOpCommandExecutor.java
===================================================================
--- trunk/dna-spi/src/main/java/org/jboss/dna/spi/graph/commands/executor/NoOpCommandExecutor.java (rev 0)
+++ trunk/dna-spi/src/main/java/org/jboss/dna/spi/graph/commands/executor/NoOpCommandExecutor.java 2008-07-24 19:52:13 UTC (rev 369)
@@ -0,0 +1,189 @@
+/*
+ * 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.executor;
+
+import org.jboss.dna.spi.graph.DateTime;
+import org.jboss.dna.spi.graph.commands.CompositeCommand;
+import org.jboss.dna.spi.graph.commands.CopyBranchCommand;
+import org.jboss.dna.spi.graph.commands.CopyNodeCommand;
+import org.jboss.dna.spi.graph.commands.CreateNodeCommand;
+import org.jboss.dna.spi.graph.commands.DeleteBranchCommand;
+import org.jboss.dna.spi.graph.commands.GetChildrenCommand;
+import org.jboss.dna.spi.graph.commands.GetNodeCommand;
+import org.jboss.dna.spi.graph.commands.GetPropertiesCommand;
+import org.jboss.dna.spi.graph.commands.GraphCommand;
+import org.jboss.dna.spi.graph.commands.MoveBranchCommand;
+import org.jboss.dna.spi.graph.commands.RecordBranchCommand;
+import org.jboss.dna.spi.graph.commands.SetPropertiesCommand;
+import org.jboss.dna.spi.graph.connection.ExecutionEnvironment;
+import org.jboss.dna.spi.graph.connection.RepositorySource;
+import org.jboss.dna.spi.graph.connection.RepositorySourceException;
+
+/**
+ * @author Randall Hauch
+ */
+public class NoOpCommandExecutor extends AbstractCommandExecutor {
+
+ /**
+ * Create a command executor that does nothing.
+ *
+ * @param env the execution environment in which the executor will be run; may not be null
+ * @param sourceName the name of the {@link RepositorySource} that is making use of this executor; may not be null or empty
+ */
+ public NoOpCommandExecutor( ExecutionEnvironment env,
+ String sourceName ) {
+ super(env, sourceName);
+ }
+
+ /**
+ * Create a command executor that does nothing.
+ *
+ * @param env the execution environment in which the executor will be run; may not be null
+ * @param sourceName the name of the {@link RepositorySource} that is making use of this executor; may not be null or empty
+ * @param now the current time; may be null if the system time is to be used
+ */
+ public NoOpCommandExecutor( ExecutionEnvironment env,
+ String sourceName,
+ DateTime now ) {
+ super(env, sourceName, now);
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.jboss.dna.spi.graph.commands.executor.AbstractCommandExecutor#execute(org.jboss.dna.spi.graph.commands.GraphCommand)
+ */
+ @Override
+ public void execute( GraphCommand command ) throws RepositorySourceException {
+ // do nothing
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.jboss.dna.spi.graph.commands.executor.AbstractCommandExecutor#execute(org.jboss.dna.spi.graph.commands.CompositeCommand)
+ */
+ @Override
+ public void execute( CompositeCommand command ) throws RepositorySourceException {
+ // do nothing
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.jboss.dna.spi.graph.commands.executor.AbstractCommandExecutor#execute(org.jboss.dna.spi.graph.commands.GetNodeCommand)
+ */
+ @Override
+ public void execute( GetNodeCommand command ) throws RepositorySourceException {
+ // do nothing
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.jboss.dna.spi.graph.commands.executor.AbstractCommandExecutor#execute(org.jboss.dna.spi.graph.commands.CopyBranchCommand)
+ */
+ @Override
+ public void execute( CopyBranchCommand command ) throws RepositorySourceException {
+ // do nothing
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.jboss.dna.spi.graph.commands.executor.AbstractCommandExecutor#execute(org.jboss.dna.spi.graph.commands.CopyNodeCommand)
+ */
+ @Override
+ public void execute( CopyNodeCommand command ) throws RepositorySourceException {
+ // do nothing
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.jboss.dna.spi.graph.commands.executor.AbstractCommandExecutor#execute(org.jboss.dna.spi.graph.commands.CreateNodeCommand)
+ */
+ @Override
+ public void execute( CreateNodeCommand command ) throws RepositorySourceException {
+ // do nothing
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.jboss.dna.spi.graph.commands.executor.AbstractCommandExecutor#execute(org.jboss.dna.spi.graph.commands.DeleteBranchCommand)
+ */
+ @Override
+ public void execute( DeleteBranchCommand command ) throws RepositorySourceException {
+ // do nothing
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.jboss.dna.spi.graph.commands.executor.AbstractCommandExecutor#execute(org.jboss.dna.spi.graph.commands.GetChildrenCommand)
+ */
+ @Override
+ public void execute( GetChildrenCommand command ) throws RepositorySourceException {
+ // do nothing
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.jboss.dna.spi.graph.commands.executor.AbstractCommandExecutor#execute(org.jboss.dna.spi.graph.commands.GetPropertiesCommand)
+ */
+ @Override
+ public void execute( GetPropertiesCommand command ) throws RepositorySourceException {
+ // do nothing
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.jboss.dna.spi.graph.commands.executor.AbstractCommandExecutor#execute(org.jboss.dna.spi.graph.commands.MoveBranchCommand)
+ */
+ @Override
+ public void execute( MoveBranchCommand command ) throws RepositorySourceException {
+ // do nothing
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.jboss.dna.spi.graph.commands.executor.AbstractCommandExecutor#execute(org.jboss.dna.spi.graph.commands.RecordBranchCommand)
+ */
+ @Override
+ public void execute( RecordBranchCommand command ) throws RepositorySourceException {
+ // do nothing
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.jboss.dna.spi.graph.commands.executor.AbstractCommandExecutor#execute(org.jboss.dna.spi.graph.commands.SetPropertiesCommand)
+ */
+ @Override
+ public void execute( SetPropertiesCommand command ) throws RepositorySourceException {
+ // do nothing
+ }
+}
Modified: 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 2008-07-23 17:17:39 UTC (rev 368)
+++ trunk/dna-spi/src/main/java/org/jboss/dna/spi/graph/commands/impl/BasicCompositeCommand.java 2008-07-24 19:52:13 UTC (rev 369)
@@ -68,4 +68,14 @@
return this;
}
+ /**
+ * {@inheritDoc}
+ *
+ * @see java.lang.Object#toString()
+ */
+ @Override
+ public String toString() {
+ return this.getClass().getSimpleName() + " (containing " + commands.size() + " commands)";
+ }
+
}
Modified: trunk/dna-spi/src/main/java/org/jboss/dna/spi/graph/commands/impl/BasicCopyNodeCommand.java
===================================================================
--- trunk/dna-spi/src/main/java/org/jboss/dna/spi/graph/commands/impl/BasicCopyNodeCommand.java 2008-07-23 17:17:39 UTC (rev 368)
+++ trunk/dna-spi/src/main/java/org/jboss/dna/spi/graph/commands/impl/BasicCopyNodeCommand.java 2008-07-24 19:52:13 UTC (rev 369)
@@ -38,7 +38,8 @@
* @param oldPath the path to the original; may not be null
* @param newPath the path to the copy; may not be null
*/
- public BasicCopyNodeCommand( Path oldPath, Path newPath ) {
+ public BasicCopyNodeCommand( Path oldPath,
+ Path newPath ) {
super();
assert oldPath != null;
assert newPath != null;
@@ -60,4 +61,14 @@
return newPath;
}
+ /**
+ * {@inheritDoc}
+ *
+ * @see java.lang.Object#toString()
+ */
+ @Override
+ public String toString() {
+ return this.getClass().getSimpleName() + " from " + this.getPath() + " to " + this.getNewPath();
+ }
+
}
Modified: trunk/dna-spi/src/main/java/org/jboss/dna/spi/graph/commands/impl/BasicCreateNodeCommand.java
===================================================================
--- trunk/dna-spi/src/main/java/org/jboss/dna/spi/graph/commands/impl/BasicCreateNodeCommand.java 2008-07-23 17:17:39 UTC (rev 368)
+++ trunk/dna-spi/src/main/java/org/jboss/dna/spi/graph/commands/impl/BasicCreateNodeCommand.java 2008-07-24 19:52:13 UTC (rev 369)
@@ -23,6 +23,7 @@
import java.util.List;
import net.jcip.annotations.NotThreadSafe;
+import org.jboss.dna.common.util.StringUtil;
import org.jboss.dna.spi.graph.Path;
import org.jboss.dna.spi.graph.Property;
import org.jboss.dna.spi.graph.commands.CreateNodeCommand;
@@ -84,7 +85,7 @@
*/
public int compareTo( CreateNodeCommand that ) {
if (this == that) return 0;
- return this.path.compareTo(that.getPath());
+ return this.getPath().compareTo(that.getPath());
}
/**
@@ -107,4 +108,38 @@
}
return false;
}
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see java.lang.Object#toString()
+ */
+ @Override
+ public String toString() {
+ StringBuilder sb = new StringBuilder();
+ sb.append(this.getClass().getSimpleName());
+ sb.append(" at ");
+ sb.append(this.getPath());
+ boolean firstProperty = true;
+ for (Property property : this.getProperties()) {
+ if (property.isEmpty()) continue;
+ if (firstProperty) {
+ sb.append(" { ");
+ firstProperty = false;
+ } else {
+ sb.append("; ");
+ }
+ sb.append(property.getName());
+ sb.append("=");
+ if (property.isSingle()) {
+ sb.append(StringUtil.readableString(property.getValues().next()));
+ } else {
+ sb.append(StringUtil.readableString(property.getValuesAsArray()));
+ }
+ }
+ if (!firstProperty) {
+ sb.append(" }");
+ }
+ return sb.toString();
+ }
}
Modified: trunk/dna-spi/src/main/java/org/jboss/dna/spi/graph/commands/impl/BasicDeleteBranchCommand.java
===================================================================
--- trunk/dna-spi/src/main/java/org/jboss/dna/spi/graph/commands/impl/BasicDeleteBranchCommand.java 2008-07-23 17:17:39 UTC (rev 368)
+++ trunk/dna-spi/src/main/java/org/jboss/dna/spi/graph/commands/impl/BasicDeleteBranchCommand.java 2008-07-24 19:52:13 UTC (rev 369)
@@ -49,4 +49,13 @@
return path;
}
+ /**
+ * {@inheritDoc}
+ *
+ * @see java.lang.Object#toString()
+ */
+ @Override
+ public String toString() {
+ return this.getClass().getSimpleName() + " at " + this.getPath();
+ }
}
Modified: trunk/dna-spi/src/main/java/org/jboss/dna/spi/graph/commands/impl/BasicGetChildrenCommand.java
===================================================================
--- trunk/dna-spi/src/main/java/org/jboss/dna/spi/graph/commands/impl/BasicGetChildrenCommand.java 2008-07-23 17:17:39 UTC (rev 368)
+++ trunk/dna-spi/src/main/java/org/jboss/dna/spi/graph/commands/impl/BasicGetChildrenCommand.java 2008-07-24 19:52:13 UTC (rev 369)
@@ -25,6 +25,7 @@
import java.util.Iterator;
import java.util.List;
import net.jcip.annotations.NotThreadSafe;
+import org.jboss.dna.common.util.StringUtil;
import org.jboss.dna.spi.cache.CachePolicy;
import org.jboss.dna.spi.graph.Name;
import org.jboss.dna.spi.graph.Path;
@@ -131,4 +132,22 @@
this.cachePolicy = cachePolicy;
}
+ /**
+ * {@inheritDoc}
+ *
+ * @see java.lang.Object#toString()
+ */
+ @Override
+ public String toString() {
+ StringBuilder sb = new StringBuilder();
+ sb.append(this.getClass().getSimpleName());
+ sb.append(" at ");
+ sb.append(this.getPath());
+ List<Path.Segment> children = this.getChildren();
+ if (children != null && children.size() > 0) {
+ sb.append(" with ").append(children.size()).append(" children: ");
+ sb.append(StringUtil.readableString(children));
+ }
+ return sb.toString();
+ }
}
Modified: trunk/dna-spi/src/main/java/org/jboss/dna/spi/graph/commands/impl/BasicGetNodeCommand.java
===================================================================
--- trunk/dna-spi/src/main/java/org/jboss/dna/spi/graph/commands/impl/BasicGetNodeCommand.java 2008-07-23 17:17:39 UTC (rev 368)
+++ trunk/dna-spi/src/main/java/org/jboss/dna/spi/graph/commands/impl/BasicGetNodeCommand.java 2008-07-24 19:52:13 UTC (rev 369)
@@ -26,8 +26,10 @@
import java.util.Iterator;
import java.util.List;
import net.jcip.annotations.NotThreadSafe;
+import org.jboss.dna.common.util.StringUtil;
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.Path.Segment;
import org.jboss.dna.spi.graph.commands.GetNodeCommand;
import org.jboss.dna.spi.graph.impl.BasicPathSegment;
@@ -52,6 +54,13 @@
}
/**
+ * @return children
+ */
+ public List<Segment> getChildren() {
+ return children;
+ }
+
+ /**
* {@inheritDoc}
*/
public void setChild( Name nameOfChild ) {
@@ -111,4 +120,43 @@
children = Collections.emptyList();
}
+ /**
+ * {@inheritDoc}
+ *
+ * @see java.lang.Object#toString()
+ */
+ @Override
+ public String toString() {
+ StringBuilder sb = new StringBuilder();
+ sb.append(this.getClass().getSimpleName());
+ sb.append(" at ");
+ sb.append(this.getPath());
+ boolean firstProperty = true;
+ for (Property property : this.getPropertyIterator()) {
+ if (property.isEmpty()) continue;
+ if (firstProperty) {
+ sb.append(" { ");
+ firstProperty = false;
+ } else {
+ sb.append("; ");
+ }
+ sb.append(property.getName());
+ sb.append("=");
+ if (property.isSingle()) {
+ sb.append(StringUtil.readableString(property.getValues().next()));
+ } else {
+ sb.append(StringUtil.readableString(property.getValuesAsArray()));
+ }
+ }
+ if (!firstProperty) {
+ sb.append(" }");
+ }
+ List<Path.Segment> children = this.getChildren();
+ if (children != null && children.size() > 0) {
+ sb.append(" with ").append(children.size()).append(" children: ");
+ sb.append(StringUtil.readableString(children));
+ }
+ return sb.toString();
+ }
+
}
Modified: trunk/dna-spi/src/main/java/org/jboss/dna/spi/graph/commands/impl/BasicGetPropertiesCommand.java
===================================================================
--- trunk/dna-spi/src/main/java/org/jboss/dna/spi/graph/commands/impl/BasicGetPropertiesCommand.java 2008-07-23 17:17:39 UTC (rev 368)
+++ trunk/dna-spi/src/main/java/org/jboss/dna/spi/graph/commands/impl/BasicGetPropertiesCommand.java 2008-07-24 19:52:13 UTC (rev 369)
@@ -24,6 +24,7 @@
import java.util.HashMap;
import java.util.Map;
import net.jcip.annotations.NotThreadSafe;
+import org.jboss.dna.common.util.StringUtil;
import org.jboss.dna.spi.cache.CachePolicy;
import org.jboss.dna.spi.graph.Name;
import org.jboss.dna.spi.graph.Path;
@@ -110,4 +111,37 @@
this.cachePolicy = cachePolicy;
}
+ /**
+ * {@inheritDoc}
+ *
+ * @see java.lang.Object#toString()
+ */
+ @Override
+ public String toString() {
+ StringBuilder sb = new StringBuilder();
+ sb.append(this.getClass().getSimpleName());
+ sb.append(" at ");
+ sb.append(this.getPath());
+ boolean firstProperty = true;
+ for (Property property : this.getPropertyIterator()) {
+ if (property.isEmpty()) continue;
+ if (firstProperty) {
+ sb.append(" { ");
+ firstProperty = false;
+ } else {
+ sb.append("; ");
+ }
+ sb.append(property.getName());
+ sb.append("=");
+ if (property.isSingle()) {
+ sb.append(StringUtil.readableString(property.getValues().next()));
+ } else {
+ sb.append(StringUtil.readableString(property.getValuesAsArray()));
+ }
+ }
+ if (!firstProperty) {
+ sb.append(" }");
+ }
+ return sb.toString();
+ }
}
Modified: trunk/dna-spi/src/main/java/org/jboss/dna/spi/graph/commands/impl/BasicMoveBranchCommand.java
===================================================================
--- trunk/dna-spi/src/main/java/org/jboss/dna/spi/graph/commands/impl/BasicMoveBranchCommand.java 2008-07-23 17:17:39 UTC (rev 368)
+++ trunk/dna-spi/src/main/java/org/jboss/dna/spi/graph/commands/impl/BasicMoveBranchCommand.java 2008-07-24 19:52:13 UTC (rev 369)
@@ -74,4 +74,14 @@
return conflictBehavior;
}
+ /**
+ * {@inheritDoc}
+ *
+ * @see java.lang.Object#toString()
+ */
+ @Override
+ public String toString() {
+ return this.getClass().getSimpleName() + " from " + this.getPath() + " to " + this.getNewPath();
+ }
+
}
Modified: trunk/dna-spi/src/main/java/org/jboss/dna/spi/graph/commands/impl/BasicRecordBranchCommand.java
===================================================================
--- trunk/dna-spi/src/main/java/org/jboss/dna/spi/graph/commands/impl/BasicRecordBranchCommand.java 2008-07-23 17:17:39 UTC (rev 368)
+++ trunk/dna-spi/src/main/java/org/jboss/dna/spi/graph/commands/impl/BasicRecordBranchCommand.java 2008-07-24 19:52:13 UTC (rev 369)
@@ -167,8 +167,8 @@
* Method that is called whenver a node is recorded by the recipient of this command. This implementation simply records it,
* but subclasses can override this method to respond immediately.
*
- * @param command the command containing the node information; never null and always above the
- * {@link #getMaxDepth() maximum depth}.
+ * @param command the command containing the node information; never null and always above the {@link #getMaxDepth() maximum
+ * depth}.
*/
protected void record( CreateNodeCommand command ) {
commands.add(command);
@@ -182,4 +182,15 @@
public List<CreateNodeCommand> getCreateNodeCommands() {
return this.commands;
}
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see java.lang.Object#toString()
+ */
+ @Override
+ public String toString() {
+ return this.getClass().getSimpleName() + " at " + this.getPath();
+ }
+
}
Modified: trunk/dna-spi/src/main/java/org/jboss/dna/spi/graph/commands/impl/BasicSetPropertiesCommand.java
===================================================================
--- trunk/dna-spi/src/main/java/org/jboss/dna/spi/graph/commands/impl/BasicSetPropertiesCommand.java 2008-07-23 17:17:39 UTC (rev 368)
+++ trunk/dna-spi/src/main/java/org/jboss/dna/spi/graph/commands/impl/BasicSetPropertiesCommand.java 2008-07-24 19:52:13 UTC (rev 369)
@@ -23,6 +23,7 @@
import java.util.List;
import net.jcip.annotations.NotThreadSafe;
+import org.jboss.dna.common.util.StringUtil;
import org.jboss.dna.spi.graph.Path;
import org.jboss.dna.spi.graph.Property;
import org.jboss.dna.spi.graph.commands.SetPropertiesCommand;
@@ -65,4 +66,38 @@
public Iterable<Property> getProperties() {
return properties;
}
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see java.lang.Object#toString()
+ */
+ @Override
+ public String toString() {
+ StringBuilder sb = new StringBuilder();
+ sb.append(this.getClass().getSimpleName());
+ sb.append(" at ");
+ sb.append(this.getPath());
+ boolean firstProperty = true;
+ for (Property property : this.getProperties()) {
+ if (property.isEmpty()) continue;
+ if (firstProperty) {
+ sb.append(" { ");
+ firstProperty = false;
+ } else {
+ sb.append("; ");
+ }
+ sb.append(property.getName());
+ sb.append("=");
+ if (property.isSingle()) {
+ sb.append(StringUtil.readableString(property.getValues().next()));
+ } else {
+ sb.append(StringUtil.readableString(property.getValuesAsArray()));
+ }
+ }
+ if (!firstProperty) {
+ sb.append(" }");
+ }
+ return sb.toString();
+ }
}
Modified: trunk/dna-spi/src/main/java/org/jboss/dna/spi/graph/impl/BasicPath.java
===================================================================
--- trunk/dna-spi/src/main/java/org/jboss/dna/spi/graph/impl/BasicPath.java 2008-07-23 17:17:39 UTC (rev 368)
+++ trunk/dna-spi/src/main/java/org/jboss/dna/spi/graph/impl/BasicPath.java 2008-07-24 19:52:13 UTC (rev 369)
@@ -307,7 +307,41 @@
/**
* {@inheritDoc}
+ *
+ * @see org.jboss.dna.spi.graph.Path#isAtOrBelow(org.jboss.dna.spi.graph.Path)
*/
+ public boolean isAtOrBelow( Path other ) {
+ if (other == null) return false;
+ if (this == other) return true;
+ Iterator<Segment> thisIter = this.segments.iterator();
+ Iterator<Segment> thatIter = other.iterator();
+ while (thisIter.hasNext() && thatIter.hasNext()) {
+ if (!thisIter.next().equals(thatIter.next())) return false;
+ }
+ if (thatIter.hasNext()) return false; // The other still has segments, but this doesn't
+ return true;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.jboss.dna.spi.graph.Path#isAtOrAbove(org.jboss.dna.spi.graph.Path)
+ */
+ public boolean isAtOrAbove( Path other ) {
+ if (other == null) return false;
+ if (this == other) return true;
+ Iterator<Segment> thisIter = this.segments.iterator();
+ Iterator<Segment> thatIter = other.iterator();
+ while (thisIter.hasNext() && thatIter.hasNext()) {
+ if (!thisIter.next().equals(thatIter.next())) return false;
+ }
+ if (thisIter.hasNext()) return false; // This still has segments, but other doesn't
+ return true;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
public boolean isDecendantOf( Path ancestor ) {
if (ancestor == null) return false;
return ancestor.isAncestorOf(this);
@@ -330,8 +364,8 @@
/**
* {@inheritDoc}
*/
- public boolean isSame( Path other ) {
- return this.compareTo(other) == 0;
+ public boolean isSameAs( Path other ) {
+ return other != null && this.compareTo(other) == 0;
}
/**
Modified: trunk/dna-spi/src/main/java/org/jboss/dna/spi/graph/impl/PathValueFactory.java
===================================================================
--- trunk/dna-spi/src/main/java/org/jboss/dna/spi/graph/impl/PathValueFactory.java 2008-07-23 17:17:39 UTC (rev 368)
+++ trunk/dna-spi/src/main/java/org/jboss/dna/spi/graph/impl/PathValueFactory.java 2008-07-24 19:52:13 UTC (rev 369)
@@ -395,7 +395,19 @@
/**
* {@inheritDoc}
+ *
+ * @see org.jboss.dna.spi.graph.PathFactory#create(org.jboss.dna.spi.graph.Path, java.lang.String)
*/
+ public Path create( Path parentPath,
+ String subpath ) {
+ // Create a relative path for the subpath ...
+ Path relativeSubpath = create(subpath);
+ return create(parentPath, relativeSubpath);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
public Segment createSegment( Name segmentName ) {
ArgCheck.isNotNull(segmentName, "segment name");
if (Path.SELF_NAME.equals(segmentName)) return Path.SELF_SEGMENT;
Modified: trunk/dna-spi/src/main/resources/org/jboss/dna/spi/SpiI18n.properties
===================================================================
--- trunk/dna-spi/src/main/resources/org/jboss/dna/spi/SpiI18n.properties 2008-07-23 17:17:39 UTC (rev 368)
+++ trunk/dna-spi/src/main/resources/org/jboss/dna/spi/SpiI18n.properties 2008-07-24 19:52:13 UTC (rev 369)
@@ -45,3 +45,8 @@
pathExpressionIsInvalid = The path expression {0} is not valid
pathExpressionHasInvalidSelect = Invalid select expression "{0}" in the path expression "{1}"
pathExpressionHasInvalidMatch = Invalid match expression "{0}" in the path expression "{1}"
+
+executingGraphCommand = Executing {0}
+executedGraphCommand = Executed {0}
+closingCommandExecutor = Closing command executor
+closedCommandExecutor = Closed command executor
Modified: trunk/dna-spi/src/test/java/org/jboss/dna/spi/graph/commands/executor/AbstractCommandExecutorTest.java
===================================================================
--- trunk/dna-spi/src/test/java/org/jboss/dna/spi/graph/commands/executor/AbstractCommandExecutorTest.java 2008-07-23 17:17:39 UTC (rev 368)
+++ trunk/dna-spi/src/test/java/org/jboss/dna/spi/graph/commands/executor/AbstractCommandExecutorTest.java 2008-07-24 19:52:13 UTC (rev 369)
@@ -44,6 +44,7 @@
import org.jboss.dna.spi.graph.commands.MoveBranchCommand;
import org.jboss.dna.spi.graph.commands.RecordBranchCommand;
import org.jboss.dna.spi.graph.commands.SetPropertiesCommand;
+import org.jboss.dna.spi.graph.connection.BasicExecutionEnvironment;
import org.jboss.dna.spi.graph.connection.ExecutionEnvironment;
import org.jboss.dna.spi.graph.connection.RepositorySourceException;
import org.junit.Before;
@@ -61,7 +62,6 @@
private AbstractCommandExecutor executor;
private GraphCommand command;
- @Mock
private ExecutionEnvironment env;
@Mock
protected CommandExecutor validator;
@@ -69,6 +69,7 @@
@Before
public void beforeEach() throws Exception {
MockitoAnnotations.initMocks(this);
+ env = new BasicExecutionEnvironment();
executor = new ExecutorImpl(env, "Source X", validator);
}
@@ -123,6 +124,7 @@
verify(validator, times(2)).execute((GetPropertiesCommand)getNodeCommand);
verify(validator, times(2)).execute((GetChildrenCommand)getNodeCommand);
verify(validator, times(1)).execute(createNodeCommand);
+ verify(validator, times(2)).execute(getNodeCommand);
verifyNoMoreInteractions(validator);
}
@@ -139,6 +141,7 @@
verify(validator, times(2)).execute((GetPropertiesCommand)getNodeCommand);
verify(validator, times(2)).execute((GetChildrenCommand)getNodeCommand);
verify(validator, times(1)).execute(createNodeCommand);
+ verify(validator, times(2)).execute(getNodeCommand);
verifyNoMoreInteractions(validator);
}
@@ -149,6 +152,7 @@
verify(validator, times(1)).execute((GraphCommand)getNodeCommand);
verify(validator, times(1)).execute((GetPropertiesCommand)getNodeCommand);
verify(validator, times(1)).execute((GetChildrenCommand)getNodeCommand);
+ verify(validator, times(1)).execute(getNodeCommand);
verifyNoMoreInteractions(validator);
}
@@ -265,6 +269,11 @@
}
@Override
+ public void execute( GetNodeCommand command ) throws RepositorySourceException, InterruptedException {
+ validator.execute(command);
+ }
+
+ @Override
public void execute( RecordBranchCommand command ) throws RepositorySourceException, InterruptedException {
validator.execute(command);
}
Copied: trunk/dna-spi/src/test/java/org/jboss/dna/spi/graph/connection/SimpleRepository.java (from rev 337, trunk/dna-repository/src/test/java/org/jboss/dna/repository/federation/SimpleRepository.java)
===================================================================
--- trunk/dna-spi/src/test/java/org/jboss/dna/spi/graph/connection/SimpleRepository.java (rev 0)
+++ trunk/dna-spi/src/test/java/org/jboss/dna/spi/graph/connection/SimpleRepository.java 2008-07-24 19:52:13 UTC (rev 369)
@@ -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.spi.graph.connection;
+
+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
+ */
+@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-spi/src/test/java/org/jboss/dna/spi/graph/connection/SimpleRepository.java
___________________________________________________________________
Name: svn:mime-type
+ text/plain
Copied: trunk/dna-spi/src/test/java/org/jboss/dna/spi/graph/connection/SimpleRepositorySource.java (from rev 337, trunk/dna-repository/src/test/java/org/jboss/dna/repository/federation/SimpleRepositorySource.java)
===================================================================
--- trunk/dna-spi/src/test/java/org/jboss/dna/spi/graph/connection/SimpleRepositorySource.java (rev 0)
+++ trunk/dna-spi/src/test/java/org/jboss/dna/spi/graph/connection/SimpleRepositorySource.java 2008-07-24 19:52:13 UTC (rev 369)
@@ -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.spi.graph.connection;
+
+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-spi/src/test/java/org/jboss/dna/spi/graph/connection/SimpleRepositorySource.java
___________________________________________________________________
Name: svn:mime-type
+ text/plain
Modified: trunk/dna-spi/src/test/java/org/jboss/dna/spi/graph/impl/BasicPathTest.java
===================================================================
--- trunk/dna-spi/src/test/java/org/jboss/dna/spi/graph/impl/BasicPathTest.java 2008-07-23 17:17:39 UTC (rev 368)
+++ trunk/dna-spi/src/test/java/org/jboss/dna/spi/graph/impl/BasicPathTest.java 2008-07-24 19:52:13 UTC (rev 369)
@@ -409,6 +409,96 @@
}
@Test
+ public void shouldConsiderNodeToBeAtOrAboveItself() {
+ assertThat(path.isAtOrAbove(path), is(true));
+ }
+
+ @Test
+ public void shouldConsiderNodeToBeAtOrBelowItself() {
+ assertThat(path.isAtOrBelow(path), is(true));
+ }
+
+ @Test
+ public void shouldConsiderAncestorToBeAtOrAboveTheDecendant() {
+ Path path1 = pathFactory.create("/a/y/z");
+ Path path2 = pathFactory.create("/a/b/c");
+ Path path3 = pathFactory.create("/x/b/c");
+ Path path4 = pathFactory.create("/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x/y/z");
+ for (int i = 1; i < path1.size(); ++i) {
+ assertThat(path1.getAncestor(i).isAtOrAbove(path1), is(true));
+ }
+ for (int i = 1; i < path2.size(); ++i) {
+ assertThat(path2.getAncestor(i).isAtOrAbove(path2), is(true));
+ }
+ for (int i = 1; i < path3.size(); ++i) {
+ assertThat(path3.getAncestor(i).isAtOrAbove(path3), is(true));
+ }
+ for (int i = 1; i < path4.size(); ++i) {
+ assertThat(path4.getAncestor(i).isAtOrAbove(path4), is(true));
+ }
+ }
+
+ @Test
+ public void shouldConsiderDecendantToBeAtOrBelowTheAncestor() {
+ Path path1 = pathFactory.create("/a/y/z");
+ Path path2 = pathFactory.create("/a/b/c");
+ Path path3 = pathFactory.create("/x/b/c");
+ Path path4 = pathFactory.create("/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x/y/z");
+ for (int i = 1; i < path1.size(); ++i) {
+ assertThat(path1.isAtOrBelow(path1.getAncestor(i)), is(true));
+ }
+ for (int i = 1; i < path2.size(); ++i) {
+ assertThat(path2.isAtOrBelow(path2.getAncestor(i)), is(true));
+ }
+ for (int i = 1; i < path3.size(); ++i) {
+ assertThat(path3.isAtOrBelow(path3.getAncestor(i)), is(true));
+ }
+ for (int i = 1; i < path4.size(); ++i) {
+ assertThat(path4.isAtOrBelow(path4.getAncestor(i)), is(true));
+ }
+ }
+
+ @Test
+ public void shouldNotConsiderAncestorToBeAtOrBelowTheDecendant() {
+ Path path1 = pathFactory.create("/a/y/z");
+ Path path2 = pathFactory.create("/a/b/c");
+ Path path3 = pathFactory.create("/x/b/c");
+ Path path4 = pathFactory.create("/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x/y/z");
+ for (int i = 1; i < path1.size(); ++i) {
+ assertThat(path1.getAncestor(i).isAtOrBelow(path1), is(false));
+ }
+ for (int i = 1; i < path2.size(); ++i) {
+ assertThat(path2.getAncestor(i).isAtOrBelow(path2), is(false));
+ }
+ for (int i = 1; i < path3.size(); ++i) {
+ assertThat(path3.getAncestor(i).isAtOrBelow(path3), is(false));
+ }
+ for (int i = 1; i < path4.size(); ++i) {
+ assertThat(path4.getAncestor(i).isAtOrBelow(path4), is(false));
+ }
+ }
+
+ @Test
+ public void shouldNotConsiderDecendantToBeAtOrAboveTheAncestor() {
+ Path path1 = pathFactory.create("/a/y/z");
+ Path path2 = pathFactory.create("/a/b/c");
+ Path path3 = pathFactory.create("/x/b/c");
+ Path path4 = pathFactory.create("/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x/y/z");
+ for (int i = 1; i < path1.size(); ++i) {
+ assertThat(path1.isAtOrAbove(path1.getAncestor(i)), is(false));
+ }
+ for (int i = 1; i < path2.size(); ++i) {
+ assertThat(path2.isAtOrAbove(path2.getAncestor(i)), is(false));
+ }
+ for (int i = 1; i < path3.size(); ++i) {
+ assertThat(path3.isAtOrAbove(path3.getAncestor(i)), is(false));
+ }
+ for (int i = 1; i < path4.size(); ++i) {
+ assertThat(path4.isAtOrAbove(path4.getAncestor(i)), is(false));
+ }
+ }
+
+ @Test
public void shouldReturnNullForLastSegmentOfRoot() {
assertThat(ROOT.getLastSegment(), is(nullValue()));
}
Modified: trunk/pom.xml
===================================================================
--- trunk/pom.xml 2008-07-23 17:17:39 UTC (rev 368)
+++ trunk/pom.xml 2008-07-24 19:52:13 UTC (rev 369)
@@ -104,6 +104,7 @@
<module>sequencers/dna-sequencer-cnd</module>
<module>sequencers/dna-sequencer-java</module>
<module>sequencers/dna-sequencer-msoffice</module>
+ <module>connectors/dna-connector-federation</module>
<module>connectors/dna-connector-inmemory</module>
<module>connectors/dna-connector-jbosscache</module>
<module>extensions/dna-mimetype-detector-aperture</module>
@@ -341,6 +342,21 @@
<artifactId>dna-repository</artifactId>
<version>${dna-version}</version>
</dependency>
+ <dependency>
+ <groupId>org.jboss.dna</groupId>
+ <artifactId>dna-connector-federation</artifactId>
+ <version>${dna-version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.jboss.dna</groupId>
+ <artifactId>dna-connector-jbosscache</artifactId>
+ <version>${dna-version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.jboss.dna</groupId>
+ <artifactId>dna-connector-inmemory</artifactId>
+ <version>${dna-version}</version>
+ </dependency>
<dependency>
<groupId>org.jboss.dna</groupId>
<artifactId>dna-mimetype-detector-aperture</artifactId>
15 years, 9 months
DNA SVN: r368 - trunk/sequencers/dna-sequencer-java/src/main/java/org/jboss/dna/sequencer/java.
by dna-commits@lists.jboss.org
Author: spagop
Date: 2008-07-23 13:17:39 -0400 (Wed, 23 Jul 2008)
New Revision: 368
Modified:
trunk/sequencers/dna-sequencer-java/src/main/java/org/jboss/dna/sequencer/java/AbstractJavaMetadata.java
Log:
enhancement for the JavaMetadata "minimal fields and methods member of type"; "constructor of class"
Modified: trunk/sequencers/dna-sequencer-java/src/main/java/org/jboss/dna/sequencer/java/AbstractJavaMetadata.java
===================================================================
--- trunk/sequencers/dna-sequencer-java/src/main/java/org/jboss/dna/sequencer/java/AbstractJavaMetadata.java 2008-07-23 17:17:17 UTC (rev 367)
+++ trunk/sequencers/dna-sequencer-java/src/main/java/org/jboss/dna/sequencer/java/AbstractJavaMetadata.java 2008-07-23 17:17:39 UTC (rev 368)
@@ -28,23 +28,39 @@
import org.eclipse.jdt.core.dom.AnnotationTypeDeclaration;
import org.eclipse.jdt.core.dom.CompilationUnit;
import org.eclipse.jdt.core.dom.EnumDeclaration;
+import org.eclipse.jdt.core.dom.FieldDeclaration;
import org.eclipse.jdt.core.dom.ImportDeclaration;
import org.eclipse.jdt.core.dom.MarkerAnnotation;
+import org.eclipse.jdt.core.dom.MethodDeclaration;
import org.eclipse.jdt.core.dom.Modifier;
import org.eclipse.jdt.core.dom.NormalAnnotation;
import org.eclipse.jdt.core.dom.PackageDeclaration;
+import org.eclipse.jdt.core.dom.ParameterizedType;
+import org.eclipse.jdt.core.dom.PrimitiveType;
+import org.eclipse.jdt.core.dom.QualifiedType;
+import org.eclipse.jdt.core.dom.SimpleType;
import org.eclipse.jdt.core.dom.SingleMemberAnnotation;
+import org.eclipse.jdt.core.dom.Type;
import org.eclipse.jdt.core.dom.TypeDeclaration;
+import org.eclipse.jdt.core.dom.VariableDeclarationFragment;
import org.jboss.dna.sequencer.java.metadata.ClassMetadata;
+import org.jboss.dna.sequencer.java.metadata.ConstructorMetadata;
+import org.jboss.dna.sequencer.java.metadata.FieldMetadata;
import org.jboss.dna.sequencer.java.metadata.ImportMetadata;
import org.jboss.dna.sequencer.java.metadata.ImportOnDemandMetadata;
import org.jboss.dna.sequencer.java.metadata.InterfaceMetadata;
import org.jboss.dna.sequencer.java.metadata.MarkerAnnotationMetadata;
+import org.jboss.dna.sequencer.java.metadata.MethodMetadata;
+import org.jboss.dna.sequencer.java.metadata.MethodTypeMemberMetadata;
import org.jboss.dna.sequencer.java.metadata.NormalAnnotationMetadata;
import org.jboss.dna.sequencer.java.metadata.PackageMetadata;
+import org.jboss.dna.sequencer.java.metadata.ParameterizedFieldMetadata;
+import org.jboss.dna.sequencer.java.metadata.PrimitiveFieldMetadata;
+import org.jboss.dna.sequencer.java.metadata.SimpleFieldMetadata;
import org.jboss.dna.sequencer.java.metadata.SingleImportMetadata;
import org.jboss.dna.sequencer.java.metadata.SingleMemberAnnotationMetadata;
import org.jboss.dna.sequencer.java.metadata.TypeMetadata;
+import org.jboss.dna.sequencer.java.metadata.Variable;
/**
* Abstract definition of a <tt>JavaMetadata<tt>. This class exposes some useful methods, that can
@@ -140,12 +156,10 @@
List<TypeMetadata> metadata = new ArrayList<TypeMetadata>();
List<AbstractTypeDeclaration> topLevelType = unit.types();
for (AbstractTypeDeclaration abstractTypeDeclaration : topLevelType) {
-
// process TypeDeclaration (class, interface)
if (abstractTypeDeclaration instanceof TypeDeclaration) {
TypeDeclaration typeDeclaration = (TypeDeclaration)abstractTypeDeclaration;
if (typeDeclaration.isInterface()) {
-
// is an interface top level type
InterfaceMetadata interfaceMetadata = new InterfaceMetadata();
interfaceMetadata.setName(JavaMetadataUtil.getName(typeDeclaration.getName()));
@@ -166,9 +180,21 @@
MarkerAnnotation marker = (MarkerAnnotation)object;
MarkerAnnotationMetadata markerAnnotationMetadata = new MarkerAnnotationMetadata();
markerAnnotationMetadata.setName(JavaMetadataUtil.getName(marker.getTypeName()));
- classMetadata.getAnnotationMetadata().add(markerAnnotationMetadata);
+ classMetadata.getAnnotations().add(markerAnnotationMetadata);
}
}
+ // fields of the class top level type
+ FieldDeclaration[] fieldDeclarations = typeDeclaration.getFields();
+ for (FieldDeclaration fieldDeclaration : fieldDeclarations) {
+ FieldMetadata fieldMetadata = getFieldMetadataFrom(fieldDeclaration);
+ classMetadata.getFields().add(fieldMetadata);
+ }
+ // methods of the class top level type
+ MethodDeclaration[] methodDeclarations = typeDeclaration.getMethods();
+ for (MethodDeclaration methodDeclaration : methodDeclarations) {
+ MethodMetadata methodMetadata = getFieldMetadataFrom(methodDeclaration);
+ classMetadata.getMethods().add(methodMetadata);
+ }
metadata.add(classMetadata);
}
}
@@ -187,4 +213,113 @@
}
return metadata;
}
+
+ /**
+ * Gets a method meta data from {@link MethodDeclaration}.
+ *
+ * @param methodDeclaration - the MethodDeclaration.
+ * @return methodMetadata - the method meta data.
+ */
+ private MethodMetadata getFieldMetadataFrom( MethodDeclaration methodDeclaration ) {
+ if (methodDeclaration != null) {
+ if (methodDeclaration.isConstructor()) {
+ return getConstructorMetadataFrom(methodDeclaration);
+ }
+ return getMethodTypeMemberMetadataFrom(methodDeclaration);
+
+ }
+ return null;
+ }
+
+ /**
+ * Get {@link MethodTypeMemberMetadata}
+ *
+ * @param methodDeclaration
+ * @return methodTypeMemberMetadata
+ */
+ private MethodMetadata getMethodTypeMemberMetadataFrom( MethodDeclaration methodDeclaration ) {
+ MethodTypeMemberMetadata methodTypeMemberMetadata = new MethodTypeMemberMetadata();
+ methodTypeMemberMetadata.setName(JavaMetadataUtil.getName(methodDeclaration.getName()));
+ return methodTypeMemberMetadata;
+ }
+
+ /**
+ * Get {@link ConstructorMetadata}
+ *
+ * @param methodDeclaration
+ * @return constructorMetadata
+ */
+ private MethodMetadata getConstructorMetadataFrom( MethodDeclaration methodDeclaration ) {
+ ConstructorMetadata constructorMetadata = new ConstructorMetadata();
+ constructorMetadata.setName(JavaMetadataUtil.getName(methodDeclaration.getName()));
+ return constructorMetadata;
+ }
+
+ /**
+ * Gets a field meta data from {@link FieldDeclaration}.
+ *
+ * @param fieldDeclaration - the declaration.
+ * @return fieldMetadata - meta data.
+ */
+ @SuppressWarnings( "unchecked" )
+ private FieldMetadata getFieldMetadataFrom( FieldDeclaration fieldDeclaration ) {
+ if (fieldDeclaration != null && fieldDeclaration.getType() != null && (!fieldDeclaration.fragments().isEmpty())) {
+ List<VariableDeclarationFragment> fragments = null;
+ // type
+ Type type = fieldDeclaration.getType();
+ // Primitive type
+ if (type instanceof PrimitiveType) {
+ PrimitiveType primitiveType = (PrimitiveType)type;
+ PrimitiveFieldMetadata primitiveFieldMetadata = new PrimitiveFieldMetadata();
+ primitiveFieldMetadata.setCode(primitiveType.getPrimitiveTypeCode().toString());
+ // variables
+ fragments = fieldDeclaration.fragments();
+ getAllVariablesOf(fragments, primitiveFieldMetadata);
+ return primitiveFieldMetadata;
+ }
+ if (type instanceof ParameterizedType) {
+ ParameterizedType parameterizedType = (ParameterizedType)type;
+ ParameterizedFieldMetadata parameterizedFieldMetadata = new ParameterizedFieldMetadata();
+ Type typeOfParameterizedType = parameterizedType.getType(); // type may be a simple type or a qualified type.
+ if (typeOfParameterizedType instanceof SimpleType) {
+ SimpleType simpleType = (SimpleType)typeOfParameterizedType;
+ parameterizedFieldMetadata.setName(JavaMetadataUtil.getName(simpleType.getName()));
+ }
+ if (typeOfParameterizedType instanceof QualifiedType) {
+ QualifiedType qualifiedType = (QualifiedType)typeOfParameterizedType;
+ parameterizedFieldMetadata.setName(JavaMetadataUtil.getName(qualifiedType.getName()));
+ Type qualifier = qualifiedType.getQualifier();
+ if (qualifier instanceof ParameterizedType) {
+ // TODO
+ }
+ }
+ // variables
+ fragments = fieldDeclaration.fragments();
+ getAllVariablesOf(fragments, parameterizedFieldMetadata);
+ return parameterizedFieldMetadata;
+ }
+ if (type instanceof SimpleType) {
+ SimpleType simpleType = (SimpleType)type;
+ SimpleFieldMetadata simpleFieldMetadata = new SimpleFieldMetadata();
+ simpleFieldMetadata.setName(JavaMetadataUtil.getName(simpleType.getName()));
+ fragments = fieldDeclaration.fragments();
+ getAllVariablesOf(fragments, simpleFieldMetadata);
+ return simpleFieldMetadata;
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Get all variables of a fragment.
+ *
+ * @param fragments
+ * @param fieldMetadata
+ */
+ private void getAllVariablesOf( List<VariableDeclarationFragment> fragments,
+ FieldMetadata fieldMetadata ) {
+ for (VariableDeclarationFragment fragment : fragments) {
+ fieldMetadata.getVariables().add(new Variable(JavaMetadataUtil.getName(fragment.getName())));
+ }
+ }
}
15 years, 9 months
DNA SVN: r367 - trunk/sequencers/dna-sequencer-java/src/main/java/org/jboss/dna/sequencer/java/metadata.
by dna-commits@lists.jboss.org
Author: spagop
Date: 2008-07-23 13:17:17 -0400 (Wed, 23 Jul 2008)
New Revision: 367
Added:
trunk/sequencers/dna-sequencer-java/src/main/java/org/jboss/dna/sequencer/java/metadata/ConstructorMetadata.java
trunk/sequencers/dna-sequencer-java/src/main/java/org/jboss/dna/sequencer/java/metadata/MethodMetadata.java
trunk/sequencers/dna-sequencer-java/src/main/java/org/jboss/dna/sequencer/java/metadata/MethodTypeMemberMetadata.java
trunk/sequencers/dna-sequencer-java/src/main/java/org/jboss/dna/sequencer/java/metadata/ParameterizedFieldMetadata.java
trunk/sequencers/dna-sequencer-java/src/main/java/org/jboss/dna/sequencer/java/metadata/PrimitiveFieldMetadata.java
trunk/sequencers/dna-sequencer-java/src/main/java/org/jboss/dna/sequencer/java/metadata/SimpleFieldMetadata.java
trunk/sequencers/dna-sequencer-java/src/main/java/org/jboss/dna/sequencer/java/metadata/Variable.java
Modified:
trunk/sequencers/dna-sequencer-java/src/main/java/org/jboss/dna/sequencer/java/metadata/ClassMetadata.java
trunk/sequencers/dna-sequencer-java/src/main/java/org/jboss/dna/sequencer/java/metadata/FieldMetadata.java
trunk/sequencers/dna-sequencer-java/src/main/java/org/jboss/dna/sequencer/java/metadata/TypeMetadata.java
Log:
enhancement for the JavaMetadata "minimal fields and methods member of type"; "constructor of class"
Modified: trunk/sequencers/dna-sequencer-java/src/main/java/org/jboss/dna/sequencer/java/metadata/ClassMetadata.java
===================================================================
--- trunk/sequencers/dna-sequencer-java/src/main/java/org/jboss/dna/sequencer/java/metadata/ClassMetadata.java 2008-07-23 17:12:46 UTC (rev 366)
+++ trunk/sequencers/dna-sequencer-java/src/main/java/org/jboss/dna/sequencer/java/metadata/ClassMetadata.java 2008-07-23 17:17:17 UTC (rev 367)
@@ -21,9 +21,13 @@
*/
package org.jboss.dna.sequencer.java.metadata;
+import java.util.List;
+
+
/**
* @author Serge Pagop
*/
public class ClassMetadata extends TypeMetadata {
+
}
Added: trunk/sequencers/dna-sequencer-java/src/main/java/org/jboss/dna/sequencer/java/metadata/ConstructorMetadata.java
===================================================================
--- trunk/sequencers/dna-sequencer-java/src/main/java/org/jboss/dna/sequencer/java/metadata/ConstructorMetadata.java (rev 0)
+++ trunk/sequencers/dna-sequencer-java/src/main/java/org/jboss/dna/sequencer/java/metadata/ConstructorMetadata.java 2008-07-23 17:17:17 UTC (rev 367)
@@ -0,0 +1,29 @@
+/*
+ * 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.sequencer.java.metadata;
+
+/**
+ *
+ */
+public class ConstructorMetadata extends MethodMetadata {
+
+}
Modified: trunk/sequencers/dna-sequencer-java/src/main/java/org/jboss/dna/sequencer/java/metadata/FieldMetadata.java
===================================================================
--- trunk/sequencers/dna-sequencer-java/src/main/java/org/jboss/dna/sequencer/java/metadata/FieldMetadata.java 2008-07-23 17:12:46 UTC (rev 366)
+++ trunk/sequencers/dna-sequencer-java/src/main/java/org/jboss/dna/sequencer/java/metadata/FieldMetadata.java 2008-07-23 17:17:17 UTC (rev 367)
@@ -21,25 +21,28 @@
*/
package org.jboss.dna.sequencer.java.metadata;
+import java.util.ArrayList;
+import java.util.List;
+
/**
* @author Serge Pagop
*/
public class FieldMetadata {
-
+
/** The name */
- private String name;
+ private List<Variable> variables = new ArrayList<Variable>();
/**
- * @return name
+ * @return variables
*/
- public String getName() {
- return name;
+ public List<Variable> getVariables() {
+ return variables;
}
/**
- * @param name Sets name to the specified value.
+ * @param variables Sets variables to the specified value.
*/
- public void setName( String name ) {
- this.name = name;
+ public void setVariables( List<Variable> variables ) {
+ this.variables = variables;
}
}
Added: trunk/sequencers/dna-sequencer-java/src/main/java/org/jboss/dna/sequencer/java/metadata/MethodMetadata.java
===================================================================
--- trunk/sequencers/dna-sequencer-java/src/main/java/org/jboss/dna/sequencer/java/metadata/MethodMetadata.java (rev 0)
+++ trunk/sequencers/dna-sequencer-java/src/main/java/org/jboss/dna/sequencer/java/metadata/MethodMetadata.java 2008-07-23 17:17:17 UTC (rev 367)
@@ -0,0 +1,44 @@
+/*
+ * 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.sequencer.java.metadata;
+
+/**
+ *
+ */
+public class MethodMetadata {
+ private String name;
+
+ /**
+ * @return name
+ */
+ public String getName() {
+ return name;
+ }
+
+ /**
+ * @param name Sets name to the specified value.
+ */
+ public void setName( String name ) {
+ this.name = name;
+ }
+
+}
Added: trunk/sequencers/dna-sequencer-java/src/main/java/org/jboss/dna/sequencer/java/metadata/MethodTypeMemberMetadata.java
===================================================================
--- trunk/sequencers/dna-sequencer-java/src/main/java/org/jboss/dna/sequencer/java/metadata/MethodTypeMemberMetadata.java (rev 0)
+++ trunk/sequencers/dna-sequencer-java/src/main/java/org/jboss/dna/sequencer/java/metadata/MethodTypeMemberMetadata.java 2008-07-23 17:17:17 UTC (rev 367)
@@ -0,0 +1,29 @@
+/*
+ * 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.sequencer.java.metadata;
+
+/**
+ *
+ */
+public class MethodTypeMemberMetadata extends MethodMetadata {
+
+}
Added: trunk/sequencers/dna-sequencer-java/src/main/java/org/jboss/dna/sequencer/java/metadata/ParameterizedFieldMetadata.java
===================================================================
--- trunk/sequencers/dna-sequencer-java/src/main/java/org/jboss/dna/sequencer/java/metadata/ParameterizedFieldMetadata.java (rev 0)
+++ trunk/sequencers/dna-sequencer-java/src/main/java/org/jboss/dna/sequencer/java/metadata/ParameterizedFieldMetadata.java 2008-07-23 17:17:17 UTC (rev 367)
@@ -0,0 +1,47 @@
+/*
+ * 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.sequencer.java.metadata;
+
+import java.util.List;
+
+/**
+ * Field meta data for parameterized type.
+ */
+public class ParameterizedFieldMetadata extends FieldMetadata {
+
+ private String name;
+
+ /**
+ * @param name
+ */
+ public void setName( String name ) {
+ this.name = name;
+ }
+
+ /**
+ * @return name
+ */
+ public String getName() {
+ return name;
+ }
+
+}
Added: trunk/sequencers/dna-sequencer-java/src/main/java/org/jboss/dna/sequencer/java/metadata/PrimitiveFieldMetadata.java
===================================================================
--- trunk/sequencers/dna-sequencer-java/src/main/java/org/jboss/dna/sequencer/java/metadata/PrimitiveFieldMetadata.java (rev 0)
+++ trunk/sequencers/dna-sequencer-java/src/main/java/org/jboss/dna/sequencer/java/metadata/PrimitiveFieldMetadata.java 2008-07-23 17:17:17 UTC (rev 367)
@@ -0,0 +1,46 @@
+/*
+ * 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.sequencer.java.metadata;
+
+/**
+ * FieldMetadata for primitive types
+ */
+public class PrimitiveFieldMetadata extends FieldMetadata {
+
+ /** The code */
+ private String code;
+
+ /**
+ * @return code
+ */
+ public String getCode() {
+ return code;
+ }
+
+ /**
+ * @param code Sets code to the specified value.
+ */
+ public void setCode( String code ) {
+ this.code = code;
+ }
+
+}
Added: trunk/sequencers/dna-sequencer-java/src/main/java/org/jboss/dna/sequencer/java/metadata/SimpleFieldMetadata.java
===================================================================
--- trunk/sequencers/dna-sequencer-java/src/main/java/org/jboss/dna/sequencer/java/metadata/SimpleFieldMetadata.java (rev 0)
+++ trunk/sequencers/dna-sequencer-java/src/main/java/org/jboss/dna/sequencer/java/metadata/SimpleFieldMetadata.java 2008-07-23 17:17:17 UTC (rev 367)
@@ -0,0 +1,45 @@
+/*
+ * 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.sequencer.java.metadata;
+
+/**
+ * field meta data for simple type.
+ */
+public class SimpleFieldMetadata extends FieldMetadata {
+
+ private String name;
+
+ /**
+ * @param name
+ */
+ public void setName( String name ) {
+ this.name = name;
+ }
+
+ /**
+ * @return name
+ */
+ public String getName() {
+ return name;
+ }
+
+}
Modified: trunk/sequencers/dna-sequencer-java/src/main/java/org/jboss/dna/sequencer/java/metadata/TypeMetadata.java
===================================================================
--- trunk/sequencers/dna-sequencer-java/src/main/java/org/jboss/dna/sequencer/java/metadata/TypeMetadata.java 2008-07-23 17:12:46 UTC (rev 366)
+++ trunk/sequencers/dna-sequencer-java/src/main/java/org/jboss/dna/sequencer/java/metadata/TypeMetadata.java 2008-07-23 17:17:17 UTC (rev 367)
@@ -32,18 +32,24 @@
* @author Serge Pagop
*/
public class TypeMetadata {
-
+
public static final int PUBLIC_MODIFIER = 0;
-
+
/** The name. */
private String name;
/** All modifiers of a top level type */
private Map<Integer, String> modifiers = new HashMap<Integer, String>();
- /** All annotations of the type meta data */
- private List<AnnotationMetadata> annotationMetadata = new ArrayList<AnnotationMetadata>();
+ /** All annotations of a top level type */
+ private List<AnnotationMetadata> annotations = new ArrayList<AnnotationMetadata>();
+ /** All fields of a top level type */
+ private List<FieldMetadata> fields = new ArrayList<FieldMetadata>();
+
+ /** All methods of a top level type */
+ private List<MethodMetadata> methods = new ArrayList<MethodMetadata>();
+
/**
* Get the name.
*
@@ -63,17 +69,17 @@
}
/**
- * @return annotationMetadata
+ * @return annotations
*/
- public List<AnnotationMetadata> getAnnotationMetadata() {
- return annotationMetadata;
+ public List<AnnotationMetadata> getAnnotations() {
+ return annotations;
}
/**
- * @param annotationMetadata Sets annotationMetadata to the specified value.
+ * @param annotations Sets annotations to the specified value.
*/
- public void setAnnotationMetadata( List<AnnotationMetadata> annotationMetadata ) {
- this.annotationMetadata = annotationMetadata;
+ public void setAnnotations( List<AnnotationMetadata> annotations ) {
+ this.annotations = annotations;
}
/**
@@ -90,4 +96,32 @@
this.modifiers = modifiers;
}
+ /**
+ * @return fields of this top level unit.
+ */
+ public List<FieldMetadata> getFields() {
+ return this.fields;
+ }
+
+ /**
+ * @param fields Sets fields to the specified value.
+ */
+ public void setFields( List<FieldMetadata> fields ) {
+ this.fields = fields;
+ }
+
+ /**
+ * @return methods of this top level unit.
+ */
+ public List<MethodMetadata> getMethods() {
+ return methods;
+ }
+
+ /**
+ * @param methods Sets methods to the specified value.
+ */
+ public void setMethods( List<MethodMetadata> methods ) {
+ this.methods = methods;
+ }
+
}
Added: trunk/sequencers/dna-sequencer-java/src/main/java/org/jboss/dna/sequencer/java/metadata/Variable.java
===================================================================
--- trunk/sequencers/dna-sequencer-java/src/main/java/org/jboss/dna/sequencer/java/metadata/Variable.java (rev 0)
+++ trunk/sequencers/dna-sequencer-java/src/main/java/org/jboss/dna/sequencer/java/metadata/Variable.java 2008-07-23 17:17:17 UTC (rev 367)
@@ -0,0 +1,52 @@
+/*
+ * 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.sequencer.java.metadata;
+
+/**
+ * A variable
+ */
+public class Variable {
+
+ private String name;
+
+ public Variable() {
+ }
+
+ public Variable( String name ) {
+ this.name = name;
+ }
+
+ /**
+ * @return name
+ */
+ public String getName() {
+ return name;
+ }
+
+ /**
+ * @param name Sets name to the specified value.
+ */
+ public void setName( String name ) {
+ this.name = name;
+ }
+
+}
15 years, 9 months