Author: rhauch
Date: 2008-06-10 16:19:15 -0400 (Tue, 10 Jun 2008)
New Revision: 253
Added:
trunk/dna-repository/src/test/java/org/jboss/dna/repository/federation/FederatedRepositoryTest.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/connection/TimeDelayingRepositorySource.java
Removed:
trunk/dna-spi/src/test/java/org/jboss/dna/spi/graph/connection/MockRepositorySource.java
trunk/dna-spi/src/test/java/org/jboss/dna/spi/graph/connection/RepositoryTestOperations.java
Modified:
trunk/dna-repository/pom.xml
trunk/dna-repository/src/main/java/org/jboss/dna/repository/RepositoryI18n.java
trunk/dna-repository/src/main/java/org/jboss/dna/repository/federation/FederatedRepository.java
trunk/dna-repository/src/main/java/org/jboss/dna/repository/federation/FederatedRepositoryConnection.java
trunk/dna-repository/src/main/java/org/jboss/dna/repository/federation/FederatedSource.java
trunk/dna-repository/src/main/java/org/jboss/dna/repository/federation/FederationService.java
trunk/dna-repository/src/main/java/org/jboss/dna/repository/observation/ObservationService.java
trunk/dna-repository/src/main/java/org/jboss/dna/repository/rules/RuleService.java
trunk/dna-repository/src/main/java/org/jboss/dna/repository/sequencers/SequencingService.java
trunk/dna-repository/src/main/java/org/jboss/dna/repository/services/AbstractServiceAdministrator.java
trunk/dna-repository/src/main/java/org/jboss/dna/repository/services/ServiceAdministrator.java
trunk/dna-repository/src/main/resources/org/jboss/dna/repository/RepositoryI18n.properties
trunk/dna-repository/src/test/java/org/jboss/dna/repository/federation/FederatedRepositoryConnectionTest.java
trunk/dna-repository/src/test/java/org/jboss/dna/repository/sequencers/SequencingServiceTest.java
trunk/dna-repository/src/test/java/org/jboss/dna/repository/util/JndiSessionFactoryTest.java
trunk/dna-repository/src/test/resources/log4j.properties
trunk/dna-spi/pom.xml
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/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/impl/BooleanValueFactoryTest.java
trunk/dna-spi/src/test/java/org/jboss/dna/spi/graph/impl/DecimalValueFactoryTest.java
trunk/dna-spi/src/test/java/org/jboss/dna/spi/graph/impl/DoubleValueFactoryTest.java
trunk/dna-spi/src/test/java/org/jboss/dna/spi/graph/impl/JodaDateTimeTest.java
trunk/dna-spi/src/test/java/org/jboss/dna/spi/graph/impl/JodaDateTimeValueFactoryTest.java
trunk/dna-spi/src/test/java/org/jboss/dna/spi/graph/impl/LongValueFactoryTest.java
Log:
DNA-117: Create a FederatedRepository class that manages multiple sources
http://jira.jboss.org/jira/browse/DNA-117
More fully implemented FederatedRepository and added unit tests that cover mode code and
cases.
Modified: trunk/dna-repository/pom.xml
===================================================================
--- trunk/dna-repository/pom.xml 2008-06-10 20:18:05 UTC (rev 252)
+++ trunk/dna-repository/pom.xml 2008-06-10 20:19:15 UTC (rev 253)
@@ -68,16 +68,6 @@
<scope>test</scope>
</dependency>
<dependency>
- <groupId>org.jmock</groupId>
- <artifactId>jmock</artifactId>
- <scope>test</scope>
- </dependency>
- <dependency>
- <groupId>org.jmock</groupId>
- <artifactId>jmock-junit4</artifactId>
- <scope>test</scope>
- </dependency>
- <dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-all</artifactId>
<scope>test</scope>
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-06-10
20:18:05 UTC (rev 252)
+++
trunk/dna-repository/src/main/java/org/jboss/dna/repository/RepositoryI18n.java 2008-06-10
20:19:15 UTC (rev 253)
@@ -34,6 +34,7 @@
public static I18n invalidStateString;
public static I18n serviceShutdowAndMayNotBeStarted;
public static I18n serviceShutdowAndMayNotBePaused;
+ public static I18n serviceNotShutdowAndMayNotBeTerminated;
public static I18n unableToFindRepositoryInJndi;
public static I18n unableToRegisterRepositoryInJndi;
public static I18n unableToUnregisterRepositoryInJndi;
@@ -104,9 +105,9 @@
public static I18n invalidRepositoryNodePath;
// XML Sequencer
- public static I18n errorSequencingXmlDocument;
- public static I18n sequencingXmlDocument;
- public static I18n canceledSequencingXmlDocument;
+ public static I18n errorSequencingXmlDocument;
+ public static I18n sequencingXmlDocument;
+ public static I18n canceledSequencingXmlDocument;
public static I18n interruptedWhileConnectingToFederationConfigurationRepository;
public static I18n
interruptedWhileClosingConnectionToFederationConfigurationRepository;
Modified:
trunk/dna-repository/src/main/java/org/jboss/dna/repository/federation/FederatedRepository.java
===================================================================
---
trunk/dna-repository/src/main/java/org/jboss/dna/repository/federation/FederatedRepository.java 2008-06-10
20:18:05 UTC (rev 252)
+++
trunk/dna-repository/src/main/java/org/jboss/dna/repository/federation/FederatedRepository.java 2008-06-10
20:19:15 UTC (rev 253)
@@ -33,6 +33,7 @@
import org.jboss.dna.repository.services.AbstractServiceAdministrator;
import org.jboss.dna.repository.services.ServiceAdministrator;
import org.jboss.dna.spi.cache.CachePolicy;
+import org.jboss.dna.spi.graph.connection.RepositoryConnection;
import org.jboss.dna.spi.graph.connection.RepositoryConnectionPool;
import org.jboss.dna.spi.graph.connection.RepositorySourceListener;
@@ -82,6 +83,14 @@
return FederatedRepository.this.awaitTermination(timeout, unit);
}
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ protected boolean doCheckIsTerminated() {
+ return FederatedRepository.this.isTerminated();
+ }
+
}
private final ServiceAdministrator administrator = new Administrator();
@@ -107,6 +116,13 @@
}
/**
+ * @return service
+ */
+ protected FederationService getService() {
+ return this.service;
+ }
+
+ /**
* Get the name of this repository
*
* @return name
@@ -127,6 +143,7 @@
*/
protected void startRepository() {
// Do not establish connections to the sources; these will be established as
needed
+
}
/**
@@ -165,6 +182,50 @@
}
/**
+ * Returns true if this federated repository is in the process of terminating after
{@link ServiceAdministrator#shutdown()}
+ * has been called on the {@link #getAdministrator() administrator}, but the
federated repository has connections that have
+ * not yet normally been {@link RepositoryConnection#close() closed}. This method may
be useful for debugging. A return of
+ * <tt>true</tt> reported a sufficient period after shutdown may indicate
that connection users have ignored or suppressed
+ * interruption, causing this repository not to properly terminate.
+ *
+ * @return true if terminating but not yet terminated, or false otherwise
+ * @see #isTerminated()
+ */
+ public boolean isTerminating() {
+ try {
+ this.sourcesWriteLock.lock();
+ for (FederatedSource source : this.sources) {
+ if (source.getConnectionPool().isTerminating()) {
+ return true;
+ }
+ }
+ return false;
+ } finally {
+ this.sourcesWriteLock.unlock();
+ }
+ }
+
+ /**
+ * Return true if this federated repository has completed its termination and no
longer has any open connections.
+ *
+ * @return true if terminated, or false otherwise
+ * @see #isTerminating()
+ */
+ public boolean isTerminated() {
+ try {
+ this.sourcesWriteLock.lock();
+ for (FederatedSource source : this.sources) {
+ if (!source.getConnectionPool().isTerminated()) {
+ return false;
+ }
+ }
+ return true;
+ } finally {
+ this.sourcesWriteLock.unlock();
+ }
+ }
+
+ /**
* Get an unmodifiable collection of {@link FederatedSource federated sources}.
* <p>
* This method can safely be called while the federation repository is in use.
@@ -287,10 +348,12 @@
* 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 void addListener( RepositorySourceListener listener ) {
- if (listener == null) return;
- this.listeners.addIfAbsent(listener);
+ public boolean addListener( RepositorySourceListener listener ) {
+ if (listener == null) return false;
+ return this.listeners.addIfAbsent(listener);
}
/**
@@ -308,6 +371,15 @@
}
/**
+ * 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 username the username
Modified:
trunk/dna-repository/src/main/java/org/jboss/dna/repository/federation/FederatedRepositoryConnection.java
===================================================================
---
trunk/dna-repository/src/main/java/org/jboss/dna/repository/federation/FederatedRepositoryConnection.java 2008-06-10
20:18:05 UTC (rev 252)
+++
trunk/dna-repository/src/main/java/org/jboss/dna/repository/federation/FederatedRepositoryConnection.java 2008-06-10
20:19:15 UTC (rev 253)
@@ -117,6 +117,11 @@
if (!this.repository.getAdministrator().isStarted()) {
throw new
RepositorySourceException(RepositoryI18n.repositoryHasBeenShutDown.text(this.repository.getName()));
}
+ if (commands == null || commands.length == 0) return;
+
+ for (GraphCommand command : commands) {
+ if (command == null) continue;
+ }
}
/**
Modified:
trunk/dna-repository/src/main/java/org/jboss/dna/repository/federation/FederatedSource.java
===================================================================
---
trunk/dna-repository/src/main/java/org/jboss/dna/repository/federation/FederatedSource.java 2008-06-10
20:18:05 UTC (rev 252)
+++
trunk/dna-repository/src/main/java/org/jboss/dna/repository/federation/FederatedSource.java 2008-06-10
20:19:15 UTC (rev 253)
@@ -25,8 +25,10 @@
import net.jcip.annotations.ThreadSafe;
import org.jboss.dna.common.util.ArgCheck;
import org.jboss.dna.spi.graph.connection.RepositoryConnection;
+import org.jboss.dna.spi.graph.connection.RepositoryConnectionFactory;
import org.jboss.dna.spi.graph.connection.RepositoryConnectionPool;
import org.jboss.dna.spi.graph.connection.RepositorySource;
+import org.jboss.dna.spi.graph.connection.RepositorySourceException;
/**
* A component that represents a {@link RepositorySource repository source} (with its
state) being federated in a
@@ -35,7 +37,7 @@
* @author Randall Hauch
*/
@ThreadSafe
-public class FederatedSource {
+public class FederatedSource implements RepositoryConnectionFactory {
private final RepositorySource source;
private final RepositoryConnectionPool connectionPool;
@@ -46,6 +48,12 @@
this.connectionPool = new RepositoryConnectionPool(source);
}
+ protected FederatedSource( RepositorySource source, RepositoryConnectionPool
connectionPool ) {
+ ArgCheck.isNotNull(source, "source");
+ this.source = source;
+ this.connectionPool = connectionPool;
+ }
+
/**
* Get the name for this federated repository source.
*
@@ -74,6 +82,13 @@
}
/**
+ * {@inheritDoc}
+ */
+ public RepositoryConnection getConnection() throws RepositorySourceException,
InterruptedException {
+ return this.connectionPool.getConnection();
+ }
+
+ /**
* Determine whether the federated source is available by attempting to connect to
the source and
* {@link RepositoryConnection#ping(long, TimeUnit) pinging} the source.
*
Modified:
trunk/dna-repository/src/main/java/org/jboss/dna/repository/federation/FederationService.java
===================================================================
---
trunk/dna-repository/src/main/java/org/jboss/dna/repository/federation/FederationService.java 2008-06-10
20:18:05 UTC (rev 252)
+++
trunk/dna-repository/src/main/java/org/jboss/dna/repository/federation/FederationService.java 2008-06-10
20:19:15 UTC (rev 253)
@@ -72,10 +72,18 @@
/**
* {@inheritDoc}
*/
- public boolean awaitTermination( long timeout, TimeUnit unit ) {
- return true;
+ @Override
+ protected boolean doCheckIsTerminated() {
+ return FederationService.this.isTerminated();
}
+ /**
+ * {@inheritDoc}
+ */
+ public boolean awaitTermination( long timeout, TimeUnit unit ) throws
InterruptedException {
+ return FederationService.this.awaitTermination(timeout, unit);
+ }
+
}
private final RepositorySource configurationSource;
@@ -164,6 +172,24 @@
}
}
+ protected boolean isTerminated() {
+ // Now shut down all repositories ...
+ for (String repositoryName : this.repositories.keySet()) {
+ FederatedRepository repository = this.repositories.get(repositoryName);
+ if (!repository.getAdministrator().isTerminated()) return false;
+ }
+ return true;
+ }
+
+ protected boolean awaitTermination( long timeout, TimeUnit unit ) throws
InterruptedException {
+ // Now shut down all repositories ...
+ for (String repositoryName : this.repositories.keySet()) {
+ FederatedRepository repository = this.repositories.get(repositoryName);
+ if (repository.getAdministrator().awaitTermination(timeout, unit)) return
false;
+ }
+ return true;
+ }
+
/**
* Create a {@link RepositorySource} that can be used to establish connections to the
federated repository with the supplied
* name.
Modified:
trunk/dna-repository/src/main/java/org/jboss/dna/repository/observation/ObservationService.java
===================================================================
---
trunk/dna-repository/src/main/java/org/jboss/dna/repository/observation/ObservationService.java 2008-06-10
20:18:05 UTC (rev 252)
+++
trunk/dna-repository/src/main/java/org/jboss/dna/repository/observation/ObservationService.java 2008-06-10
20:19:15 UTC (rev 253)
@@ -56,6 +56,7 @@
/**
* Interface to which problems with particular events are logged.
+ *
* @author Randall Hauch
*/
public static interface ProblemLog {
@@ -65,6 +66,7 @@
/**
* Problem log implementation that records problems in the log.
+ *
* @author Randall Hauch
*/
public class DefaultProblemLog implements ProblemLog {
@@ -90,6 +92,7 @@
/**
* The administrative component for this service.
+ *
* @author Randall Hauch
*/
protected class Administrator extends AbstractServiceAdministrator {
@@ -114,6 +117,14 @@
return true;
}
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ protected boolean doCheckIsTerminated() {
+ return true;
+ }
+
}
private Logger logger = Logger.getLogger(this.getClass());
@@ -146,6 +157,7 @@
/**
* Get the statistics for this system.
+ *
* @return the statistics, which are updated as the system is used
*/
public Statistics getStatistics() {
@@ -154,6 +166,7 @@
/**
* Get the logger for this system
+ *
* @return the logger
*/
public Logger getLogger() {
@@ -162,6 +175,7 @@
/**
* Set the logger for this system.
+ *
* @param logger the logger, or null if the standard logging should be used
*/
public void setLogger( Logger logger ) {
@@ -177,6 +191,7 @@
/**
* Set the problem log that will be notified of problems handling events. By default,
such problems are sent to the log.
+ *
* @param problemLog the new problem log implementation; if null, then the default
problem log is used
*/
public void setProblemLog( ProblemLog problemLog ) {
@@ -256,6 +271,7 @@
* The filters of an already-registered {@link WorkspaceListener} can be changed at
runtime by changing the attributes and
* {@link WorkspaceListener#reregister() registering}.
* </p>
+ *
* @param repositoryWorkspaceName the name to be used with the session factory to
obtain a session to the repository and
* workspace that is to be monitored
* @param absolutePath the absolute path of the node at or below which changes are to
be monitored; may be null if all nodes
@@ -292,6 +308,7 @@
* needed, it simply must be {@link
ObservationManager#removeEventListener(EventListener) removed} as a listener of the
* workspace and garbage collected.
* </p>
+ *
* @param repositoryWorkspaceName the name to be used with the session factory to
obtain a session to the repository and
* workspace that is to be monitored
* @param absolutePath the absolute path of the node at or below which changes are to
be monitored; may be null if all nodes
@@ -317,6 +334,7 @@
* needed, it simply must be {@link
ObservationManager#removeEventListener(EventListener) removed} as a listener of the
* workspace and garbage collected.
* </p>
+ *
* @param repositoryWorkspaceName the name to be used with the session factory to
obtain a session to the repository and
* workspace that is to be monitored
* @param eventTypes the bitmask of the {@link Event} types that are to be monitored
@@ -341,6 +359,7 @@
* made but excluding those to which that particular listener is not entitled,
according to the listeners access permissions
* and filters.
* </p>
+ *
* @param events
* @param listener
*/
@@ -460,6 +479,7 @@
/**
* Implementation of the {@link EventListener JCR EventListener} interface, returned
by the sequencing system.
+ *
* @author Randall Hauch
*/
@ThreadSafe
@@ -617,6 +637,7 @@
/**
* The statistics for the system. Each sequencing system has an instance of this
class that is updated.
+ *
* @author Randall Hauch
*/
@ThreadSafe
Modified:
trunk/dna-repository/src/main/java/org/jboss/dna/repository/rules/RuleService.java
===================================================================
---
trunk/dna-repository/src/main/java/org/jboss/dna/repository/rules/RuleService.java 2008-06-10
20:18:05 UTC (rev 252)
+++
trunk/dna-repository/src/main/java/org/jboss/dna/repository/rules/RuleService.java 2008-06-10
20:19:15 UTC (rev 253)
@@ -70,6 +70,7 @@
* the same time, all executions will be properly synchronized with methods to {@link
#addRuleSet(RuleSet) add},
* {@link #updateRuleSet(RuleSet) update}, and {@link #removeRuleSet(String) remove} rule
sets.
* </p>
+ *
* @author Randall Hauch
*/
@ThreadSafe
@@ -79,6 +80,7 @@
/**
* The administrative component for this service.
+ *
* @author Randall Hauch
*/
protected class Administrator extends AbstractServiceAdministrator {
@@ -100,6 +102,14 @@
/**
* {@inheritDoc}
*/
+ @Override
+ protected boolean doCheckIsTerminated() {
+ return RuleService.this.isTerminated();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
public boolean awaitTermination( long timeout, TimeUnit unit ) throws
InterruptedException {
return doAwaitTermination(timeout, unit);
}
@@ -124,6 +134,7 @@
/**
* Return the administrative component for this service.
+ *
* @return the administrative component; never null
*/
public ServiceAdministrator getAdministrator() {
@@ -134,6 +145,7 @@
* Get the class loader factory that should be used to load sequencers. By default,
this service uses a factory that will
* return either the {@link Thread#getContextClassLoader() current thread's
context class loader} (if not null) or the class
* loader that loaded this class.
+ *
* @return the class loader factory; never null
* @see #setClassLoaderFactory(ClassLoaderFactory)
*/
@@ -145,6 +157,7 @@
* Set the Maven Repository that should be used to load the sequencer classes. By
default, this service uses a class loader
* factory that will return either the {@link Thread#getContextClassLoader() current
thread's context class loader} (if not
* null) or the class loader that loaded this class.
+ *
* @param classLoaderFactory the class loader factory reference, or null if the
default class loader factory should be used.
* @see #getClassLoaderFactory()
*/
@@ -154,6 +167,7 @@
/**
* Obtain the rule sets that are currently available in this service.
+ *
* @return an unmodifiable copy of the rule sets; never null, but possibly empty ...
*/
public Collection<RuleSet> getRuleSets() {
@@ -170,6 +184,7 @@
/**
* Add a rule set, or update any existing one that represents the {@link
RuleSet#equals(Object) same rule set}
+ *
* @param ruleSet the new rule set
* @return true if the rule set was added, or false if the rule set was not added
(because it wasn't necessary)
* @throws IllegalArgumentException if <code>ruleSet</code> is null
@@ -266,6 +281,7 @@
/**
* Update the configuration for a sequencer, or add it if there is no {@link
RuleSet#equals(Object) matching configuration}.
+ *
* @param ruleSet the rule set to be updated
* @return true if the rule set was updated, or false if the rule set was not updated
(because it wasn't necessary)
* @throws InvalidRuleSetException if the supplied rule set is invalid, incomplete,
incorrectly defined, or uses a JSR-94
@@ -279,6 +295,7 @@
/**
* Remove a rule set.
+ *
* @param ruleSetName the name of the rule set to be removed
* @return true if the rule set was removed, or if it was not an existing rule set
* @throws IllegalArgumentException if <code>ruleSetName</code> is null
or empty
@@ -310,6 +327,7 @@
/**
* Get the logger for this system
+ *
* @return the logger
*/
public Logger getLogger() {
@@ -318,6 +336,7 @@
/**
* Set the logger for this system.
+ *
* @param logger the logger, or null if the standard logging should be used
*/
public void setLogger( Logger logger ) {
@@ -328,6 +347,7 @@
* Execute the set of rules defined by the supplied rule set name. This method is
safe to be concurrently called by multiple
* threads, and is properly synchronized with the methods to {@link
#addRuleSet(RuleSet) add},
* {@link #updateRuleSet(RuleSet) update}, and {@link #removeRuleSet(String) remove}
rule sets.
+ *
* @param ruleSetName the {@link RuleSet#getName() name} of the {@link RuleSet} that
should be used
* @param globals the global variables
* @param facts the facts
@@ -396,8 +416,13 @@
return this.shutdownLatch.await(timeout, unit);
}
+ protected boolean isTerminated() {
+ return this.shutdownLatch.getCount() == 0;
+ }
+
/**
* Finds the JSR-94 service provider instance and returns it. If it could not be
found, this method attempts to load it.
+ *
* @param ruleSet the rule set for which the service provider is to be found; may not
be null
* @return the rule service provider; never null
* @throws ConfigurationException if there is a problem loading the service provider
@@ -433,6 +458,7 @@
/**
* Deregister the supplied rule set, if it could be found. This method does nothing
if any of the service provider components
* could not be found.
+ *
* @param ruleSet the rule set to be deregistered; may not be null
* @return the service provider reference, or null if the service provider could not
be found ...
* @throws ConfigurationException
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-06-10
20:18:05 UTC (rev 252)
+++
trunk/dna-repository/src/main/java/org/jboss/dna/repository/sequencers/SequencingService.java 2008-06-10
20:19:15 UTC (rev 253)
@@ -66,18 +66,21 @@
/**
* A sequencing system is used to monitor changes in the content of {@link Repository JCR
repositories} and to sequence the
* content to extract or to generate structured information.
+ *
* @author Randall Hauch
*/
public class SequencingService implements AdministeredService, NodeChangeListener {
/**
* Interface used to select the set of {@link Sequencer} instances that should be
run.
+ *
* @author Randall Hauch
*/
public static interface Selector {
/**
* Select the sequencers that should be used to sequence the supplied node.
+ *
* @param sequencers the list of all sequencers available at the moment; never
null
* @param node the node to be sequenced; never null
* @param nodeChange the set of node changes; never null
@@ -89,6 +92,7 @@
/**
* The default {@link Selector} implementation that selects every sequencer every
time it's called, regardless of the node (or
* logger) supplied.
+ *
* @author Randall Hauch
*/
protected static class DefaultSelector implements Selector {
@@ -100,12 +104,14 @@
/**
* Interface used to determine whether a {@link NodeChange} should be processed.
+ *
* @author Randall Hauch
*/
public static interface NodeFilter {
/**
* Determine whether the node represented by the supplied change should be
submitted for sequencing.
+ *
* @param nodeChange the node change event
* @return true if the node should be submitted for sequencing, or false if the
change should be ignored
*/
@@ -114,6 +120,7 @@
/**
* The default filter implementation, which accepts only new nodes or nodes that have
new or changed properties.
+ *
* @author Randall Hauch
*/
protected static class DefaultNodeFilter implements NodeFilter {
@@ -126,11 +133,13 @@
/**
* The default {@link Selector} that considers every {@link Sequencer} to be used for
every node.
+ *
* @see
SequencingService#setSequencerSelector(org.jboss.dna.repository.sequencers.SequencingService.Selector)
*/
public static final Selector DEFAULT_SEQUENCER_SELECTOR = new DefaultSelector();
/**
* The default {@link NodeFilter} that accepts new nodes or nodes that have
new/changed properties.
+ *
* @see
SequencingService#setSequencerSelector(org.jboss.dna.repository.sequencers.SequencingService.Selector)
*/
public static final NodeFilter DEFAULT_NODE_FILTER = new DefaultNodeFilter();
@@ -144,6 +153,7 @@
/**
* The administrative component for this service.
+ *
* @author Randall Hauch
*/
protected class Administrator extends AbstractServiceAdministrator {
@@ -173,6 +183,14 @@
/**
* {@inheritDoc}
*/
+ @Override
+ protected boolean doCheckIsTerminated() {
+ return isServiceTerminated();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
public boolean awaitTermination( long timeout, TimeUnit unit ) throws
InterruptedException {
return doAwaitTermination(timeout, unit);
}
@@ -199,6 +217,7 @@
/**
* Return the administrative component for this service.
+ *
* @return the administrative component; never null
*/
public ServiceAdministrator getAdministrator() {
@@ -207,6 +226,7 @@
/**
* Get the statistics for this system.
+ *
* @return statistics
*/
public Statistics getStatistics() {
@@ -224,6 +244,7 @@
* Get the class loader factory that should be used to load sequencers. By default,
this service uses a factory that will
* return either the {@link Thread#getContextClassLoader() current thread's
context class loader} (if not null) or the class
* loader that loaded this class.
+ *
* @return the class loader factory; never null
* @see #setClassLoaderFactory(ClassLoaderFactory)
*/
@@ -235,6 +256,7 @@
* Set the Maven Repository that should be used to load the sequencer classes. By
default, this service uses a class loader
* factory that will return either the {@link Thread#getContextClassLoader() current
thread's context class loader} (if not
* null) or the class loader that loaded this class.
+ *
* @param classLoaderFactory the class loader factory reference, or null if the
default class loader factory should be used.
* @see #getClassLoaderFactory()
*/
@@ -245,6 +267,7 @@
/**
* Add the configuration for a sequencer, or update any existing one that represents
the
* {@link SequencerConfig#equals(Object) same configuration}
+ *
* @param config the new configuration
* @return true if the sequencer was added, or false if there already was an existing
and
* {@link SequencerConfig#hasChanged(SequencerConfig) unchanged} sequencer
configuration
@@ -259,6 +282,7 @@
/**
* 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
* {@link SequencerConfig#hasChanged(SequencerConfig) unchanged} sequencer
configuration
@@ -272,6 +296,7 @@
/**
* Remove the configuration for a sequencer.
+ *
* @param config the configuration to be removed
* @return true if the sequencer was removed, or false if there was no existing
sequencer
* @throws IllegalArgumentException if <code>config</code> is null
@@ -284,6 +309,7 @@
/**
* Get the logger for this system
+ *
* @return the logger
*/
public Logger getLogger() {
@@ -292,6 +318,7 @@
/**
* Set the logger for this system.
+ *
* @param logger the logger, or null if the standard logging should be used
*/
public void setLogger( Logger logger ) {
@@ -318,6 +345,7 @@
/**
* Get the executor service used to run the sequencers.
+ *
* @return the executor service
* @see #setExecutorService(ExecutorService)
*/
@@ -328,6 +356,7 @@
/**
* Set the executor service that should be used by this system. By default, the
system is set up with a
* {@link Executors#newSingleThreadExecutor() executor that uses a single thread}.
+ *
* @param executorService the executor service
* @see #getExecutorService()
* @see Executors#newCachedThreadPool()
@@ -355,6 +384,7 @@
* <p>
* This method creates a {@link Executors#newSingleThreadExecutor() single-threaded
executor}.
* </p>
+ *
* @return
*/
protected ExecutorService createDefaultExecutorService() {
@@ -380,6 +410,13 @@
}
}
+ protected boolean isServiceTerminated() {
+ if (this.executorService != null) {
+ return this.executorService.isTerminated();
+ }
+ return true;
+ }
+
protected boolean doAwaitTermination( long timeout, TimeUnit unit ) throws
InterruptedException {
if (this.executorService == null || this.executorService.isTerminated()) return
true;
return this.executorService.awaitTermination(timeout, unit);
@@ -387,6 +424,7 @@
/**
* Get the sequencing selector used by this system.
+ *
* @return the sequencing selector
*/
public Selector getSequencerSelector() {
@@ -395,6 +433,7 @@
/**
* Set the sequencer selector, or null if the {@link #DEFAULT_SEQUENCER_SELECTOR
default sequencer selector} should be used.
+ *
* @param sequencerSelector the selector
*/
public void setSequencerSelector( Selector sequencerSelector ) {
@@ -403,6 +442,7 @@
/**
* Get the node filter used by this system.
+ *
* @return the node filter
*/
public NodeFilter getNodeFilter() {
@@ -412,6 +452,7 @@
/**
* Set the filter that checks which nodes are to be sequenced, or null if the {@link
#DEFAULT_NODE_FILTER default node filter}
* should be used.
+ *
* @param nodeFilter the new node filter
*/
public void setNodeFilter( NodeFilter nodeFilter ) {
@@ -443,6 +484,7 @@
/**
* Do the work of processing by sequencing the node. This method is called by the
{@link #executorService executor service}
* when it performs it's work on the enqueued {@link ChangedNode ChangedNode
runnable objects}.
+ *
* @param node the node to be processed.
*/
protected void processChangedNode( NodeChange changedNode ) {
@@ -620,6 +662,7 @@
/**
* The statistics for the system. Each sequencing system has an instance of this
class that is updated.
+ *
* @author Randall Hauch
*/
@ThreadSafe
Modified:
trunk/dna-repository/src/main/java/org/jboss/dna/repository/services/AbstractServiceAdministrator.java
===================================================================
---
trunk/dna-repository/src/main/java/org/jboss/dna/repository/services/AbstractServiceAdministrator.java 2008-06-10
20:18:05 UTC (rev 252)
+++
trunk/dna-repository/src/main/java/org/jboss/dna/repository/services/AbstractServiceAdministrator.java 2008-06-10
20:19:15 UTC (rev 253)
@@ -30,6 +30,7 @@
/**
* Simple abstract implementation of the service administrator interface that can be
easily subclassed by services that require an
* administrative interface.
+ *
* @author Randall Hauch
*/
@ThreadSafe
@@ -47,6 +48,7 @@
/**
* Return the current state of this service.
+ *
* @return the current state
*/
public State getState() {
@@ -55,6 +57,7 @@
/**
* Set the state of the service. This method does nothing if the desired state
matches the current state.
+ *
* @param state the desired state
* @return this object for method chaining purposes
* @see #setState(String)
@@ -72,6 +75,7 @@
pause();
break;
case SHUTDOWN:
+ case TERMINATED:
shutdown();
break;
}
@@ -80,6 +84,7 @@
/**
* Set the state of the service. This method does nothing if the desired state
matches the current state.
+ *
* @param state the desired state in string form
* @return this object for method chaining purposes
* @throws IllegalArgumentException if the specified state string is null or does not
match one of the predefined
@@ -100,6 +105,7 @@
/**
* Start monitoring and sequence the events. This method can be called multiple
times, including after the service is
* {@link #pause() paused}. However, once the service is {@link #shutdown()
shutdown}, it cannot be started or paused.
+ *
* @return this object for method chaining purposes
* @throws IllegalStateException if called when the service has been {@link
#shutdown() shutdown}.
* @see #pause()
@@ -107,10 +113,16 @@
* @see #isStarted()
*/
public synchronized ServiceAdministrator start() {
- if (isShutdown()) throw new
IllegalStateException(RepositoryI18n.serviceShutdowAndMayNotBeStarted.text(getServiceName()));
- if (this.state != State.STARTED) {
- doStart(this.state);
- this.state = State.STARTED;
+ switch (this.state) {
+ case STARTED:
+ break;
+ case PAUSED:
+ doStart(this.state);
+ this.state = State.STARTED;
+ break;
+ case SHUTDOWN:
+ case TERMINATED:
+ throw new
IllegalStateException(RepositoryI18n.serviceShutdowAndMayNotBeStarted.text(getServiceName()));
}
return this;
}
@@ -119,6 +131,7 @@
* Implementation of the functionality to switch to the started state. This method is
only called if the state from which the
* service is transitioning is appropriate ({@link State#PAUSED}). This method does
nothing by default, and should be
* overridden if needed.
+ *
* @param fromState the state from which this service is transitioning; never null
* @throws IllegalStateException if the service is such that it cannot be
transitioned from the supplied state
*/
@@ -129,6 +142,7 @@
/**
* Temporarily stop monitoring and sequencing events. This method can be called
multiple times, including after the service is
* {@link #start() started}. However, once the service is {@link #shutdown()
shutdown}, it cannot be started or paused.
+ *
* @return this object for method chaining purposes
* @throws IllegalStateException if called when the service has been {@link
#shutdown() shutdown}.
* @see #start()
@@ -136,10 +150,16 @@
* @see #isPaused()
*/
public synchronized ServiceAdministrator pause() {
- if (isShutdown()) throw new
IllegalStateException(RepositoryI18n.serviceShutdowAndMayNotBePaused.text(getServiceName()));
- if (this.state != State.PAUSED) {
- doPause(this.state);
- this.state = State.PAUSED;
+ switch (this.state) {
+ case STARTED:
+ doPause(this.state);
+ this.state = State.PAUSED;
+ break;
+ case PAUSED:
+ break;
+ case SHUTDOWN:
+ case TERMINATED:
+ throw new
IllegalStateException(RepositoryI18n.serviceShutdowAndMayNotBePaused.text(getServiceName()));
}
return this;
}
@@ -148,6 +168,7 @@
* Implementation of the functionality to switch to the paused state. This method is
only called if the state from which the
* service is transitioning is appropriate ({@link State#STARTED}). This method does
nothing by default, and should be
* overridden if needed.
+ *
* @param fromState the state from which this service is transitioning; never null
* @throws IllegalStateException if the service is such that it cannot be
transitioned from the supplied state
*/
@@ -158,15 +179,24 @@
/**
* Permanently stop monitoring and sequencing events. This method can be called
multiple times, but only the first call has an
* effect. Once the service has been shutdown, it may not be {@link #start()
restarted} or {@link #pause() paused}.
+ *
* @return this object for method chaining purposes
* @see #start()
* @see #pause()
* @see #isShutdown()
*/
public synchronized ServiceAdministrator shutdown() {
- if (this.state != State.SHUTDOWN) {
- doShutdown(this.state);
- this.state = State.SHUTDOWN;
+ switch (this.state) {
+ case STARTED:
+ case PAUSED:
+ this.state = State.SHUTDOWN;
+ doShutdown(this.state);
+ isTerminated();
+ break;
+ case SHUTDOWN:
+ case TERMINATED:
+ isTerminated();
+ break;
}
return this;
}
@@ -175,6 +205,7 @@
* Implementation of the functionality to switch to the shutdown state. This method
is only called if the state from which the
* service is transitioning is appropriate ({@link State#STARTED} or {@link
State#PAUSED}). This method does nothing by
* default, and should be overridden if needed.
+ *
* @param fromState the state from which this service is transitioning; never null
* @throws IllegalStateException if the service is such that it cannot be
transitioned from the supplied state
*/
@@ -184,6 +215,7 @@
/**
* Return whether this service has been started and is currently running.
+ *
* @return true if started and currently running, or false otherwise
* @see #start()
* @see #pause()
@@ -196,6 +228,7 @@
/**
* Return whether this service is currently paused.
+ *
* @return true if currently paused, or false otherwise
* @see #pause()
* @see #start()
@@ -208,17 +241,45 @@
/**
* Return whether this service is stopped and unable to be restarted.
+ *
* @return true if currently shutdown, or false otherwise
* @see #shutdown()
* @see #isPaused()
* @see #isStarted()
*/
public boolean isShutdown() {
- return this.state == State.SHUTDOWN;
+ return this.state == State.SHUTDOWN || this.state == State.TERMINATED;
}
/**
+ * {@inheritDoc}
+ */
+ public boolean isTerminated() {
+ switch (this.state) {
+ case PAUSED:
+ case STARTED:
+ case SHUTDOWN:
+ if (doCheckIsTerminated()) {
+ this.state = State.TERMINATED;
+ return true;
+ }
+ return false;
+ case TERMINATED:
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Subclasses should implement this method to determine whether the service has
completed shutdown.
+ *
+ * @return true if terminated, or false otherwise
+ */
+ protected abstract boolean doCheckIsTerminated();
+
+ /**
* Get the name of this service in the current locale.
+ *
* @return the service name
*/
public String getServiceName() {
@@ -227,10 +288,12 @@
/**
* Get the name of this service in the specified locale.
+ *
* @param locale the locale in which the service name is to be returned; may be null
if the default locale is to be used
* @return the service name
*/
public String getServiceName( Locale locale ) {
return this.serviceName.text(locale);
}
+
}
Modified:
trunk/dna-repository/src/main/java/org/jboss/dna/repository/services/ServiceAdministrator.java
===================================================================
---
trunk/dna-repository/src/main/java/org/jboss/dna/repository/services/ServiceAdministrator.java 2008-06-10
20:18:05 UTC (rev 252)
+++
trunk/dna-repository/src/main/java/org/jboss/dna/repository/services/ServiceAdministrator.java 2008-06-10
20:19:15 UTC (rev 253)
@@ -26,6 +26,7 @@
/**
* Contract defining an administrative interface for controlling the running state of a
service.
+ *
* @author Randall Hauch
*/
@ThreadSafe
@@ -33,22 +34,26 @@
/**
* The available states.
+ *
* @author Randall Hauch
*/
public static enum State {
STARTED,
PAUSED,
- SHUTDOWN;
+ SHUTDOWN,
+ TERMINATED;
}
/**
* Return the current state of this system.
+ *
* @return the current state
*/
public State getState();
/**
* Set the state of the system. This method does nothing if the desired state matches
the current state.
+ *
* @param state the desired state
* @return this object for method chaining purposes
* @see #setState(String)
@@ -60,6 +65,7 @@
/**
* Set the state of the system. This method does nothing if the desired state matches
the current state.
+ *
* @param state the desired state in string form
* @return this object for method chaining purposes
* @throws IllegalArgumentException if the specified state string is null or does not
match one of the predefined
@@ -74,6 +80,7 @@
/**
* Start monitoring and sequence the events. This method can be called multiple
times, including after the system is
* {@link #pause() paused}. However, once the system is {@link #shutdown() shutdown},
it cannot be started or paused.
+ *
* @return this object for method chaining purposes
* @throws IllegalStateException if called when the system has been {@link
#shutdown() shutdown}.
* @see #pause()
@@ -85,6 +92,7 @@
/**
* Temporarily stop monitoring and sequencing events. This method can be called
multiple times, including after the system is
* {@link #start() started}. However, once the system is {@link #shutdown()
shutdown}, it cannot be started or paused.
+ *
* @return this object for method chaining purposes
* @throws IllegalStateException if called when the system has been {@link
#shutdown() shutdown}.
* @see #start()
@@ -96,6 +104,7 @@
/**
* Permanently stop monitoring and sequencing events. This method can be called
multiple times, but only the first call has an
* effect. Once the system has been shutdown, it may not be {@link #start()
restarted} or {@link #pause() paused}.
+ *
* @return this object for method chaining purposes
* @see #start()
* @see #pause()
@@ -104,41 +113,62 @@
public ServiceAdministrator shutdown();
/**
- * Blocks until all work has completed execution after a shutdown request, or the
timeout occurs, or the current thread is
- * interrupted, whichever happens first.
+ * Blocks until the shutdown has completed, or the timeout occurs, or the current
thread is interrupted, whichever happens
+ * first.
+ *
* @param timeout the maximum time to wait
* @param unit the time unit of the timeout argument
- * @return <tt>true</tt> if this service terminated and
<tt>false</tt> if the timeout elapsed before termination
+ * @return <tt>true</tt> if this service complete shut down and
<tt>false</tt> if the timeout elapsed before it was shut
+ * down completely
* @throws InterruptedException if interrupted while waiting
*/
boolean awaitTermination( long timeout, TimeUnit unit ) throws InterruptedException;
/**
* Return whether this system has been started and is currently running.
+ *
* @return true if started and currently running, or false otherwise
* @see #start()
* @see #pause()
* @see #isPaused()
* @see #isShutdown()
+ * @see #isTerminated()
*/
public boolean isStarted();
/**
* Return whether this system is currently paused.
+ *
* @return true if currently paused, or false otherwise
* @see #pause()
* @see #start()
* @see #isStarted()
* @see #isShutdown()
+ * @see #isTerminated()
*/
public boolean isPaused();
/**
- * Return whether this system is stopped and unable to be restarted.
- * @return true if currently shutdown, or false otherwise
+ * Return whether this system has been shut down.
+ *
+ * @return true if this service has been shut down, or false otherwise
* @see #shutdown()
* @see #isPaused()
* @see #isStarted()
+ * @see #isTerminated()
*/
public boolean isShutdown();
+
+ /**
+ * Return whether this system has finished {@link #shutdown() shutting down}. Note
that <code>isTerminated</code> is never
+ * <code>true</code> unless either {@link #shutdown()} was called first.
+ *
+ * @return true if the system has finished shutting down, or false otherwise
+ * @see #shutdown()
+ * @see #isPaused()
+ * @see #isStarted()
+ * @see #isShutdown()
+ */
+ public boolean isTerminated();
+
}
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-06-10
20:18:05 UTC (rev 252)
+++
trunk/dna-repository/src/main/resources/org/jboss/dna/repository/RepositoryI18n.properties 2008-06-10
20:19:15 UTC (rev 253)
@@ -22,6 +22,7 @@
invalidStateString = Invalid state parameter "{0}"
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}"
Modified:
trunk/dna-repository/src/test/java/org/jboss/dna/repository/federation/FederatedRepositoryConnectionTest.java
===================================================================
---
trunk/dna-repository/src/test/java/org/jboss/dna/repository/federation/FederatedRepositoryConnectionTest.java 2008-06-10
20:18:05 UTC (rev 252)
+++
trunk/dna-repository/src/test/java/org/jboss/dna/repository/federation/FederatedRepositoryConnectionTest.java 2008-06-10
20:19:15 UTC (rev 253)
@@ -105,6 +105,24 @@
}
@Test
+ public void shouldReturnImmediatelyWhenExecutingNullOrEmptyCommandArray() {
+ stub(repositoryAdmin.isStarted()).toReturn(true);
+ ExecutionEnvironment env = mock(ExecutionEnvironment.class);
+ connection.execute(env, (GraphCommand[])null);
+ verify(repositoryAdmin, times(1)).isStarted();
+ connection.execute(env, new GraphCommand[0]);
+ verify(repositoryAdmin, times(2)).isStarted();
+ }
+
+ @Test
+ public void shouldSkipNullCommandReferencesWhenExecuting() {
+ stub(repositoryAdmin.isStarted()).toReturn(true);
+ ExecutionEnvironment env = mock(ExecutionEnvironment.class);
+ connection.execute(env, new GraphCommand[] {null, null, null});
+ verify(repositoryAdmin, times(1)).isStarted();
+ }
+
+ @Test
public void shouldAddListenerToRepositoryWhenSetOnConnection() {
// Old listener is no-op, so it is not removed from repository ...
RepositorySourceListener listener = mock(RepositorySourceListener.class);
@@ -129,5 +147,4 @@
connection.close();
verify(repository, times(1)).removeListener(listener2);
}
-
}
Added:
trunk/dna-repository/src/test/java/org/jboss/dna/repository/federation/FederatedRepositoryTest.java
===================================================================
---
trunk/dna-repository/src/test/java/org/jboss/dna/repository/federation/FederatedRepositoryTest.java
(rev 0)
+++
trunk/dna-repository/src/test/java/org/jboss/dna/repository/federation/FederatedRepositoryTest.java 2008-06-10
20:19:15 UTC (rev 253)
@@ -0,0 +1,222 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site:
http://www.fsf.org.
+ */
+package org.jboss.dna.repository.federation;
+
+import static org.hamcrest.core.Is.is;
+import static org.hamcrest.core.IsNull.notNullValue;
+import static org.hamcrest.core.IsSame.sameInstance;
+import static org.junit.Assert.assertThat;
+import static org.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 java.util.concurrent.TimeUnit;
+import org.jboss.dna.spi.graph.connection.RepositoryConnection;
+import org.jboss.dna.spi.graph.connection.RepositorySourceListener;
+import org.jboss.dna.spi.graph.connection.TimeDelayingRepositorySource;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.MockitoAnnotations;
+import org.mockito.MockitoAnnotations.Mock;
+
+/**
+ * @author Randall Hauch
+ */
+public class FederatedRepositoryTest {
+
+ private FederatedRepository repository;
+ private String name;
+ @Mock
+ private FederationService service;
+ @Mock
+ private RepositorySourceListener listener1;
+ @Mock
+ private RepositorySourceListener listener2;
+ @Mock
+ private FederatedSource source1;
+ @Mock
+ private FederatedSource source2;
+
+ // private RepositoryConnectionPool connectionPool;
+
+ @Before
+ public void beforeEach() throws Exception {
+ MockitoAnnotations.initMocks(this);
+ name = "Test repository";
+ repository = new FederatedRepository(service, name);
+ stub(source1.getName()).toReturn("soure 1");
+ stub(source2.getName()).toReturn("soure 2");
+ }
+
+ @Test
+ public void shouldHaveNamePassedIntoConstructor() {
+ assertThat(repository.getName(), is(name));
+ }
+
+ @Test
+ public void shouldHaveFederationServicePassedIntoConstructor() {
+ assertThat(repository.getService(), is(sameInstance(service)));
+ }
+
+ @Test
+ public void shouldHaveAdministrator() {
+ assertThat(repository.getAdministrator(), is(notNullValue()));
+ }
+
+ @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 shouldHaveNoSourcesAfterInitialization() {
+ assertThat(repository.getSources(), is(notNullValue()));
+ assertThat(repository.getSources().isEmpty(), is(true));
+ }
+
+ @Test
+ public void shouldAddSourceThatIsNotAlreadyRegistered() {
+ assertThat(repository.getSources(), hasItems(new FederatedSource[] {}));
+ assertThat(repository.addSource(source1), is(true));
+ assertThat(repository.getSources(), hasItems(source1));
+ assertThat(repository.addSource(source2), is(true));
+ assertThat(repository.getSources(), hasItems(source1, source2));
+ }
+
+ @Test
+ public void shouldNotAddSourceThatIsAlreadyRegistered() {
+ String source1Name = source1.getName();
+ FederatedSource source1a = mock(FederatedSource.class);
+ stub(source1a.getName()).toReturn(source1Name);
+
+ assertThat(repository.getSources(), hasItems(new FederatedSource[] {}));
+ assertThat(repository.addSource(source1), is(true));
+ assertThat(repository.getSources(), hasItems(source1));
+ assertThat(repository.addSource(source2), is(true));
+ assertThat(repository.getSources(), hasItems(source1, source2));
+ assertThat(repository.addSource(source1a), is(false));
+ assertThat(repository.getSources(), hasItems(source1, source2));
+ }
+
+ @Test
+ public void shouldShutdownAndRemoveRepositoryFromFederationService() {
+ repository.getAdministrator().shutdown();
+ verify(service, times(1)).removeRepository(repository);
+ }
+
+ @Test
+ public void shouldShutdownAllSourceConnectionPoolsWhenShuttingDownRepository() throws
Exception {
+ // Create the source instances that wait during termination ...
+ TimeDelayingRepositorySource timeDelaySource1 = new
TimeDelayingRepositorySource("time delay source 1");
+ source1 = new FederatedSource(timeDelaySource1);
+ TimeDelayingRepositorySource timeDelaySource2 = new
TimeDelayingRepositorySource("time delay source 2");
+ source2 = new FederatedSource(timeDelaySource2);
+ repository.addSource(source1);
+ repository.addSource(source2);
+ assertThat(repository.getSources(), hasItems(source1, source2));
+
+ // Get a connection from one source ...
+ RepositoryConnection connection = source2.getConnection();
+ assertThat(connection, is(notNullValue()));
+
+ // Shut down the repository, which will shut down each of the sources ...
+ repository.getAdministrator().shutdown();
+ assertThat(repository.getAdministrator().isShutdown(), is(true));
+ assertThat(repository.getAdministrator().isTerminated(), is(false));
+
+ // Source 1 should be shut down AND terminated ...
+ assertThat(source1.getConnectionPool().isShutdown(), is(true));
+ assertThat(source1.getConnectionPool().isTerminated(), is(true));
+
+ // Source 2 should be shutdown but not terminated, since we still have a
connection ...
+ assertThat(source2.getConnectionPool().isShutdown(), is(true));
+ assertThat(source2.getConnectionPool().isTerminated(), is(false));
+
+ // Close the connection ...
+ connection.close();
+ assertThat(repository.getAdministrator().awaitTermination(1, TimeUnit.SECONDS),
is(true));
+ assertThat(repository.getAdministrator().isShutdown(), is(true));
+ assertThat(repository.getAdministrator().isTerminated(), is(true));
+ }
+}
Property changes on:
trunk/dna-repository/src/test/java/org/jboss/dna/repository/federation/FederatedRepositoryTest.java
___________________________________________________________________
Name: svn:mime-type
+ text/plain
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-06-10
20:18:05 UTC (rev 252)
+++
trunk/dna-repository/src/test/java/org/jboss/dna/repository/sequencers/SequencingServiceTest.java 2008-06-10
20:19:15 UTC (rev 253)
@@ -141,7 +141,8 @@
assertThat(sequencingService.getAdministrator().shutdown().isShutdown(),
is(true));
assertThat(sequencingService.getAdministrator().isPaused(), is(false));
assertThat(sequencingService.getAdministrator().isStarted(), is(false));
- assertThat(sequencingService.getAdministrator().getState(),
is(ServiceAdministrator.State.SHUTDOWN));
+ ServiceAdministrator.State actualState =
sequencingService.getAdministrator().getState();
+ assertThat(actualState == ServiceAdministrator.State.SHUTDOWN || actualState
== ServiceAdministrator.State.TERMINATED, is(true));
}
}
@@ -170,7 +171,8 @@
assertThat(sequencingService.getAdministrator().shutdown().isShutdown(),
is(true));
assertThat(sequencingService.getAdministrator().isPaused(), is(false));
assertThat(sequencingService.getAdministrator().isStarted(), is(false));
- assertThat(sequencingService.getAdministrator().getState(),
is(ServiceAdministrator.State.SHUTDOWN));
+ ServiceAdministrator.State actualState =
sequencingService.getAdministrator().getState();
+ assertThat(actualState == ServiceAdministrator.State.SHUTDOWN || actualState ==
ServiceAdministrator.State.TERMINATED, is(true));
// Now start it back up ... this will fail
sequencingService.getAdministrator().start();
Modified:
trunk/dna-repository/src/test/java/org/jboss/dna/repository/util/JndiSessionFactoryTest.java
===================================================================
---
trunk/dna-repository/src/test/java/org/jboss/dna/repository/util/JndiSessionFactoryTest.java 2008-06-10
20:18:05 UTC (rev 252)
+++
trunk/dna-repository/src/test/java/org/jboss/dna/repository/util/JndiSessionFactoryTest.java 2008-06-10
20:19:15 UTC (rev 253)
@@ -27,6 +27,7 @@
import static org.hamcrest.core.IsSame.sameInstance;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.fail;
+import static org.mockito.Mockito.mock;
import javax.jcr.Repository;
import javax.jcr.Session;
import javax.naming.InitialContext;
@@ -34,8 +35,6 @@
import org.jboss.dna.common.SystemFailureException;
import org.jboss.dna.common.jcr.AbstractJcrRepositoryTest;
import org.jboss.dna.common.naming.MockInitialContext;
-import org.jboss.dna.repository.util.JndiSessionFactory;
-import org.jmock.Mockery;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
@@ -49,14 +48,12 @@
public static final String MOCK_REPOSITORY_NAME_ALT =
"java:jcr/unit/test/repository/2";
private JndiSessionFactory factory;
- private Mockery context;
private Repository mockRepository;
private Session session;
@Before
public void beforeEach() throws Exception {
- this.context = new Mockery();
- this.mockRepository = this.context.mock(Repository.class);
+ this.mockRepository = mock(Repository.class);
MockInitialContext.register(MOCK_REPOSITORY_NAME, this.mockRepository);
this.factory = new JndiSessionFactory();
}
Modified: trunk/dna-repository/src/test/resources/log4j.properties
===================================================================
--- trunk/dna-repository/src/test/resources/log4j.properties 2008-06-10 20:18:05 UTC (rev
252)
+++ trunk/dna-repository/src/test/resources/log4j.properties 2008-06-10 20:19:15 UTC (rev
253)
@@ -9,7 +9,9 @@
# Set up the default logging to be INFO level, then override specific units
log4j.logger.org.jboss.dna=INFO
-log4j.logger.org.jboss.dna.repository.sequencers=TRACE
+#log4j.logger.org.jboss.dna.repository.sequencers=TRACE
+#log4j.logger.org.jboss.dna.repository.federation=DEBUG
+#log4j.logger.org.jboss.dna.spi=DEBUG
# Jackrabbit logging
log4j.logger.org.apache.jackrabbit=WARN, stdout
Modified: trunk/dna-spi/pom.xml
===================================================================
--- trunk/dna-spi/pom.xml 2008-06-10 20:18:05 UTC (rev 252)
+++ trunk/dna-spi/pom.xml 2008-06-10 20:19:15 UTC (rev 253)
@@ -44,15 +44,10 @@
<scope>test</scope>
</dependency>
<dependency>
- <groupId>org.jmock</groupId>
- <artifactId>jmock</artifactId>
+ <groupId>org.mockito</groupId>
+ <artifactId>mockito-all</artifactId>
<scope>test</scope>
</dependency>
- <dependency>
- <groupId>org.jmock</groupId>
- <artifactId>jmock-junit4</artifactId>
- <scope>test</scope>
- </dependency>
<!--
Logging (require SLF4J API for compiling, but use Log4J and its SLF4J binding for
testing)
-->
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-06-10
20:18:05 UTC (rev 252)
+++
trunk/dna-spi/src/main/java/org/jboss/dna/spi/graph/connection/RepositoryConnectionPool.java 2008-06-10
20:19:15 UTC (rev 253)
@@ -21,14 +21,11 @@
*/
package org.jboss.dna.spi.graph.connection;
-import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.LinkedList;
-import java.util.List;
import java.util.Set;
import java.util.concurrent.BlockingQueue;
-import java.util.concurrent.Callable;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
@@ -40,7 +37,6 @@
import net.jcip.annotations.GuardedBy;
import net.jcip.annotations.ThreadSafe;
import org.jboss.dna.common.util.ArgCheck;
-import org.jboss.dna.common.util.LogContext;
import org.jboss.dna.common.util.Logger;
import org.jboss.dna.spi.SpiI18n;
import org.jboss.dna.spi.cache.CachePolicy;
@@ -405,104 +401,6 @@
}
// -------------------------------------------------
- // Utility methods ...
- // -------------------------------------------------
-
- /**
- * Call the supplied operation, using a connection from this pool.
- *
- * @param <T> the return type for the operation
- * @param operation the operation to be run using a connection in this pool
- * @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 #callable(RepositoryOperation)
- * @see #callables(Iterable)
- * @see #callables(RepositoryOperation...)
- */
- public <T> T call( RepositoryOperation<T> operation ) throws
RepositorySourceException, InterruptedException {
- ArgCheck.isNotNull(operation, "repository operation");
- // Get a connection ...
- T result = null;
- LogContext.set("context", operation.getName());
- RepositoryConnection conn = this.getConnection();
- try {
- // And run the client with the connection ...
- result = operation.run(conn);
- } finally {
- conn.close();
- }
- LogContext.clear();
- return result;
- }
-
- /**
- * Return a callable object that, when run, performs the supplied repository
operation against a connection in this pool.
- *
- * @param <T> the return type for the operation
- * @param operation the operation to be run using a connection in this pool
- * @return the callable
- * @see #call(RepositoryOperation)
- * @see #callables(Iterable)
- * @see #callables(RepositoryOperation...)
- */
- public <T> Callable<T> callable( final RepositoryOperation<T>
operation ) {
- ArgCheck.isNotNull(operation, "repository operation");
- final RepositoryConnectionPool pool = this;
- return new Callable<T>() {
-
- /**
- * Execute by getting a connection from this pool, running the client, and
return the connection to the pool.
- *
- * @return the operation's result
- * @throws Exception
- */
- public T call() throws Exception {
- return pool.call(operation);
- }
- };
- }
-
- /**
- * Return a collection of callable objects that, when run, perform the supplied
repository operations against connections in
- * this pool.
- *
- * @param <T> the return type for the operations
- * @param operations the operations to be run using connection from this pool
- * @return the collection of callables
- * @see #call(RepositoryOperation)
- * @see #callable(RepositoryOperation)
- * @see #callables(Iterable)
- */
- public <T> List<Callable<T>> callables(
RepositoryOperation<T>... operations ) {
- List<Callable<T>> callables = new
ArrayList<Callable<T>>();
- for (final RepositoryOperation<T> operation : operations) {
- callables.add(callable(operation));
- }
- return callables;
- }
-
- /**
- * Return a collection of callable objects that, when run, perform the supplied
repository operations against connections in
- * this pool.
- *
- * @param <T> the return type for the operations
- * @param operations the operations to be run using connection from this pool
- * @return the collection of callables
- * @see #call(RepositoryOperation)
- * @see #callable(RepositoryOperation)
- * @see #callables(RepositoryOperation...)
- */
- public <T> List<Callable<T>> callables(
Iterable<RepositoryOperation<T>> operations ) {
- List<Callable<T>> callables = new
ArrayList<Callable<T>>();
- for (final RepositoryOperation<T> operation : operations) {
- callables.add(callable(operation));
- }
- return callables;
- }
-
- // -------------------------------------------------
// State management methods ...
// -------------------------------------------------
@@ -956,7 +854,7 @@
@GuardedBy( "mainLock" )
protected int drainUnusedConnections( int count ) {
if (count <= 0) return 0;
- this.logger.trace("Draining up to {} unused repository connections to
{0}", count, getName());
+ 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);
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-06-10
20:18:05 UTC (rev 252)
+++
trunk/dna-spi/src/main/java/org/jboss/dna/spi/graph/connection/RepositoryOperation.java 2008-06-10
20:19:15 UTC (rev 253)
@@ -22,18 +22,43 @@
package org.jboss.dna.spi.graph.connection;
/**
+ * An operation that runs against a repository connection.
+ *
* @author Randall Hauch
* @param <T> the type of result returned by the client
*/
public interface RepositoryOperation<T> {
+ /**
+ * Get the name of this operation.
+ *
+ * @return the operation's name
+ */
String getName();
+ /**
+ * Run the operation using the supplied connection.
+ *
+ * @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( RepositoryConnection connection ) throws RepositorySourceException,
InterruptedException;
+ /**
+ * A factory interface for creating repository operations.
+ *
+ * @param <T> the type of result for the operations
+ * @author Randall Hauch
+ */
public static interface Factory<T> {
+ /**
+ * Create a repository operation that returns the result of type T.
+ *
+ * @return the operation
+ */
RepositoryOperation<T> create();
}
-
}
Added:
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
(rev 0)
+++
trunk/dna-spi/src/main/java/org/jboss/dna/spi/graph/connection/RepositoryOperations.java 2008-06-10
20:19:15 UTC (rev 253)
@@ -0,0 +1,155 @@
+/*
+ * 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.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.concurrent.Callable;
+import org.jboss.dna.common.util.ArgCheck;
+import org.jboss.dna.common.util.LogContext;
+
+/**
+ * @author Randall Hauch
+ */
+public class RepositoryOperations {
+
+ /**
+ * Call the supplied operation, using a connection from this pool.
+ *
+ * @param <T> the return type for the operation
+ * @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(RepositoryConnectionFactory, RepositoryOperation)
+ * @see #createCallables(RepositoryConnectionFactory, Iterable)
+ * @see #createCallables(RepositoryConnectionFactory, RepositoryOperation...)
+ */
+ public static <T> T call( RepositoryConnectionFactory connectionFactory,
RepositoryOperation<T> operation ) throws RepositorySourceException,
InterruptedException {
+ ArgCheck.isNotNull(operation, "repository operation");
+ // Get a connection ...
+ T result = null;
+ LogContext.set("context", operation.getName());
+ RepositoryConnection conn = connectionFactory.getConnection();
+ try {
+ // And run the client with the connection ...
+ result = operation.run(conn);
+ } finally {
+ conn.close();
+ }
+ LogContext.clear();
+ return result;
+ }
+
+ /**
+ * Return a callable object that, when run, performs the supplied repository
operation against a connection obtained from the
+ * supplied factory.
+ *
+ * @param <T> the return type for the operation
+ * @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(RepositoryConnectionFactory, RepositoryOperation)
+ * @see #createCallables(RepositoryConnectionFactory, Iterable)
+ * @see #createCallables(RepositoryConnectionFactory, RepositoryOperation...)
+ */
+ public static <T> Callable<T> createCallable( final
RepositoryConnectionFactory connectionFactory, final RepositoryOperation<T>
operation ) {
+ ArgCheck.isNotNull(operation, "repository operation");
+ return new Callable<T>() {
+
+ /**
+ * Execute by getting a connection from this pool, running the client, and
return the connection to the pool.
+ *
+ * @return the operation's result
+ * @throws Exception
+ */
+ public T call() throws Exception {
+ return RepositoryOperations.call(connectionFactory, operation);
+ }
+ };
+ }
+
+ /**
+ * Return a collection of callable objects that, when run, perform the supplied
repository operations against connections in
+ * this pool.
+ *
+ * @param <T> the return type for the operations
+ * @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(RepositoryConnectionFactory, RepositoryOperation)
+ * @see #createCallable(RepositoryConnectionFactory, RepositoryOperation)
+ * @see #createCallables(RepositoryConnectionFactory, Iterable)
+ */
+ public static <T> List<Callable<T>> createCallables( final
RepositoryConnectionFactory connectionFactory, final RepositoryOperation<T>...
operations ) {
+ List<Callable<T>> callables = new
ArrayList<Callable<T>>();
+ for (final RepositoryOperation<T> operation : operations) {
+ callables.add(createCallable(connectionFactory, operation));
+ }
+ return callables;
+ }
+
+ /**
+ * Return a collection of callable objects that, when run, perform the supplied
repository operations against connections in
+ * this pool.
+ *
+ * @param <T> the return type for the operations
+ * @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(RepositoryConnectionFactory, RepositoryOperation)
+ * @see #createCallable(RepositoryConnectionFactory, RepositoryOperation)
+ * @see #createCallables(RepositoryConnectionFactory, RepositoryOperation...)
+ */
+ public static <T> List<Callable<T>> createCallables( final
RepositoryConnectionFactory connectionFactory,
Iterable<RepositoryOperation<T>> operations ) {
+ List<Callable<T>> callables = new
ArrayList<Callable<T>>();
+ for (final RepositoryOperation<T> operation : operations) {
+ callables.add(createCallable(connectionFactory, operation));
+ }
+ return callables;
+ }
+
+ /**
+ * Return a collection of callable objects that, when run, perform the supplied
repository operations against connections in
+ * this pool.
+ *
+ * @param <T> the return type for the operations
+ * @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(RepositoryConnectionFactory, RepositoryOperation)
+ * @see #createCallable(RepositoryConnectionFactory, RepositoryOperation)
+ * @see #createCallables(RepositoryConnectionFactory, RepositoryOperation...)
+ */
+ public static <T> List<Callable<T>> createCallables( 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(connectionFactory, operation));
+ }
+ return callables;
+ }
+
+}
Property changes on:
trunk/dna-spi/src/main/java/org/jboss/dna/spi/graph/connection/RepositoryOperations.java
___________________________________________________________________
Name: svn:mime-type
+ text/plain
Deleted:
trunk/dna-spi/src/test/java/org/jboss/dna/spi/graph/connection/MockRepositorySource.java
===================================================================
---
trunk/dna-spi/src/test/java/org/jboss/dna/spi/graph/connection/MockRepositorySource.java 2008-06-10
20:18:05 UTC (rev 252)
+++
trunk/dna-spi/src/test/java/org/jboss/dna/spi/graph/connection/MockRepositorySource.java 2008-06-10
20:19:15 UTC (rev 253)
@@ -1,238 +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.Set;
-import java.util.concurrent.CopyOnWriteArraySet;
-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.atomic.AtomicReference;
-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.commands.GraphCommand;
-import org.jmock.Mockery;
-
-/**
- * @author Randall Hauch
- */
-@ThreadSafe
-public class MockRepositorySource implements RepositorySource {
-
- private final String identifier;
- private final AtomicInteger retryLimit = new AtomicInteger(0);
- private final Mockery context;
- private final AtomicInteger connectionsOpenedCount = new AtomicInteger(0);
- private final AtomicInteger connectionsClosedCount = new AtomicInteger(0);
- private final Set<Connection> openConnections = new
CopyOnWriteArraySet<Connection>();
- private CachePolicy defaultCachePolicy;
-
- public MockRepositorySource( String identifier, Mockery context ) {
- this.identifier = identifier;
- this.context = context;
- }
-
- /**
- * {@inheritDoc}
- */
- public String getName() {
- return this.identifier;
- }
-
- /**
- * {@inheritDoc}
- */
- public int getRetryLimit() {
- return this.retryLimit.get();
- }
-
- /**
- * {@inheritDoc}
- */
- public void setRetryLimit( int limit ) {
- this.retryLimit.set(limit);
- }
-
- public CachePolicy getDefaultCachePolicy() {
- return defaultCachePolicy;
- }
-
- public void setDefaultCachePolicy( CachePolicy defaultCachePolicy ) {
- this.defaultCachePolicy = defaultCachePolicy;
- }
-
- /**
- * {@inheritDoc}
- */
- public RepositoryConnection getConnection() throws RepositorySourceException {
- int connectionNumber = this.connectionsOpenedCount.incrementAndGet();
- String connectionName = "Connection " + connectionNumber;
- XAResource xaResource = context != null ? context.mock(XAResource.class,
connectionName) : null;
- Connection c = newConnection(connectionName, xaResource);
- this.openConnections.add(c);
- return c;
- }
-
- protected Connection newConnection( String connectionName, XAResource xaResource )
throws RepositorySourceException {
- Connection c = new Connection(connectionName);
- c.setXaResource(xaResource);
- return c;
- }
-
- protected void close( Connection conn ) {
- if (conn != null && this.openConnections.remove(conn)) {
- this.connectionsClosedCount.incrementAndGet();
- }
- }
-
- public int getOpenConnectionCount() {
- return this.openConnections.size();
- }
-
- public int getTotalConnectionsCreated() {
- return this.connectionsOpenedCount.get();
- }
-
- public int getTotalConnectionsClosed() {
- return this.connectionsClosedCount.get();
- }
-
- /**
- * {@inheritDoc}
- */
- public Reference getReference() {
- throw new UnsupportedOperationException();
- }
-
- public class Connection implements RepositoryConnection {
-
- private final String connectionName;
- private final AtomicBoolean closed = new AtomicBoolean(false);
- private final AtomicBoolean loadResponse = new AtomicBoolean(true);
- private final AtomicBoolean pingResponse = new AtomicBoolean(true);
- private final AtomicLong closeCount = new AtomicLong(0);
- private final AtomicLong loadCount = new AtomicLong(0);
- private final AtomicLong loadDelay = new AtomicLong(0);
- private final AtomicLong pingCount = new AtomicLong(0);
- private final AtomicLong pingDelay = new AtomicLong(0);
- private final AtomicReference<XAResource> xaResource = new
AtomicReference<XAResource>();
-
- protected Connection( String connectionName ) {
- assert connectionName != null && connectionName.trim().length() !=
0;
- this.connectionName = connectionName;
- }
-
- public String getConnectionName() {
- return this.connectionName;
- }
-
- /**
- * {@inheritDoc}
- */
- public void close() {
- this.closeCount.incrementAndGet();
- this.closed.set(true);
- MockRepositorySource.this.close(this);
- }
-
- /**
- * {@inheritDoc}
- */
- public String getSourceName() {
- return MockRepositorySource.this.getName();
- }
-
- /**
- * {@inheritDoc}
- */
- public CachePolicy getDefaultCachePolicy() {
- return MockRepositorySource.this.getDefaultCachePolicy();
- }
-
- /**
- * {@inheritDoc}
- */
- public XAResource getXAResource() {
- return this.xaResource.get();
- }
-
- public void setXaResource( XAResource xaResource ) {
- this.xaResource.set(xaResource);
- }
-
- /**
- * {@inheritDoc}
- */
- public void execute( ExecutionEnvironment env, GraphCommand... commands ) throws
RepositorySourceException, InterruptedException {
- long delay = this.loadDelay.get();
- if (delay > 0l) Thread.sleep(delay);
- this.loadCount.incrementAndGet();
- }
-
- public void setLoadResponse( boolean response ) {
- this.loadResponse.set(response);
- }
-
- public void setLoadDelay( long time, TimeUnit unit ) {
- this.loadDelay.set(unit.toMillis(time));
- }
-
- /**
- * {@inheritDoc}
- */
- public boolean ping( long time, TimeUnit unit ) throws InterruptedException {
- Thread.sleep(this.pingDelay.get());
- return this.pingResponse.get();
- }
-
- public void setPingResponse( boolean pingResponse ) {
- this.pingResponse.set(pingResponse);
- }
-
- public void setPingDelay( long time, TimeUnit unit ) {
- this.pingDelay.set(unit.toMillis(time));
- }
-
- public long getPingCount() {
- return this.pingCount.get();
- }
-
- public long getLoadCount() {
- return this.loadCount.get();
- }
-
- public long getCloseCount() {
- return this.closeCount.get();
- }
-
- /**
- * {@inheritDoc}
- */
- public void setListener( RepositorySourceListener listener ) {
- }
-
- }
-
-}
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-06-10
20:18:05 UTC (rev 252)
+++
trunk/dna-spi/src/test/java/org/jboss/dna/spi/graph/connection/RepositoryConnectionPoolTest.java 2008-06-10
20:19:15 UTC (rev 253)
@@ -23,11 +23,11 @@
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 static
org.jboss.dna.spi.graph.connection.RepositorySourceLoadHarness.runLoadTest;
import java.util.List;
+import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
-import org.jmock.Mockery;
import org.junit.After;
import org.junit.Before;
import org.junit.Ignore;
@@ -39,14 +39,12 @@
public class RepositoryConnectionPoolTest {
private RepositoryConnectionPool pool;
- private MockRepositorySource repositorySource;
+ private TimeDelayingRepositorySource repositorySource;
private ExecutionEnvironment env;
- private Mockery context;
@Before
public void beforeEach() throws Exception {
- this.context = new Mockery();
- this.repositorySource = new MockRepositorySource("source 1",
this.context);
+ this.repositorySource = new TimeDelayingRepositorySource("source 1");
this.pool = new RepositoryConnectionPool(this.repositorySource, 1, 1, 100,
TimeUnit.SECONDS);
this.env = null;
}
@@ -160,24 +158,39 @@
public void shouldBlockClientsWhenNotEnoughConnections() throws Exception {
int numConnectionsInPool = 1;
int numClients = 2;
- RepositoryOperation.Factory<Integer> operationFactory =
RepositoryTestOperations.createMultipleLoadOperationFactory(env, 10);
- runLoadTest(repositorySource, numConnectionsInPool, numClients, 4,
TimeUnit.SECONDS, operationFactory);
+ RepositoryConnectionPool pool = new RepositoryConnectionPool(repositorySource);
+ pool.setCorePoolSize(numConnectionsInPool);
+ pool.setMaximumPoolSize(numConnectionsInPool);
+ RepositoryOperation.Factory<Integer> operationFactory =
RepositorySourceLoadHarness.createMultipleLoadOperationFactory(env, 10);
+ runLoadTest(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;
- RepositoryOperation.Factory<Integer> operationFactory =
RepositoryTestOperations.createMultipleLoadOperationFactory(env, 10);
- runLoadTest(repositorySource, numConnectionsInPool, numClients, 4,
TimeUnit.SECONDS, operationFactory);
+ RepositoryConnectionPool pool = new RepositoryConnectionPool(repositorySource);
+ pool.setCorePoolSize(numConnectionsInPool);
+ pool.setMaximumPoolSize(numConnectionsInPool);
+ RepositoryOperation.Factory<Integer> operationFactory =
RepositorySourceLoadHarness.createMultipleLoadOperationFactory(env, 10);
+ runLoadTest(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;
- RepositoryOperation.Factory<Integer> operationFactory =
RepositoryTestOperations.createMultipleLoadOperationFactory(env, 10);
- runLoadTest(repositorySource, numConnectionsInPool, numClients, 4,
TimeUnit.SECONDS, operationFactory);
+ RepositoryConnectionPool pool = new RepositoryConnectionPool(repositorySource);
+ pool.setCorePoolSize(numConnectionsInPool);
+ pool.setMaximumPoolSize(numConnectionsInPool);
+ RepositoryOperation.Factory<Integer> operationFactory =
RepositorySourceLoadHarness.createMultipleLoadOperationFactory(env, 10);
+ runLoadTest(pool, numClients, 100, TimeUnit.MILLISECONDS, operationFactory);
+ pool.shutdown();
+ pool.awaitTermination(4, TimeUnit.SECONDS);
}
@Ignore( "doesn't run on hudson" )
@@ -185,13 +198,19 @@
public void shouldClientsToRunConncurrentlyWithMultipleConnectionInPool() throws
Exception {
int numConnectionsInPool = 10;
int numClients = 50;
- RepositoryOperation.Factory<Integer> operationFactory =
RepositoryTestOperations.createMultipleLoadOperationFactory(env, 20);
- List<Integer> results = runLoadTest(repositorySource, numConnectionsInPool,
numClients, 10, TimeUnit.SECONDS, operationFactory);
+ RepositoryConnectionPool pool = new RepositoryConnectionPool(repositorySource);
+ pool.setCorePoolSize(numConnectionsInPool);
+ pool.setMaximumPoolSize(numConnectionsInPool);
+ RepositoryOperation.Factory<Integer> operationFactory =
RepositorySourceLoadHarness.createMultipleLoadOperationFactory(env, 20);
+ List<Future<Integer>> results = runLoadTest(pool, numClients, 200,
TimeUnit.MILLISECONDS, operationFactory);
int total = 0;
- for (Integer integer : results) {
- if (integer != null) total += integer;
+ 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);
}
}
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-06-10
20:18:05 UTC (rev 252)
+++
trunk/dna-spi/src/test/java/org/jboss/dna/spi/graph/connection/RepositorySourceLoadHarness.java 2008-06-10
20:19:15 UTC (rev 253)
@@ -26,7 +26,6 @@
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.CountDownLatch;
-import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
@@ -37,12 +36,21 @@
/**
* A test harness for using repository connections under load.
+ *
* @author Randall Hauch
*/
public class RepositorySourceLoadHarness {
- public static <T> List<T> runLoadTest( RepositoryConnectionFactory
connectionFactory, int numConnectionsInPool, int numClients, long maxTime, TimeUnit
maxTimeUnit,
- RepositoryOperation.Factory<T>
clientFactory ) throws InterruptedException, ExecutionException {
+ public static Future<Integer> execute( RepositoryConnectionFactory
connectionFactory, ExecutionEnvironment env, long maxTime, TimeUnit maxTimeUnit ) throws
InterruptedException {
+ int numTimes = 1;
+ int numClients = 1;
+ RepositoryOperation.Factory<Integer> operationFactory =
RepositorySourceLoadHarness.createMultipleLoadOperationFactory(env, numTimes);
+ List<Future<Integer>> results = runLoadTest(connectionFactory,
numClients, maxTime, maxTimeUnit, operationFactory);
+ return results.get(0);
+ }
+
+ public static <T> List<Future<T>> runLoadTest(
RepositoryConnectionFactory connectionFactory, int numClients, long maxTime, TimeUnit
maxTimeUnit, RepositoryOperation.Factory<T> clientFactory )
+ throws InterruptedException {
// Create the clients ...
Collection<RepositoryOperation<T>> clients = new
ArrayList<RepositoryOperation<T>>();
for (int i = 0; i != numClients; ++i) {
@@ -50,71 +58,47 @@
}
// and run the test ...
- return runLoadTest(connectionFactory, numConnectionsInPool, maxTime, maxTimeUnit,
clients);
+ return runLoadTest(connectionFactory, maxTime, maxTimeUnit, clients);
}
- public static <T> List<T> runLoadTest( RepositoryConnectionFactory
connectionFactory, int numConnectionsInPool, long maxTime, TimeUnit maxTimeUnit,
RepositoryOperation<T>... clients )
- throws InterruptedException, ExecutionException {
+ public static <T> List<Future<T>> runLoadTest(
RepositoryConnectionFactory connectionFactory, long maxTime, TimeUnit maxTimeUnit,
RepositoryOperation<T>... clients ) throws InterruptedException {
// Create the client collection ...
Collection<RepositoryOperation<T>> clientCollection = new
ArrayList<RepositoryOperation<T>>();
for (RepositoryOperation<T> client : clients) {
if (client != null) clientCollection.add(client);
}
// and run the test ...
- return runLoadTest(connectionFactory, numConnectionsInPool, maxTime, maxTimeUnit,
clientCollection);
+ return runLoadTest(connectionFactory, maxTime, maxTimeUnit, clientCollection);
}
- public static <T> List<T> runLoadTest( RepositoryConnectionFactory
connectionFactory, int numConnectionsInPool, long maxTime, TimeUnit maxTimeUnit,
Collection<RepositoryOperation<T>> clients )
- throws InterruptedException, ExecutionException {
+ public static <T> List<Future<T>> runLoadTest(
RepositoryConnectionFactory connectionFactory, long maxTime, TimeUnit maxTimeUnit,
Collection<RepositoryOperation<T>> clients )
+ throws InterruptedException {
assert connectionFactory != null;
- assert numConnectionsInPool > 0;
assert clients != null;
assert clients.size() > 0;
- // Create a connection pool ...
- final RepositoryConnectionPool connectionPool = new
RepositoryConnectionPool(connectionFactory, numConnectionsInPool, numConnectionsInPool,
10, TimeUnit.SECONDS);
-
// Create an Executor Service, using a thread factory that makes the first
'n' thread all wait for each other ...
- final ThreadFactory threadFactory = new TestThreadFactory(clients.size(),
connectionPool);
- final ExecutorService clientPool = Executors.newFixedThreadPool(clients.size(),
threadFactory);
+ ExecutorService clientPool = null;
+ if (clients.size() == 1) {
+ clientPool = Executors.newSingleThreadExecutor();
+ } else {
+ final ThreadFactory threadFactory = new TestThreadFactory(clients.size());
+ clientPool = Executors.newFixedThreadPool(clients.size(), threadFactory);
+ }
try {
// Wrap each client by a callable and by another that uses a latch ...
- List<Callable<T>> callables = connectionPool.callables(clients);
+ List<Callable<T>> callables =
RepositoryOperations.createCallables(connectionFactory, clients);
// Run the tests ...
List<Future<T>> futures = clientPool.invokeAll(callables,
maxTime, maxTimeUnit);
-
- // Whether or not all clients completed, process the results ...
- List<T> results = new ArrayList<T>();
- for (Future<T> future : futures) {
- if (future.isDone() && !future.isCancelled()) {
- // Record the results ...
- results.add(future.get());
- } else {
- // Record the results as null
- results.add(null);
- // Cancell any operation that is not completed
- future.cancel(true);
- }
- }
- // Return the results ...
- return results;
+ return futures;
} finally {
- try {
- // Shut down the pool of clients ...
- clientPool.shutdown();
- if (!clientPool.awaitTermination(5, TimeUnit.SECONDS)) {
- String msg = "Unable to shutdown clients after 5 seconds";
-
Logger.getLogger(RepositorySourceLoadHarness.class).error(MockI18n.passthrough, msg);
- }
- } finally {
- // Shut down the connections ...
- connectionPool.shutdown();
- if (!connectionPool.awaitTermination(5, TimeUnit.SECONDS)) {
- String msg = "Unable to shutdown connections after 5
seconds";
-
Logger.getLogger(RepositorySourceLoadHarness.class).error(MockI18n.passthrough, msg);
- }
+ // Shut down the pool of clients ...
+ clientPool.shutdown();
+ if (!clientPool.awaitTermination(5, TimeUnit.SECONDS)) {
+ String msg = "Unable to shutdown clients after 5 seconds";
+
Logger.getLogger(RepositorySourceLoadHarness.class).error(MockI18n.passthrough, msg);
}
}
@@ -123,16 +107,17 @@
/**
* A thread factory that makes an initial set of threads wait until all of those
threads are created and ready. This is useful
* in testing to ensure that the first threads created don't get a jump start.
+ *
* @author Randall Hauch
*/
protected static class TestThreadFactory implements ThreadFactory {
+ protected final int totalNumberOfThreads;
protected final CountDownLatch latch;
- protected final RepositoryConnectionPool pool;
- public TestThreadFactory( int numberOfThreadsToWait, RepositoryConnectionPool
pool ) {
+ public TestThreadFactory( int numberOfThreadsToWait ) {
this.latch = new CountDownLatch(numberOfThreadsToWait);
- this.pool = pool;
+ this.totalNumberOfThreads = numberOfThreadsToWait;
}
/**
@@ -146,20 +131,95 @@
*/
@Override
public void run() {
- try {
- // Count down the thread count (if 0, this doesn't do
anything)
- latch.countDown();
- // Wait for all threads to reach this point ...
- latch.await();
- } catch (InterruptedException e) {
- throw new RuntimeException(e);
+ if (totalNumberOfThreads > 1) {
+ // There are other threads, and we want to synchronize with them
...
+ try {
+ // Count down the number of threads that are to reach this
point (if 0, this doesn't do anything)
+ latch.countDown();
+ // Wait for all threads to reach this point ...
+ latch.await();
+ } catch (InterruptedException e) {
+ throw new RuntimeException(e);
+ }
}
- // Check that the number of connections-in-use is smaller than the
maximum pool size
- if (pool != null) assert pool.getInUseCount() <=
pool.getMaximumPoolSize();
super.run();
}
};
}
}
+ /**
+ * 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
+ * number of times, intermixed with random math operations and {@link Thread#yield()
yielding}.
+ *
+ * @param env the environment
+ * @param callsPerOperation the number of <code>load</code> calls per
RepositoryOperation
+ * @return the factory
+ */
+ public static RepositoryOperation.Factory<Integer>
createMultipleLoadOperationFactory( final ExecutionEnvironment env, final int
callsPerOperation ) {
+ return new RepositoryOperation.Factory<Integer>() {
+
+ public RepositoryOperation<Integer> create() {
+ return new CallLoadMultipleTimes(env, callsPerOperation);
+ }
+ };
+ }
+
+ public static class CallLoadMultipleTimes implements
RepositoryOperation<Integer> {
+
+ private final int count;
+ private final ExecutionEnvironment env;
+
+ public CallLoadMultipleTimes( ExecutionEnvironment env, int count ) {
+ Logger.getLogger(RepositorySourceLoadHarness.class).debug("Creating
repository operation to call {0} times", count);
+ this.count = count;
+ this.env = env;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public String getName() {
+ return Thread.currentThread().getName() +
"-CallLoadMultipleTimes";
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public Integer run( RepositoryConnection connection ) throws
RepositorySourceException, InterruptedException {
+ Logger.getLogger(RepositorySourceLoadHarness.class).debug("Running {0}
operation", this.getClass().getSimpleName());
+ int total = count;
+ for (int i = 0; i != count; ++i) {
+ // Add two random numbers ...
+ int int1 = random(this.hashCode() ^ (int)System.nanoTime() * i);
+ if (i % 2 == 0) {
+ Thread.yield();
+ }
+ connection.execute(env);
+ int int2 = random(this.hashCode() ^ (int)System.nanoTime() + i);
+ total += Math.min(Math.abs(Math.max(int1, int2) + int1 * int2 / 3),
count);
+ }
+ Logger.getLogger(RepositorySourceLoadHarness.class).debug("Finishing {0}
operation", this.getClass().getSimpleName());
+ return total < count ? total : count; // should really always return
count
+ }
+ }
+
+ /**
+ * A "random-enough" number generator that is cheap and that has no
synchronization issues (like some other random number
+ * generators).
+ * <p>
+ * This was taken from <a href="http://wwww.jcip.org">Java
Concurrency In Practice</a> (page 253).
+ * </p>
+ *
+ * @param seed the seed, typically based on a hash code and nanoTime
+ * @return a number that is "random enough"
+ */
+ public static int random( int seed ) {
+ seed ^= (seed << 6);
+ seed ^= (seed >>> 21);
+ seed ^= (seed << 7);
+ return seed;
+ }
+
}
Deleted:
trunk/dna-spi/src/test/java/org/jboss/dna/spi/graph/connection/RepositoryTestOperations.java
===================================================================
---
trunk/dna-spi/src/test/java/org/jboss/dna/spi/graph/connection/RepositoryTestOperations.java 2008-06-10
20:18:05 UTC (rev 252)
+++
trunk/dna-spi/src/test/java/org/jboss/dna/spi/graph/connection/RepositoryTestOperations.java 2008-06-10
20:19:15 UTC (rev 253)
@@ -1,102 +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.Logger;
-
-/**
- * @author Randall Hauch
- */
-public class RepositoryTestOperations {
-
- /**
- * 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
- * number of times, intermixed with random math operations and {@link Thread#yield()
yielding}.
- * @param env the environment
- * @param callsPerOperation the number of <code>load</code> calls per
RepositoryOperation
- * @return the factory
- */
- public static RepositoryOperation.Factory<Integer>
createMultipleLoadOperationFactory( final ExecutionEnvironment env, final int
callsPerOperation ) {
- return new RepositoryOperation.Factory<Integer>() {
-
- public RepositoryOperation<Integer> create() {
- return new CallLoadMultipleTimes(env, callsPerOperation);
- }
- };
- }
-
- public static class CallLoadMultipleTimes implements
RepositoryOperation<Integer> {
-
- private final int count;
- private final ExecutionEnvironment env;
-
- public CallLoadMultipleTimes( ExecutionEnvironment env, int count ) {
- this.count = count;
- this.env = env;
- }
-
- /**
- * {@inheritDoc}
- */
- public String getName() {
- return Thread.currentThread().getName() +
"-CallLoadMultipleTimes";
- }
-
- /**
- * {@inheritDoc}
- */
- public Integer run( RepositoryConnection connection ) throws InterruptedException
{
- Logger.getLogger(RepositoryTestOperations.class).debug("Running {}
operation", this.getClass().getSimpleName());
- int total = count;
- for (int i = 0; i != count; ++i) {
- // Add two random numbers ...
- int int1 = random(this.hashCode() ^ (int)System.nanoTime() * i);
- if (i % 2 == 0) {
- Thread.yield();
- }
- connection.execute(env);
- int int2 = random(this.hashCode() ^ (int)System.nanoTime() + i);
- total += Math.min(Math.abs(Math.max(int1, int2) + int1 * int2 / 3),
count);
- }
- Logger.getLogger(RepositoryTestOperations.class).debug("Finishing {}
operation", this.getClass().getSimpleName());
- return total < count ? total : count; // should really always return
count
- }
- }
-
- /**
- * A "random-enough" number generator that is cheap and that has no
synchronization issues (like some other random number
- * generators).
- * <p>
- * This was taken from <a href="http://wwww.jcip.org">Java
Concurrency In Practice</a> (page 253).
- * </p>
- * @param seed the seed, typically based on a hash code and nanoTime
- * @return a number that is "random enough"
- */
- public static int random( int seed ) {
- seed ^= (seed << 6);
- seed ^= (seed >>> 21);
- seed ^= (seed << 7);
- return seed;
- }
-
-}
Copied:
trunk/dna-spi/src/test/java/org/jboss/dna/spi/graph/connection/TimeDelayingRepositorySource.java
(from rev 251,
trunk/dna-spi/src/test/java/org/jboss/dna/spi/graph/connection/MockRepositorySource.java)
===================================================================
---
trunk/dna-spi/src/test/java/org/jboss/dna/spi/graph/connection/TimeDelayingRepositorySource.java
(rev 0)
+++
trunk/dna-spi/src/test/java/org/jboss/dna/spi/graph/connection/TimeDelayingRepositorySource.java 2008-06-10
20:19:15 UTC (rev 253)
@@ -0,0 +1,299 @@
+/*
+ * 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.mockito.Mockito.mock;
+import java.util.Set;
+import java.util.concurrent.CopyOnWriteArraySet;
+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.atomic.AtomicReference;
+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.commands.GraphCommand;
+
+/**
+ * @author Randall Hauch
+ */
+@ThreadSafe
+public class TimeDelayingRepositorySource implements RepositorySource {
+
+ private final String identifier;
+ 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>();
+ private final AtomicLong loadCount = new AtomicLong(0);
+ private final AtomicLong loadDelay = new AtomicLong(0);
+ private final AtomicLong pingCount = new AtomicLong(0);
+ private final AtomicLong pingDelay = new AtomicLong(0);
+ private CachePolicy defaultCachePolicy;
+
+ public TimeDelayingRepositorySource( String identifier ) {
+ this.identifier = identifier;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public String getName() {
+ return this.identifier;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public int getRetryLimit() {
+ return this.retryLimit.get();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void setRetryLimit( int limit ) {
+ this.retryLimit.set(limit);
+ }
+
+ public CachePolicy getDefaultCachePolicy() {
+ return defaultCachePolicy;
+ }
+
+ public void setDefaultCachePolicy( CachePolicy defaultCachePolicy ) {
+ this.defaultCachePolicy = defaultCachePolicy;
+ }
+
+ /**
+ * @return loadCount
+ */
+ public long getTotalExecuteCount() {
+ return this.loadCount.get();
+ }
+
+ /**
+ * @return pingCount
+ */
+ public long getTotalPingCount() {
+ return this.pingCount.get();
+ }
+
+ /**
+ * @return loadDelay
+ */
+ public long getConnectionExecuteDelayInMillis() {
+ return this.loadDelay.get();
+ }
+
+ public void setConnectionExecuteDelay( long time, TimeUnit unit ) {
+ this.loadDelay.set(unit.toMillis(time));
+ }
+
+ /**
+ * @return pingDelay
+ */
+ public long getConnectionPingDelayInMillis() {
+ return this.pingDelay.get();
+ }
+
+ public void setConnectionPingDelay( long time, TimeUnit unit ) {
+ this.pingDelay.set(unit.toMillis(time));
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public RepositoryConnection getConnection() throws RepositorySourceException {
+ int connectionNumber = this.connectionsOpenedCount.incrementAndGet();
+ String connectionName = "Connection " + connectionNumber;
+ XAResource xaResource = newXaResource(connectionName);
+ Connection c = newConnection(connectionName, xaResource);
+ this.openConnections.add(c);
+ return c;
+ }
+
+ /**
+ * Factory method that can be overridden by subclasses. This method implementation
simply creates a mock {@link XAResource}.
+ *
+ * @param connectionName the name of the connection
+ * @return the XAResource, or null if this source does not support XA
+ */
+ protected XAResource newXaResource( String connectionName ) {
+ return mock(XAResource.class);
+ }
+
+ /**
+ * Factory method that can be overridden by subclasses. This method implementation
creates a new {@link Connection} that uses
+ * standard bean properties for the various delays and counts.
+ *
+ * @param connectionName
+ * @param xaResource
+ * @return
+ * @throws RepositorySourceException
+ */
+ protected Connection newConnection( String connectionName, XAResource xaResource )
throws RepositorySourceException {
+ Connection c = new Connection(connectionName, this.loadDelay.get(),
this.pingDelay.get());
+ c.setXaResource(xaResource);
+ return c;
+ }
+
+ protected void close( Connection conn ) {
+ if (conn != null && this.openConnections.remove(conn)) {
+ this.connectionsClosedCount.incrementAndGet();
+ this.loadCount.addAndGet(conn.getLoadCount());
+ this.pingCount.addAndGet(conn.getPingCount());
+ }
+ }
+
+ public int getOpenConnectionCount() {
+ return this.openConnections.size();
+ }
+
+ public int getTotalConnectionsCreated() {
+ return this.connectionsOpenedCount.get();
+ }
+
+ public int getTotalConnectionsClosed() {
+ return this.connectionsClosedCount.get();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public Reference getReference() {
+ throw new UnsupportedOperationException();
+ }
+
+ public class Connection implements RepositoryConnection {
+
+ private final String connectionName;
+ private final AtomicBoolean closed = new AtomicBoolean(false);
+ private final AtomicBoolean loadResponse = new AtomicBoolean(true);
+ private final AtomicBoolean pingResponse = new AtomicBoolean(true);
+ private final AtomicLong closeCount = new AtomicLong(0);
+ private final AtomicLong loadCount = new AtomicLong(0);
+ private final AtomicLong loadDelay;
+ private final AtomicLong pingCount = new AtomicLong(0);
+ private final AtomicLong pingDelay;
+ private final AtomicReference<XAResource> xaResource = new
AtomicReference<XAResource>();
+
+ protected Connection( String connectionName, long loadDelay, long pingDelay ) {
+ assert connectionName != null && connectionName.trim().length() !=
0;
+ this.loadDelay = new AtomicLong(loadDelay);
+ this.pingDelay = new AtomicLong(pingDelay);
+ this.connectionName = connectionName;
+ }
+
+ public String getConnectionName() {
+ return this.connectionName;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void close() {
+ this.closeCount.incrementAndGet();
+ this.closed.set(true);
+ TimeDelayingRepositorySource.this.close(this);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public String getSourceName() {
+ return TimeDelayingRepositorySource.this.getName();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public CachePolicy getDefaultCachePolicy() {
+ return TimeDelayingRepositorySource.this.getDefaultCachePolicy();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public XAResource getXAResource() {
+ return this.xaResource.get();
+ }
+
+ public void setXaResource( XAResource xaResource ) {
+ this.xaResource.set(xaResource);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void execute( ExecutionEnvironment env, GraphCommand... commands ) throws
RepositorySourceException, InterruptedException {
+ long delay = this.loadDelay.get();
+ if (delay > 0l) Thread.sleep(delay);
+ this.loadCount.incrementAndGet();
+ }
+
+ public void setLoadResponse( boolean response ) {
+ this.loadResponse.set(response);
+ }
+
+ public void setLoadDelay( long time, TimeUnit unit ) {
+ this.loadDelay.set(unit.toMillis(time));
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean ping( long time, TimeUnit unit ) throws InterruptedException {
+ Thread.sleep(this.pingDelay.get());
+ return this.pingResponse.get();
+ }
+
+ public void setPingResponse( boolean pingResponse ) {
+ this.pingResponse.set(pingResponse);
+ }
+
+ public void setPingDelay( long time, TimeUnit unit ) {
+ this.pingDelay.set(unit.toMillis(time));
+ }
+
+ public long getPingCount() {
+ return this.pingCount.get();
+ }
+
+ public long getLoadCount() {
+ return this.loadCount.get();
+ }
+
+ public long getCloseCount() {
+ return this.closeCount.get();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void setListener( RepositorySourceListener listener ) {
+ }
+
+ }
+
+}
Property changes on:
trunk/dna-spi/src/test/java/org/jboss/dna/spi/graph/connection/TimeDelayingRepositorySource.java
___________________________________________________________________
Name: svn:mime-type
+ text/plain
Modified:
trunk/dna-spi/src/test/java/org/jboss/dna/spi/graph/impl/BooleanValueFactoryTest.java
===================================================================
---
trunk/dna-spi/src/test/java/org/jboss/dna/spi/graph/impl/BooleanValueFactoryTest.java 2008-06-10
20:18:05 UTC (rev 252)
+++
trunk/dna-spi/src/test/java/org/jboss/dna/spi/graph/impl/BooleanValueFactoryTest.java 2008-06-10
20:19:15 UTC (rev 253)
@@ -23,6 +23,7 @@
import static org.hamcrest.core.Is.is;
import static org.junit.Assert.assertThat;
+import static org.mockito.Mockito.mock;
import java.io.ByteArrayInputStream;
import java.io.StringReader;
import java.net.URI;
@@ -31,7 +32,6 @@
import org.jboss.dna.spi.graph.Name;
import org.jboss.dna.spi.graph.Path;
import org.jboss.dna.spi.graph.Reference;
-import org.jmock.Mockery;
import org.junit.Before;
import org.junit.Test;
@@ -43,7 +43,6 @@
private BooleanValueFactory factory;
private StringValueFactory stringFactory;
- private Mockery context;
/**
* @throws java.lang.Exception
@@ -52,7 +51,6 @@
public void setUp() throws Exception {
stringFactory = new StringValueFactory(Path.URL_DECODER, Path.DEFAULT_ENCODER);
factory = new BooleanValueFactory(Path.URL_DECODER, stringFactory);
- context = new Mockery();
}
@Test
@@ -122,17 +120,17 @@
@Test( expected = UnsupportedOperationException.class )
public void shouldNotCreateBooleanFromName() {
- factory.create(context.mock(Name.class));
+ factory.create(mock(Name.class));
}
@Test( expected = UnsupportedOperationException.class )
public void shouldNotCreateBooleanFromPath() {
- factory.create(context.mock(Path.class));
+ factory.create(mock(Path.class));
}
@Test( expected = UnsupportedOperationException.class )
public void shouldNotCreateBooleanFromReference() {
- factory.create(context.mock(Reference.class));
+ factory.create(mock(Reference.class));
}
@Test( expected = UnsupportedOperationException.class )
Modified:
trunk/dna-spi/src/test/java/org/jboss/dna/spi/graph/impl/DecimalValueFactoryTest.java
===================================================================
---
trunk/dna-spi/src/test/java/org/jboss/dna/spi/graph/impl/DecimalValueFactoryTest.java 2008-06-10
20:18:05 UTC (rev 252)
+++
trunk/dna-spi/src/test/java/org/jboss/dna/spi/graph/impl/DecimalValueFactoryTest.java 2008-06-10
20:19:15 UTC (rev 253)
@@ -23,6 +23,7 @@
import static org.hamcrest.core.Is.is;
import static org.junit.Assert.assertThat;
+import static org.mockito.Mockito.mock;
import java.io.ByteArrayInputStream;
import java.io.StringReader;
import java.math.BigDecimal;
@@ -32,7 +33,6 @@
import org.jboss.dna.spi.graph.Name;
import org.jboss.dna.spi.graph.Path;
import org.jboss.dna.spi.graph.Reference;
-import org.jmock.Mockery;
import org.junit.Before;
import org.junit.Test;
@@ -44,7 +44,6 @@
private DecimalValueFactory factory;
private StringValueFactory stringFactory;
- private Mockery context;
/**
* @throws java.lang.Exception
@@ -53,7 +52,6 @@
public void setUp() throws Exception {
stringFactory = new StringValueFactory(Path.URL_DECODER, Path.DEFAULT_ENCODER);
factory = new DecimalValueFactory(Path.URL_DECODER, stringFactory);
- context = new Mockery();
}
@Test( expected = UnsupportedOperationException.class )
@@ -115,17 +113,17 @@
@Test( expected = UnsupportedOperationException.class )
public void shouldNotCreateDecimalFromName() {
- factory.create(context.mock(Name.class));
+ factory.create(mock(Name.class));
}
@Test( expected = UnsupportedOperationException.class )
public void shouldNotCreateDecimalFromPath() {
- factory.create(context.mock(Path.class));
+ factory.create(mock(Path.class));
}
@Test( expected = UnsupportedOperationException.class )
public void shouldNotCreateDecimalFromReference() {
- factory.create(context.mock(Reference.class));
+ factory.create(mock(Reference.class));
}
@Test( expected = UnsupportedOperationException.class )
@@ -160,8 +158,7 @@
}
@Test( expected = IllegalArgumentException.class )
- public void
shouldNotCreateDecimalFromInputStreamContainingUtf8EncodingOfStringWithContentsOtherThanDecimal()
- throws Exception {
+ public void
shouldNotCreateDecimalFromInputStreamContainingUtf8EncodingOfStringWithContentsOtherThanDecimal()
throws Exception {
factory.create(new
ByteArrayInputStream("something".getBytes("UTF-8")));
}
Modified:
trunk/dna-spi/src/test/java/org/jboss/dna/spi/graph/impl/DoubleValueFactoryTest.java
===================================================================
---
trunk/dna-spi/src/test/java/org/jboss/dna/spi/graph/impl/DoubleValueFactoryTest.java 2008-06-10
20:18:05 UTC (rev 252)
+++
trunk/dna-spi/src/test/java/org/jboss/dna/spi/graph/impl/DoubleValueFactoryTest.java 2008-06-10
20:19:15 UTC (rev 253)
@@ -23,6 +23,7 @@
import static org.hamcrest.core.Is.is;
import static org.junit.Assert.assertThat;
+import static org.mockito.Mockito.mock;
import java.io.ByteArrayInputStream;
import java.io.StringReader;
import java.math.BigDecimal;
@@ -32,7 +33,6 @@
import org.jboss.dna.spi.graph.Name;
import org.jboss.dna.spi.graph.Path;
import org.jboss.dna.spi.graph.Reference;
-import org.jmock.Mockery;
import org.junit.Before;
import org.junit.Test;
@@ -44,7 +44,6 @@
private DoubleValueFactory factory;
private StringValueFactory stringFactory;
- private Mockery context;
/**
* @throws java.lang.Exception
@@ -53,7 +52,6 @@
public void setUp() throws Exception {
stringFactory = new StringValueFactory(Path.URL_DECODER, Path.URL_ENCODER);
factory = new DoubleValueFactory(Path.URL_DECODER, stringFactory);
- context = new Mockery();
}
@Test( expected = UnsupportedOperationException.class )
@@ -115,17 +113,17 @@
@Test( expected = UnsupportedOperationException.class )
public void shouldNotCreateDoubleFromName() {
- factory.create(context.mock(Name.class));
+ factory.create(mock(Name.class));
}
@Test( expected = UnsupportedOperationException.class )
public void shouldNotCreateDoubleFromPath() {
- factory.create(context.mock(Path.class));
+ factory.create(mock(Path.class));
}
@Test( expected = UnsupportedOperationException.class )
public void shouldNotCreateDoubleFromReference() {
- factory.create(context.mock(Reference.class));
+ factory.create(mock(Reference.class));
}
@Test( expected = UnsupportedOperationException.class )
Modified: trunk/dna-spi/src/test/java/org/jboss/dna/spi/graph/impl/JodaDateTimeTest.java
===================================================================
---
trunk/dna-spi/src/test/java/org/jboss/dna/spi/graph/impl/JodaDateTimeTest.java 2008-06-10
20:18:05 UTC (rev 252)
+++
trunk/dna-spi/src/test/java/org/jboss/dna/spi/graph/impl/JodaDateTimeTest.java 2008-06-10
20:19:15 UTC (rev 253)
@@ -22,8 +22,8 @@
package org.jboss.dna.spi.graph.impl;
import static org.hamcrest.core.Is.is;
-import static org.hamcrest.text.StringStartsWith.startsWith;
import static org.junit.Assert.assertThat;
+import static org.jboss.dna.common.text.StringMatcher.startsWith;
import org.junit.Before;
import org.junit.Test;
Modified:
trunk/dna-spi/src/test/java/org/jboss/dna/spi/graph/impl/JodaDateTimeValueFactoryTest.java
===================================================================
---
trunk/dna-spi/src/test/java/org/jboss/dna/spi/graph/impl/JodaDateTimeValueFactoryTest.java 2008-06-10
20:18:05 UTC (rev 252)
+++
trunk/dna-spi/src/test/java/org/jboss/dna/spi/graph/impl/JodaDateTimeValueFactoryTest.java 2008-06-10
20:19:15 UTC (rev 253)
@@ -23,6 +23,7 @@
import static org.hamcrest.core.Is.is;
import static org.junit.Assert.assertThat;
+import static org.mockito.Mockito.mock;
import java.io.ByteArrayInputStream;
import java.io.StringReader;
import java.math.BigDecimal;
@@ -32,7 +33,6 @@
import org.jboss.dna.spi.graph.Name;
import org.jboss.dna.spi.graph.Path;
import org.jboss.dna.spi.graph.Reference;
-import org.jmock.Mockery;
import org.junit.Before;
import org.junit.Test;
@@ -53,7 +53,6 @@
private JodaDateTimeValueFactory factory;
private StringValueFactory stringFactory;
- private Mockery context;
/**
* @throws java.lang.Exception
@@ -62,7 +61,6 @@
public void setUp() throws Exception {
stringFactory = new StringValueFactory(Path.URL_DECODER, Path.URL_ENCODER);
factory = new JodaDateTimeValueFactory(Path.URL_DECODER, stringFactory);
- context = new Mockery();
}
@Test( expected = UnsupportedOperationException.class )
@@ -127,17 +125,17 @@
@Test( expected = UnsupportedOperationException.class )
public void shouldNotCreateDateFromName() {
- factory.create(context.mock(Name.class));
+ factory.create(mock(Name.class));
}
@Test( expected = UnsupportedOperationException.class )
public void shouldNotCreateDateFromPath() {
- factory.create(context.mock(Path.class));
+ factory.create(mock(Path.class));
}
@Test( expected = UnsupportedOperationException.class )
public void shouldNotCreateDateFromReference() {
- factory.create(context.mock(Reference.class));
+ factory.create(mock(Reference.class));
}
@Test( expected = UnsupportedOperationException.class )
@@ -164,14 +162,12 @@
}
@Test( expected = IllegalArgumentException.class )
- public void
shouldNotCreateDateFromByteArrayContainingUtf8EncodingOfStringWithContentThatIsNotWellFormedDate()
- throws Exception {
+ public void
shouldNotCreateDateFromByteArrayContainingUtf8EncodingOfStringWithContentThatIsNotWellFormedDate()
throws Exception {
factory.create("something".getBytes("UTF-8"));
}
@Test( expected = IllegalArgumentException.class )
- public void
shouldNotCreateDateFromInputStreamContainingUtf8EncodingOfStringWithContentThatIsNotWellFormedDate()
- throws Exception {
+ public void
shouldNotCreateDateFromInputStreamContainingUtf8EncodingOfStringWithContentThatIsNotWellFormedDate()
throws Exception {
factory.create(new
ByteArrayInputStream("something".getBytes("UTF-8")));
}
Modified:
trunk/dna-spi/src/test/java/org/jboss/dna/spi/graph/impl/LongValueFactoryTest.java
===================================================================
---
trunk/dna-spi/src/test/java/org/jboss/dna/spi/graph/impl/LongValueFactoryTest.java 2008-06-10
20:18:05 UTC (rev 252)
+++
trunk/dna-spi/src/test/java/org/jboss/dna/spi/graph/impl/LongValueFactoryTest.java 2008-06-10
20:19:15 UTC (rev 253)
@@ -23,6 +23,7 @@
import static org.hamcrest.core.Is.is;
import static org.junit.Assert.assertThat;
+import static org.mockito.Mockito.mock;
import java.io.ByteArrayInputStream;
import java.io.StringReader;
import java.math.BigDecimal;
@@ -32,7 +33,6 @@
import org.jboss.dna.spi.graph.Name;
import org.jboss.dna.spi.graph.Path;
import org.jboss.dna.spi.graph.Reference;
-import org.jmock.Mockery;
import org.junit.Before;
import org.junit.Test;
@@ -44,7 +44,6 @@
private LongValueFactory factory;
private StringValueFactory stringFactory;
- private Mockery context;
/**
* @throws java.lang.Exception
@@ -53,7 +52,6 @@
public void setUp() throws Exception {
stringFactory = new StringValueFactory(Path.URL_DECODER, Path.URL_ENCODER);
factory = new LongValueFactory(Path.URL_DECODER, stringFactory);
- context = new Mockery();
}
@Test( expected = UnsupportedOperationException.class )
@@ -117,17 +115,17 @@
@Test( expected = UnsupportedOperationException.class )
public void shouldNotCreateLongFromName() {
- factory.create(context.mock(Name.class));
+ factory.create(mock(Name.class));
}
@Test( expected = UnsupportedOperationException.class )
public void shouldNotCreateLongFromPath() {
- factory.create(context.mock(Path.class));
+ factory.create(mock(Path.class));
}
@Test( expected = UnsupportedOperationException.class )
public void shouldNotCreateLongFromReference() {
- factory.create(context.mock(Reference.class));
+ factory.create(mock(Reference.class));
}
@Test( expected = UnsupportedOperationException.class )