Author: rhauch
Date: 2009-09-03 12:11:39 -0400 (Thu, 03 Sep 2009)
New Revision: 1190
Added:
trunk/extensions/dna-connector-store-jpa/src/main/java/org/jboss/dna/connector/store/jpa/EntityManagers.java
Modified:
trunk/dna-graph/src/main/java/org/jboss/dna/graph/connector/RepositorySource.java
trunk/dna-graph/src/main/java/org/jboss/dna/graph/connector/federation/FederatedRepositorySource.java
trunk/dna-graph/src/main/java/org/jboss/dna/graph/connector/inmemory/InMemoryRepositorySource.java
trunk/dna-graph/src/test/java/org/jboss/dna/graph/connector/TimeDelayingRepositorySource.java
trunk/dna-graph/src/test/java/org/jboss/dna/graph/connector/test/AbstractConnectorTest.java
trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/CndNodeTypeRegistrationTest.java
trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrSessionTest.java
trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/TypeRegistrationTest.java
trunk/dna-repository/src/main/java/org/jboss/dna/repository/RepositoryLibrary.java
trunk/dna-repository/src/main/java/org/jboss/dna/repository/RepositoryService.java
trunk/dna-repository/src/test/java/org/jboss/dna/repository/FakeRepositorySource.java
trunk/dna-repository/src/test/java/org/jboss/dna/repository/sequencer/StreamSequencerAdapterTest.java
trunk/extensions/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/FederatedRepositorySource.java
trunk/extensions/dna-connector-filesystem/src/main/java/org/jboss/dna/connector/filesystem/FileSystemSource.java
trunk/extensions/dna-connector-infinispan/src/main/java/org/jboss/dna/connector/infinispan/InfinispanSource.java
trunk/extensions/dna-connector-jbosscache/src/main/java/org/jboss/dna/connector/jbosscache/JBossCacheSource.java
trunk/extensions/dna-connector-jdbc-metadata/src/main/java/org/jboss/dna/connector/jdbc/JdbcRepositorySource.java
trunk/extensions/dna-connector-store-jpa/src/main/java/org/jboss/dna/connector/store/jpa/JpaConnection.java
trunk/extensions/dna-connector-store-jpa/src/main/java/org/jboss/dna/connector/store/jpa/JpaConnectorI18n.java
trunk/extensions/dna-connector-store-jpa/src/main/java/org/jboss/dna/connector/store/jpa/JpaSource.java
trunk/extensions/dna-connector-store-jpa/src/main/resources/org/jboss/dna/connector/store/jpa/JpaConnectorI18n.properties
trunk/extensions/dna-connector-store-jpa/src/test/java/org/jboss/dna/connector/store/jpa/JpaSourceTest.java
trunk/extensions/dna-connector-svn/src/main/java/org/jboss/dna/connector/svn/SVNRepositorySource.java
Log:
DNA-509 JPA Connector does not close all EntityManager instances that it creates
Added to the JPA Connector project a new class that allows JpaSource and JpaConnection to
hold onto a JPA EntityManager and EntityManagerFactory, while ensuring that the
EntityManager and EntityManagerFactory instances are ALWAYS closed - as long as the
JpaConnection objects and JpaSource objects are always closed (in any order). It also
allows the JpaSource to start using a new EntityManagerFactory if the settings are
changed, without impacting any previously-opened and in-use connections.
Although I did try to find a way for the JpaSource to not have a 'close()' method,
it simply was not possible to do without adding TREMENDOUS overhead to the creation of an
EntityManagerFactory for every connection (remember, the EntityManagerFactory must be
configured with each entity class, and does the schema validation/create/drop/update
operations, and this had to be done on EVERY create new connection). And rather than have
'close()' be an artifact of the JpaSource class, it's actually better if this
method is defined on the RepositorySource interface and that all implementations provide a
close() method. This provides a standard way for the RepositorySource implementations to
begin reclaiming resources such as connections, caches, files, and/or large objects.
RepositoryLibrary and RepositoryService were modified to ensure that all RepositorySource
objects are closed when the library and service are shutdown (via their administrative
interface).
The reusable connector framework unit tests were also modified to ensure that they all
close the RepositorySource upon teardown of the tests (or, in the case of the reading
tests, upon teardown after all tests are run).
Modified:
trunk/dna-graph/src/main/java/org/jboss/dna/graph/connector/RepositorySource.java
===================================================================
---
trunk/dna-graph/src/main/java/org/jboss/dna/graph/connector/RepositorySource.java 2009-09-03
14:52:15 UTC (rev 1189)
+++
trunk/dna-graph/src/main/java/org/jboss/dna/graph/connector/RepositorySource.java 2009-09-03
16:11:39 UTC (rev 1190)
@@ -193,4 +193,20 @@
*/
RepositorySourceCapabilities getCapabilities();
+ /**
+ * Signal this source that it is no longer needed and should begin the process of
reclaiming or closing all resources that it
+ * has acquired. Because {@link #getConnection() connections} may still be in use,
this method may not necessarily close all
+ * resources immediately.
+ * <p>
+ * This is a required method, and must be called when this source is no longer needed
if one or more {@link #getConnection()
+ * connections} have been obtained since the previous call to this method.
+ * </p>
+ * <p>
+ * Note that calling this method also does not preclude {@link #getConnection()
obtaining more connections} after this method
+ * is called. If that happens, this source should simply reacquire any resources
necessary to provide additional connections,
+ * and this method needs to be called once again.
+ * </p>
+ */
+ void close();
+
}
Modified:
trunk/dna-graph/src/main/java/org/jboss/dna/graph/connector/federation/FederatedRepositorySource.java
===================================================================
---
trunk/dna-graph/src/main/java/org/jboss/dna/graph/connector/federation/FederatedRepositorySource.java 2009-09-03
14:52:15 UTC (rev 1189)
+++
trunk/dna-graph/src/main/java/org/jboss/dna/graph/connector/federation/FederatedRepositorySource.java 2009-09-03
16:11:39 UTC (rev 1190)
@@ -191,6 +191,18 @@
/**
* {@inheritDoc}
*
+ * @see org.jboss.dna.graph.connector.RepositorySource#close()
+ */
+ public void close() {
+ synchronized (this) {
+ // Release the configuration ...
+ this.configuration = null;
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ *
* @see javax.naming.Referenceable#getReference()
*/
public Reference getReference() {
Modified:
trunk/dna-graph/src/main/java/org/jboss/dna/graph/connector/inmemory/InMemoryRepositorySource.java
===================================================================
---
trunk/dna-graph/src/main/java/org/jboss/dna/graph/connector/inmemory/InMemoryRepositorySource.java 2009-09-03
14:52:15 UTC (rev 1189)
+++
trunk/dna-graph/src/main/java/org/jboss/dna/graph/connector/inmemory/InMemoryRepositorySource.java 2009-09-03
16:11:39 UTC (rev 1190)
@@ -256,7 +256,7 @@
*
* @see org.jboss.dna.graph.connector.RepositorySource#getConnection()
*/
- public RepositoryConnection getConnection() throws RepositorySourceException {
+ public synchronized RepositoryConnection getConnection() throws
RepositorySourceException {
if (repository == null) {
repository = new InMemoryRepository(name, rootNodeUuid,
defaultWorkspaceName);
}
@@ -265,7 +265,17 @@
/**
* {@inheritDoc}
+ *
+ * @see org.jboss.dna.graph.connector.RepositorySource#close()
*/
+ public synchronized void close() {
+ // Null the reference to the in-memory repository; open connections still
reference it and can continue to work ...
+ this.repository = null;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
public synchronized Reference getReference() {
String className = getClass().getName();
String factoryClassName = this.getClass().getName();
Modified:
trunk/dna-graph/src/test/java/org/jboss/dna/graph/connector/TimeDelayingRepositorySource.java
===================================================================
---
trunk/dna-graph/src/test/java/org/jboss/dna/graph/connector/TimeDelayingRepositorySource.java 2009-09-03
14:52:15 UTC (rev 1189)
+++
trunk/dna-graph/src/test/java/org/jboss/dna/graph/connector/TimeDelayingRepositorySource.java 2009-09-03
16:11:39 UTC (rev 1190)
@@ -182,6 +182,15 @@
}
/**
+ * {@inheritDoc}
+ *
+ * @see org.jboss.dna.graph.connector.RepositorySource#close()
+ */
+ public void close() {
+ // Do not do anything, since when the connections are closed they'll be
removed from the 'openConnections' set
+ }
+
+ /**
* Factory method that can be overridden by subclasses. This method implementation
simply creates a mock {@link XAResource}.
*
* @param connectionName the name of the connection
Modified:
trunk/dna-graph/src/test/java/org/jboss/dna/graph/connector/test/AbstractConnectorTest.java
===================================================================
---
trunk/dna-graph/src/test/java/org/jboss/dna/graph/connector/test/AbstractConnectorTest.java 2009-09-03
14:52:15 UTC (rev 1189)
+++
trunk/dna-graph/src/test/java/org/jboss/dna/graph/connector/test/AbstractConnectorTest.java 2009-09-03
16:11:39 UTC (rev 1190)
@@ -28,7 +28,6 @@
import static org.junit.Assert.assertThat;
import java.io.PrintStream;
import java.io.PrintWriter;
-import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
@@ -39,7 +38,6 @@
import java.util.UUID;
import java.util.concurrent.TimeUnit;
import org.jboss.dna.common.statistic.Stopwatch;
-import org.jboss.dna.common.util.Reflection;
import org.jboss.dna.graph.DnaLexicon;
import org.jboss.dna.graph.ExecutionContext;
import org.jboss.dna.graph.Graph;
@@ -170,13 +168,9 @@
}
}
if (source != null) {
+ // Close the source, notifying it that it can reclaim any resources ...
try {
- Reflection reflection = new Reflection(source.getClass());
- reflection.invokeBestMethodOnTarget(new String[] {"close"},
source);
- } catch (NoSuchMethodException err) {
- // do nothing (method did not exist)
- } catch (IllegalAccessException err) {
- } catch (InvocationTargetException err) {
+ source.close();
} finally {
source = null;
}
Modified: trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/CndNodeTypeRegistrationTest.java
===================================================================
---
trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/CndNodeTypeRegistrationTest.java 2009-09-03
14:52:15 UTC (rev 1189)
+++
trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/CndNodeTypeRegistrationTest.java 2009-09-03
16:11:39 UTC (rev 1190)
@@ -70,11 +70,6 @@
}
- @Test( expected = AssertionError.class )
- public void shouldNotAllowNullTypeSource() throws Exception {
- repoTypeManager.registerNodeTypes((JcrNodeTypeSource)null);
- }
-
@Test( expected = RepositoryException.class )
public void shouldNotAllowRedefinitionOfExistingType() throws Exception {
nodeTypes = new CndNodeTypeSource(CND_LOCATION + "existingType.cnd");
Modified: trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrSessionTest.java
===================================================================
--- trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrSessionTest.java 2009-09-03 14:52:15
UTC (rev 1189)
+++ trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrSessionTest.java 2009-09-03 16:11:39
UTC (rev 1190)
@@ -98,26 +98,6 @@
}
}
- @Test( expected = AssertionError.class )
- public void shouldNotAllowNullRepository() throws Exception {
- new JcrSession(null, workspace, context, sessionAttributes);
- }
-
- @Test( expected = AssertionError.class )
- public void shouldNotAllowNullWorkspace() throws Exception {
- new JcrSession(repository, null, context, sessionAttributes);
- }
-
- @Test( expected = AssertionError.class )
- public void shouldNotAllowNullExecutionContext() throws Exception {
- new JcrSession(repository, workspace, null, sessionAttributes);
- }
-
- @Test( expected = AssertionError.class )
- public void shouldNotAllowNullSessionAttributesMap() throws Exception {
- new JcrSession(repository, workspace, context, null);
- }
-
@Test( expected = UnsupportedOperationException.class )
public void shouldNotAllowAddLockToken() throws Exception {
session.addLockToken(null);
Modified: trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/TypeRegistrationTest.java
===================================================================
--- trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/TypeRegistrationTest.java 2009-09-03
14:52:15 UTC (rev 1189)
+++ trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/TypeRegistrationTest.java 2009-09-03
16:11:39 UTC (rev 1190)
@@ -66,16 +66,6 @@
nameFactory = context.getValueFactories().getNameFactory();
}
- @Test( expected = AssertionError.class )
- public void shouldNotAllowNullDefinition() throws Exception {
- repoTypeManager.registerNodeType(null, true);
- }
-
- @Test( expected = AssertionError.class )
- public void shouldNotAllowTemplateWithNullContext() throws Exception {
- repoTypeManager.registerNodeType(new JcrNodeTypeTemplate(null), true);
- }
-
@Test( expected = InvalidNodeTypeDefinitionException.class )
public void shouldNotAllowNodeTypeWithNoName() throws Exception {
ntTemplate.setName(null);
Modified:
trunk/dna-repository/src/main/java/org/jboss/dna/repository/RepositoryLibrary.java
===================================================================
---
trunk/dna-repository/src/main/java/org/jboss/dna/repository/RepositoryLibrary.java 2009-09-03
14:52:15 UTC (rev 1189)
+++
trunk/dna-repository/src/main/java/org/jboss/dna/repository/RepositoryLibrary.java 2009-09-03
16:11:39 UTC (rev 1190)
@@ -218,7 +218,10 @@
try {
this.sourcesLock.readLock().lock();
for (RepositoryConnectionPool pool : this.pools.values()) {
+ // Shutdown the pool of connections ...
pool.shutdown();
+ // Now close the source (still allows in-use connections to be used) ...
+ pool.getRepositorySource().close();
}
} finally {
this.sourcesLock.readLock().unlock();
Modified:
trunk/dna-repository/src/main/java/org/jboss/dna/repository/RepositoryService.java
===================================================================
---
trunk/dna-repository/src/main/java/org/jboss/dna/repository/RepositoryService.java 2009-09-03
14:52:15 UTC (rev 1189)
+++
trunk/dna-repository/src/main/java/org/jboss/dna/repository/RepositoryService.java 2009-09-03
16:11:39 UTC (rev 1190)
@@ -94,6 +94,17 @@
/**
* {@inheritDoc}
*
+ * @see
org.jboss.dna.repository.service.AbstractServiceAdministrator#doShutdown(org.jboss.dna.repository.service.ServiceAdministrator.State)
+ */
+ @Override
+ protected void doShutdown( State fromState ) {
+ super.doShutdown(fromState);
+ shutdownService();
+ }
+
+ /**
+ * {@inheritDoc}
+ *
* @see
org.jboss.dna.repository.service.ServiceAdministrator#awaitTermination(long,
java.util.concurrent.TimeUnit)
*/
public boolean awaitTermination( long timeout,
@@ -228,6 +239,11 @@
}
}
+ protected synchronized void shutdownService() {
+ // Close the repository library ...
+ this.sources.getAdministrator().shutdown();
+ }
+
/**
* Instantiate the {@link RepositorySource} described by the supplied properties.
*
Modified:
trunk/dna-repository/src/test/java/org/jboss/dna/repository/FakeRepositorySource.java
===================================================================
---
trunk/dna-repository/src/test/java/org/jboss/dna/repository/FakeRepositorySource.java 2009-09-03
14:52:15 UTC (rev 1189)
+++
trunk/dna-repository/src/test/java/org/jboss/dna/repository/FakeRepositorySource.java 2009-09-03
16:11:39 UTC (rev 1190)
@@ -79,6 +79,15 @@
/**
* {@inheritDoc}
*
+ * @see org.jboss.dna.graph.connector.RepositorySource#close()
+ */
+ public void close() {
+ // do nothing
+ }
+
+ /**
+ * {@inheritDoc}
+ *
* @see org.jboss.dna.graph.connector.RepositorySource#getName()
*/
public String getName() {
Modified:
trunk/dna-repository/src/test/java/org/jboss/dna/repository/sequencer/StreamSequencerAdapterTest.java
===================================================================
---
trunk/dna-repository/src/test/java/org/jboss/dna/repository/sequencer/StreamSequencerAdapterTest.java 2009-09-03
14:52:15 UTC (rev 1189)
+++
trunk/dna-repository/src/test/java/org/jboss/dna/repository/sequencer/StreamSequencerAdapterTest.java 2009-09-03
16:11:39 UTC (rev 1190)
@@ -70,7 +70,7 @@
private StreamSequencerAdapter sequencer;
private final String[] validExpressions = {"/a/* => /output"};
private final SequencerConfig validConfig = new SequencerConfig("name",
"desc", Collections.<String, Object>emptyMap(),
-
"something.class", null, validExpressions);
+
"something.class", null, validExpressions);
private SequencerOutputMap sequencerOutput;
private final String sampleData = "The little brown fox didn't something
bad.";
private ExecutionContext context;
@@ -422,28 +422,6 @@
});
}
- @Test( expected = java.lang.AssertionError.class )
- public void shouldNotAllowNullInputNode() throws Exception {
- sequencer.createStreamSequencerContext(null, sequencedProperty, seqContext,
problems);
- }
-
- @Test( expected = java.lang.AssertionError.class )
- public void shouldNotAllowNullSequencedProperty() throws Exception {
-
- graph.create("/a").and();
- Node input = graph.getNodeAt("/a");
- sequencer.createStreamSequencerContext(input, null, seqContext, problems);
- }
-
- @Test( expected = java.lang.AssertionError.class )
- public void shouldNotAllowNullExecutionContext() throws Exception {
-
- this.sequencedProperty = mock(Property.class);
- graph.create("/a").and();
- Node input = graph.getNodeAt("/a");
- sequencer.createStreamSequencerContext(input, sequencedProperty, null,
problems);
- }
-
@Test
public void shouldProvideNamespaceRegistry() throws Exception {
Modified:
trunk/extensions/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/FederatedRepositorySource.java
===================================================================
---
trunk/extensions/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/FederatedRepositorySource.java 2009-09-03
14:52:15 UTC (rev 1189)
+++
trunk/extensions/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/FederatedRepositorySource.java 2009-09-03
16:11:39 UTC (rev 1190)
@@ -467,6 +467,15 @@
}
/**
+ * {@inheritDoc}
+ *
+ * @see org.jboss.dna.graph.connector.RepositorySource#close()
+ */
+ public void close() {
+ // do nothing ...
+ }
+
+ /**
* Get the {@link FederatedRepository} instance that this source is using. This
method uses the following logic:
* <ol>
* <li>If a {@link FederatedRepository} already was obtained from a prior call,
the same instance is returned.</li>
Modified:
trunk/extensions/dna-connector-filesystem/src/main/java/org/jboss/dna/connector/filesystem/FileSystemSource.java
===================================================================
---
trunk/extensions/dna-connector-filesystem/src/main/java/org/jboss/dna/connector/filesystem/FileSystemSource.java 2009-09-03
14:52:15 UTC (rev 1189)
+++
trunk/extensions/dna-connector-filesystem/src/main/java/org/jboss/dna/connector/filesystem/FileSystemSource.java 2009-09-03
16:11:39 UTC (rev 1190)
@@ -563,12 +563,21 @@
}
};
}
-
+
return new FileSystemConnection(name, defaultWorkspaceName, availableWorkspaces,
isCreatingWorkspacesAllowed(),
cachePolicy, rootNodeUuid, workspaceRootPath,
maxPathLength, filenameFilter,
getSupportsUpdates());
}
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.jboss.dna.graph.connector.RepositorySource#close()
+ */
+ public synchronized void close() {
+ this.availableWorkspaces = null;
+ }
+
@Immutable
/*package*/class FileSystemCachePolicy implements CachePolicy {
private static final long serialVersionUID = 1L;
Modified:
trunk/extensions/dna-connector-infinispan/src/main/java/org/jboss/dna/connector/infinispan/InfinispanSource.java
===================================================================
---
trunk/extensions/dna-connector-infinispan/src/main/java/org/jboss/dna/connector/infinispan/InfinispanSource.java 2009-09-03
14:52:15 UTC (rev 1189)
+++
trunk/extensions/dna-connector-infinispan/src/main/java/org/jboss/dna/connector/infinispan/InfinispanSource.java 2009-09-03
16:11:39 UTC (rev 1190)
@@ -420,6 +420,16 @@
}
/**
+ * {@inheritDoc}
+ *
+ * @see org.jboss.dna.graph.connector.RepositorySource#close()
+ */
+ public synchronized void close() {
+ // Null the reference to the repository; open connections still reference it and
can continue to work ...
+ this.repository = null;
+ }
+
+ /**
* @return repositoryContext
*/
public RepositoryContext getRepositoryContext() {
@@ -430,7 +440,7 @@
return repositoryContext != null ? repositoryContext.getObserver() : null;
}
- protected Context getContext() {
+ protected synchronized Context getContext() {
return this.jndiContext;
}
Modified:
trunk/extensions/dna-connector-jbosscache/src/main/java/org/jboss/dna/connector/jbosscache/JBossCacheSource.java
===================================================================
---
trunk/extensions/dna-connector-jbosscache/src/main/java/org/jboss/dna/connector/jbosscache/JBossCacheSource.java 2009-09-03
14:52:15 UTC (rev 1189)
+++
trunk/extensions/dna-connector-jbosscache/src/main/java/org/jboss/dna/connector/jbosscache/JBossCacheSource.java 2009-09-03
16:11:39 UTC (rev 1190)
@@ -485,6 +485,16 @@
}
/**
+ * {@inheritDoc}
+ *
+ * @see org.jboss.dna.graph.connector.RepositorySource#close()
+ */
+ public synchronized void close() {
+ // Null the reference to the repository; open connections still reference it and
can continue to work ...
+ this.repository = null;
+ }
+
+ /**
* Method that is responsible for attempting to create a new cache given the supplied
workspace name. Note that this is
* probably called at most once for each workspace name (except if this method fails
to create a cache for a given workspace
* name).
Modified:
trunk/extensions/dna-connector-jdbc-metadata/src/main/java/org/jboss/dna/connector/jdbc/JdbcRepositorySource.java
===================================================================
---
trunk/extensions/dna-connector-jdbc-metadata/src/main/java/org/jboss/dna/connector/jdbc/JdbcRepositorySource.java 2009-09-03
14:52:15 UTC (rev 1189)
+++
trunk/extensions/dna-connector-jdbc-metadata/src/main/java/org/jboss/dna/connector/jdbc/JdbcRepositorySource.java 2009-09-03
16:11:39 UTC (rev 1190)
@@ -42,7 +42,6 @@
import javax.naming.Reference;
import javax.naming.StringRefAddr;
import javax.naming.spi.ObjectFactory;
-
import net.jcip.annotations.ThreadSafe;
import org.jboss.dna.common.i18n.I18n;
import org.jboss.dna.common.jdbc.provider.DataSourceDatabaseMetadataProvider;
@@ -96,7 +95,7 @@
protected transient DriverDatabaseMetadataProvider driverProvider;
protected transient DataSourceDatabaseMetadataProvider dataSourceProvider;
protected transient UUID rootUuid = UUID.fromString(DEFAULT_ROOT_NODE_UUID);
-
+
protected static final String SOURCE_NAME = "sourceName";
protected static final String ROOT_NODE_UUID = "rootNodeUuid";
protected static final String DEFAULT_CACHE_POLICY = "defaultCachePolicy";
@@ -108,11 +107,12 @@
protected static final String RETRY_LIMIT = "retryLimit";
/**
- * Get and optionally create driver based provider
+ * Get and optionally create driver based provider
+ *
* @param create create provider
* @return driverProvider
*/
- protected DriverDatabaseMetadataProvider getDriverProvider(boolean create) {
+ protected DriverDatabaseMetadataProvider getDriverProvider( boolean create ) {
// lazy creation
if (driverProvider == null) {
driverProvider = new DefaultDriverDatabaseMetadataProvider();
@@ -121,18 +121,19 @@
}
/**
- * Get and optionally create data source based provider
+ * Get and optionally create data source based provider
+ *
* @param create create provider
* @return dataSourceProvider
*/
- protected DataSourceDatabaseMetadataProvider getDataSourceProvider(boolean create) {
+ protected DataSourceDatabaseMetadataProvider getDataSourceProvider( boolean create )
{
// lazy creation
if (dataSourceProvider == null && create) {
dataSourceProvider = new DefaultDataSourceDatabaseMetadataProvider();
}
return dataSourceProvider;
}
-
+
/**
* default constructor
*/
@@ -153,22 +154,19 @@
*
* @see org.jboss.dna.graph.connector.RepositorySource#getConnection()
*/
- public RepositoryConnection getConnection() throws RepositorySourceException {
+ public synchronized RepositoryConnection getConnection() throws
RepositorySourceException {
String errMsg = null;
// check name
if (getName() == null) {
errMsg = JdbcMetadataI18n.propertyIsRequired.text("name");
throw new RepositorySourceException(errMsg);
}
-
+
// create Jdbc connection using data source first
try {
if (dataSourceProvider != null) {
// create wrapper for Jdbc connection
- return new JdbcConnection(getName(),
- getDefaultCachePolicy(),
- dataSourceProvider.getConnection(),
- rootUuid);
+ return new JdbcConnection(getName(), getDefaultCachePolicy(),
dataSourceProvider.getConnection(), rootUuid);
}
} catch (Exception e) {
errMsg = JdbcMetadataI18n.unableToGetConnectionUsingDriver.text(getName(),
getDriverClassName(), getDatabaseUrl());
@@ -179,16 +177,13 @@
try {
if (driverProvider != null) {
// create wrapper for Jdbc connection
- return new JdbcConnection(getName(),
- getDefaultCachePolicy(),
- driverProvider.getConnection(),
- rootUuid);
+ return new JdbcConnection(getName(), getDefaultCachePolicy(),
driverProvider.getConnection(), rootUuid);
}
} catch (Exception e) {
errMsg =
JdbcMetadataI18n.unableToGetConnectionUsingDataSource.text(getName(),
getDataSourceName());
throw new RepositorySourceException(errMsg, e);
}
-
+
// Either data source name or JDBC driver connection properties must be defined
errMsg = JdbcMetadataI18n.oneOfPropertiesIsRequired.text(getName());
throw new RepositorySourceException(errMsg);
@@ -197,6 +192,14 @@
/**
* {@inheritDoc}
*
+ * @see org.jboss.dna.graph.connector.RepositorySource#close()
+ */
+ public synchronized void close() {
+ }
+
+ /**
+ * {@inheritDoc}
+ *
* @see org.jboss.dna.graph.connector.RepositorySource#getName()
*/
public String getName() {
@@ -278,7 +281,7 @@
* @return rootNodeUuid
*/
public String getRootNodeUuid() {
- return rootUuid != null? rootUuid.toString() : null;
+ return rootUuid != null ? rootUuid.toString() : null;
}
/**
@@ -289,7 +292,7 @@
if (rootNodeUuid != null && rootNodeUuid.trim().length() == 0)
rootNodeUuid = DEFAULT_ROOT_NODE_UUID;
this.rootUuid = UUID.fromString(rootNodeUuid);
}
-
+
/**
* {@inheritDoc}
*/
@@ -316,10 +319,10 @@
public String getDriverClassName() {
// get provider
DriverDatabaseMetadataProvider provider = getDriverProvider(false);
- // return
- return (provider != null)? provider.getDriverClassName() : null;
+ // return
+ return (provider != null) ? provider.getDriverClassName() : null;
}
-
+
/**
* Sets JDBC driver class name
*
@@ -335,7 +338,7 @@
provider.setDriverClassName(driverClassName);
}
}
-
+
/**
* Gets database URL as string
*
@@ -344,8 +347,8 @@
public String getDatabaseUrl() {
// get provider
DriverDatabaseMetadataProvider provider = getDriverProvider(false);
- // return
- return (provider != null)? provider.getDatabaseUrl() : null;
+ // return
+ return (provider != null) ? provider.getDatabaseUrl() : null;
}
/**
@@ -363,7 +366,7 @@
provider.setDatabaseUrl(databaseUrl);
}
}
-
+
/**
* Gets the user name
*
@@ -372,7 +375,7 @@
public String getUserName() {
// get provider
DriverDatabaseMetadataProvider provider = getDriverProvider(false);
- return (provider != null)? provider.getUserName() : null;
+ return (provider != null) ? provider.getUserName() : null;
}
/**
@@ -389,7 +392,7 @@
provider.setUserName(userName);
}
}
-
+
/**
* Get user's password
*
@@ -398,8 +401,8 @@
public String getPassword() {
// get provider
DriverDatabaseMetadataProvider provider = getDriverProvider(false);
- return (provider != null)? provider.getPassword() : null;
- }
+ return (provider != null) ? provider.getPassword() : null;
+ }
/**
* Sets the user's password
@@ -415,7 +418,7 @@
provider.setPassword(password);
}
}
-
+
/**
* Sets data source JNDI name
*
@@ -424,7 +427,7 @@
public String getDataSourceName() {
// get provider
DataSourceDatabaseMetadataProvider provider = getDataSourceProvider(false);
- return (provider != null)? provider.getDataSourceName() : null;
+ return (provider != null) ? provider.getDataSourceName() : null;
}
/**
@@ -441,7 +444,7 @@
provider.setDataSourceName(dataSourceName);
}
}
-
+
/**
* {@inheritDoc}
*
@@ -455,29 +458,29 @@
if (getName() != null) {
ref.add(new StringRefAddr(SOURCE_NAME, getName()));
}
-
+
if (getRootNodeUuid() != null) {
ref.add(new StringRefAddr(ROOT_NODE_UUID, getRootNodeUuid()));
}
if (getDataSourceName() != null) {
ref.add(new StringRefAddr(DATA_SOURCE_JNDI_NAME, getDataSourceName()));
}
-
+
if (getUserName() != null) {
ref.add(new StringRefAddr(USERNAME, getUserName()));
}
-
+
if (getPassword() != null) {
ref.add(new StringRefAddr(PASSWORD, getPassword()));
}
-
+
if (getDatabaseUrl() != null) {
ref.add(new StringRefAddr(URL, getDatabaseUrl()));
}
if (getDriverClassName() != null) {
ref.add(new StringRefAddr(DRIVER_CLASS_NAME, getDriverClassName()));
}
-
+
if (getDefaultCachePolicy() != null) {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
CachePolicy policy = getDefaultCachePolicy();
@@ -535,7 +538,7 @@
String password = (String)values.get(PASSWORD);
String url = (String)values.get(URL);
String driverClassName = (String)values.get(DRIVER_CLASS_NAME);
-
+
Object defaultCachePolicy = values.get(DEFAULT_CACHE_POLICY);
String retryLimit = (String)values.get(RETRY_LIMIT);
Added:
trunk/extensions/dna-connector-store-jpa/src/main/java/org/jboss/dna/connector/store/jpa/EntityManagers.java
===================================================================
---
trunk/extensions/dna-connector-store-jpa/src/main/java/org/jboss/dna/connector/store/jpa/EntityManagers.java
(rev 0)
+++
trunk/extensions/dna-connector-store-jpa/src/main/java/org/jboss/dna/connector/store/jpa/EntityManagers.java 2009-09-03
16:11:39 UTC (rev 1190)
@@ -0,0 +1,151 @@
+/*
+ * JBoss DNA (
http://www.jboss.org/dna)
+ * See the COPYRIGHT.txt file distributed with this work for information
+ * regarding copyright ownership. Some portions may be licensed
+ * to Red Hat, Inc. under one or more contributor license agreements.
+ * See the AUTHORS.txt file in the distribution for a full listing of
+ * individual contributors.
+ *
+ * JBoss DNA is free software. Unless otherwise indicated, all code in JBoss DNA
+ * is licensed to you 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.
+ *
+ * JBoss DNA is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site:
http://www.fsf.org.
+ */
+package org.jboss.dna.connector.store.jpa;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.concurrent.atomic.AtomicInteger;
+import javax.persistence.EntityManager;
+import javax.persistence.EntityManagerFactory;
+import net.jcip.annotations.ThreadSafe;
+import org.hibernate.ejb.Ejb3Configuration;
+
+/**
+ * Utility class that owns an {@link EntityManagerFactory} instance and that provides
references to {@link EntityManager}
+ * instances while providing the ability to properly clean up all resources by closing
the EntityManager and EntityManagerFactory
+ * objects when no longer needed.
+ * <p>
+ * This class is instantiated by the {@link JpaSource} and passed to the {@link
JpaConnection} objects, which use this class to
+ * obtain an EntityManager. When the JpaConnection object is {@link JpaConnection#close()
closed}, it returns the EntityManager to
+ * this object. Because this class maintains a count of the EntityManager references
handed out, the last EntityManager to be
+ * returned will cause the EntityManagerFactory to be closed.
+ * </p>
+ * <p>
+ * This class does put the EntityManager implementations inside a HashMap, and therefore
does expect that the EntityManager uses
+ * object equality for <code>equals</code>.
+ * </p>
+ */
+@ThreadSafe
+class EntityManagers {
+
+ private final Ejb3Configuration configuration;
+ private final Map<EntityManager, AtomicInteger> referenceCounts = new
HashMap<EntityManager, AtomicInteger>();
+ private EntityManagerFactory factory;
+ private boolean canClose;
+
+ EntityManagers( Ejb3Configuration configuration ) {
+ this.configuration = configuration;
+ }
+
+ /**
+ * Check out an EntityManager instance. The resulting manager <i>must</i>
be returned with {@link #checkin(EntityManager)}. In
+ * fact, for every {@link #checkout()} call, there must be a corresponding {@link
#checkin(EntityManager)} call with the
+ * checked out EntityManager.
+ * <p>
+ * Note that this class may return the same EntityManager for multiple calls, but
this should not matter to the caller.
+ * </p>
+ *
+ * @return the entity manager; never null
+ */
+ public synchronized EntityManager checkout() {
+ if (factory == null) {
+ // Create the factory ...
+ factory = configuration.buildEntityManagerFactory();
+ assert referenceCounts.isEmpty();
+ canClose = false;
+ }
+ // Create the entity manager and increment the reference count ...
+ EntityManager manager = factory.createEntityManager();
+ if (referenceCounts.containsKey(manager)) {
+ referenceCounts.get(manager).incrementAndGet();
+ } else {
+ referenceCounts.put(manager, new AtomicInteger(1));
+ }
+ return manager;
+ }
+
+ /**
+ * Return an EntityManager when it is no longer needed. This method should be called
once supplying the same EntityManager
+ * instance returned from a {@link #checkout()} call. In fact, for every {@link
#checkout()} call, there must be a
+ * corresponding {@link #checkin(EntityManager)} call with the checked out
EntityManager.
+ * <p>
+ * If this is the last reference to the EntityManager instance, it will be closed.
+ * </p>
+ *
+ * @param manager the entity manager; may not be null and must be the result of a
prior {@link #checkout()} call
+ */
+ public synchronized void checkin( EntityManager manager ) {
+ if (manager == null) return;
+ // Decrement the reference count ...
+ AtomicInteger count = referenceCounts.get(manager);
+ assert count != null;
+ count.decrementAndGet();
+ assert count.get() >= 0;
+ if (count.get() == 0) {
+ // Need to remove this manager ...
+ if (referenceCounts.remove(manager) != null) {
+ // And close the manager ...
+ manager.close();
+ }
+ }
+ // If there are no more entity managers checkout out, close the factory ...
+ closeFactoryIfNoManagersCheckedOut();
+ }
+
+ public synchronized void close() {
+ canClose = true;
+ closeFactoryIfNoManagersCheckedOut();
+ }
+
+ /**
+ * For all opened EntityManager instances to be closed immediately, even if they are
checked out. This should be called with
+ * caution, since all EntityManager and EntityManagerFactory instances will be closed
when no longer used - as long as the
+ * {@link #checkout() checkout}/{@link #checkin(EntityManager) checkin} pattern is
always used.
+ */
+ public synchronized void closeNow() {
+ canClose = true;
+ try {
+ for (EntityManager manager : referenceCounts.keySet()) {
+ manager.close();
+ }
+ referenceCounts.clear();
+ } finally {
+ try {
+ factory.close(); // This implicitly closes all EntityManagers that are
still opened
+ } finally {
+ factory = null;
+ }
+ }
+ }
+
+ private void closeFactoryIfNoManagersCheckedOut() {
+ if (referenceCounts.isEmpty() && canClose) {
+ try {
+ factory.close();
+ } finally {
+ factory = null;
+ }
+ }
+ }
+}
Property changes on:
trunk/extensions/dna-connector-store-jpa/src/main/java/org/jboss/dna/connector/store/jpa/EntityManagers.java
___________________________________________________________________
Name: svn:keywords
+ Id Revision
Name: svn:eol-style
+ LF
Modified:
trunk/extensions/dna-connector-store-jpa/src/main/java/org/jboss/dna/connector/store/jpa/JpaConnection.java
===================================================================
---
trunk/extensions/dna-connector-store-jpa/src/main/java/org/jboss/dna/connector/store/jpa/JpaConnection.java 2009-09-03
14:52:15 UTC (rev 1189)
+++
trunk/extensions/dna-connector-store-jpa/src/main/java/org/jboss/dna/connector/store/jpa/JpaConnection.java 2009-09-03
16:11:39 UTC (rev 1190)
@@ -42,7 +42,8 @@
private final String name;
private final CachePolicy cachePolicy;
- private final EntityManager entityManager;
+ private final EntityManagers entityManagers;
+ private EntityManager entityManager;
private final Model model;
private final UUID rootNodeUuid;
private final String nameOfDefaultWorkspace;
@@ -56,7 +57,7 @@
/*package*/JpaConnection( String sourceName,
Observer observer,
CachePolicy cachePolicy,
- EntityManager entityManager,
+ EntityManagers entityManagers,
Model model,
UUID rootNodeUuid,
String nameOfDefaultWorkspace,
@@ -66,13 +67,15 @@
boolean compressData,
boolean enforceReferentialIntegrity ) {
assert sourceName != null;
- assert entityManager != null;
+ assert entityManagers != null;
assert model != null;
assert rootNodeUuid != null;
this.observer = observer;
this.name = sourceName;
this.cachePolicy = cachePolicy; // may be null
- this.entityManager = entityManager;
+ this.entityManagers = entityManagers;
+ this.entityManager = entityManagers.checkout();
+ assert this.entityManagers != null;
this.model = model;
this.rootNodeUuid = rootNodeUuid;
this.largeValueMinimumSizeInBytes = largeValueMinimumSizeInBytes;
@@ -117,7 +120,7 @@
*/
public boolean ping( long time,
TimeUnit unit ) {
- return entityManager.isOpen();
+ return entityManager != null ? entityManager.isOpen() : false;
}
/**
@@ -129,6 +132,9 @@
public void execute( ExecutionContext context,
Request request ) throws RepositorySourceException {
long size = largeValueMinimumSizeInBytes;
+ if (entityManager == null) {
+ throw new
RepositorySourceException(JpaConnectorI18n.connectionIsNoLongerOpen.text(name));
+ }
RequestProcessor proc = model.createRequestProcessor(name,
context,
observer,
@@ -153,6 +159,14 @@
* @see org.jboss.dna.graph.connector.RepositoryConnection#close()
*/
public void close() {
+ if (entityManager != null) {
+ // Do this only once ...
+ try {
+ entityManagers.checkin(entityManager);
+ } finally {
+ entityManager = null;
+ }
+ }
}
}
Modified:
trunk/extensions/dna-connector-store-jpa/src/main/java/org/jboss/dna/connector/store/jpa/JpaConnectorI18n.java
===================================================================
---
trunk/extensions/dna-connector-store-jpa/src/main/java/org/jboss/dna/connector/store/jpa/JpaConnectorI18n.java 2009-09-03
14:52:15 UTC (rev 1189)
+++
trunk/extensions/dna-connector-store-jpa/src/main/java/org/jboss/dna/connector/store/jpa/JpaConnectorI18n.java 2009-09-03
16:11:39 UTC (rev 1190)
@@ -50,6 +50,7 @@
public static I18n workspaceAlreadyExists;
public static I18n workspaceDoesNotExist;
public static I18n unableToCreateWorkspaces;
+ public static I18n connectionIsNoLongerOpen;
public static I18n basicModelDescription;
Modified:
trunk/extensions/dna-connector-store-jpa/src/main/java/org/jboss/dna/connector/store/jpa/JpaSource.java
===================================================================
---
trunk/extensions/dna-connector-store-jpa/src/main/java/org/jboss/dna/connector/store/jpa/JpaSource.java 2009-09-03
14:52:15 UTC (rev 1189)
+++
trunk/extensions/dna-connector-store-jpa/src/main/java/org/jboss/dna/connector/store/jpa/JpaSource.java 2009-09-03
16:11:39 UTC (rev 1190)
@@ -210,7 +210,7 @@
private volatile String modelName;
private transient Model model;
private transient DataSource dataSource;
- private transient EntityManagerFactory entityManagerFactory;
+ private transient EntityManagers entityManagers;
private transient CachePolicy cachePolicy;
private transient RepositoryContext repositoryContext;
private transient UUID rootUuid = UUID.fromString(rootNodeUuid);
@@ -861,14 +861,12 @@
}
assert rootNodeUuid != null;
assert rootUuid != null;
- EntityManager entityManager = null;
- if (entityManagerFactory == null || !entityManagerFactory.isOpen()) {
+ if (entityManagers == null) {
// Create the JPA EntityManagerFactory by programmatically configuring
Hibernate Entity Manager ...
Ejb3Configuration configurator = new Ejb3Configuration();
// Configure the entity classes ...
configurator.addAnnotatedClass(StoreOptionEntity.class);
- if (model != null) model.configure(configurator);
// Configure additional properties, which may be overridden by subclasses
...
configure(configurator);
@@ -913,56 +911,75 @@
setProperty(configurator, "hibernate.show_sql",
String.valueOf(this.showSql));
}
- entityManagerFactory = configurator.buildEntityManagerFactory();
+ EntityManagerFactory entityManagerFactory =
configurator.buildEntityManagerFactory();
+ try {
+ // Establish a connection and obtain the store options...
+ EntityManager entityManager =
entityManagerFactory.createEntityManager();
+ try {
- // Establish a connection and obtain the store options...
- entityManager = entityManagerFactory.createEntityManager();
+ // Find and update/set the root node's UUID ...
+ StoreOptions options = new StoreOptions(entityManager);
+ UUID actualUuid = options.getRootNodeUuid();
+ if (actualUuid != null) {
+ this.setRootNodeUuid(actualUuid.toString());
+ } else {
+ options.setRootNodeUuid(this.rootUuid);
+ }
- // Find and update/set the root node's UUID ...
- StoreOptions options = new StoreOptions(entityManager);
- UUID actualUuid = options.getRootNodeUuid();
- if (actualUuid != null) {
- this.setRootNodeUuid(actualUuid.toString());
- } else {
- options.setRootNodeUuid(this.rootUuid);
- }
-
- // Find or set the type of model that will be used.
- String actualModelName = options.getModelName();
- if (actualModelName == null) {
- // This is a new store, so set to the specified model ...
- if (model == null) setModel(Models.DEFAULT.getName());
- assert model != null;
- options.setModelName(model);
- } else {
- try {
- setModel(actualModelName);
- } catch (Throwable e) {
- // The actual model name doesn't match what's available in
the software ...
+ // Find or set the type of model that will be used.
+ String actualModelName = options.getModelName();
+ if (actualModelName == null) {
+ // This is a new store, so set to the specified model ...
+ if (model == null) setModel(Models.DEFAULT.getName());
+ assert model != null;
+ options.setModelName(model);
+ } else {
+ // Set the model to the what's listed in the database ...
+ try {
+ setModel(actualModelName);
+ } catch (Throwable e) {
+ // The actual model name doesn't match what's
available in the software ...
+ String msg =
JpaConnectorI18n.existingStoreSpecifiesUnknownModel.text(name, actualModelName);
+ throw new RepositorySourceException(msg);
+ }
+ }
+ } finally {
entityManager.close();
- entityManagerFactory.close();
- String msg =
JpaConnectorI18n.existingStoreSpecifiesUnknownModel.text(name, actualModelName);
- throw new RepositorySourceException(msg);
}
+ } finally {
+ entityManagerFactory.close();
}
- entityManager.close();
- entityManagerFactory.close();
- // Now, create another entity manager with the classes from the correct
model
+ // The model has not yet configured itself, so do that now ...
model.configure(configurator);
- entityManagerFactory = configurator.buildEntityManagerFactory();
- entityManager = entityManagerFactory.createEntityManager();
+
+ // Now, create another entity manager with the classes from the correct model
and without changing the schema...
+ entityManagers = new EntityManagers(configurator);
}
- if (entityManager == null) {
- entityManager = entityManagerFactory.createEntityManager();
- }
Observer observer = repositoryContext != null ? repositoryContext.getObserver() :
null;
- return new JpaConnection(getName(), observer, cachePolicy, entityManager, model,
rootUuid, defaultWorkspace,
+ return new JpaConnection(getName(), observer, cachePolicy, entityManagers, model,
rootUuid, defaultWorkspace,
getPredefinedWorkspaceNames(), largeValueSizeInBytes,
isCreatingWorkspacesAllowed(),
compressData, referentialIntegrityEnforced);
}
/**
+ * {@inheritDoc}
+ *
+ * @see org.jboss.dna.graph.connector.RepositorySource#close()
+ */
+ public synchronized void close() {
+ if (entityManagers != null) {
+ try {
+ // Close this object; existing connections will continue to work, and the
last connection closed
+ // will actually shut the lights off...
+ entityManagers.close();
+ } finally {
+ entityManagers = null;
+ }
+ }
+ }
+
+ /**
* Set up the JPA configuration using Hibernate, except for the entity classes (which
will already be configured when this
* method is called) and the data source or connection information (which will be set
after this method returns). Subclasses
* may override this method to customize the configuration.
@@ -993,19 +1010,6 @@
setProperty(configuration, "hibernate.hbm2ddl.auto",
"create");
}
- /**
- * Close any resources held by this source. This will ensure that all connections are
closed.
- */
- public synchronized void close() {
- if (entityManagerFactory != null) {
- try {
- entityManagerFactory.close();
- } finally {
- entityManagerFactory = null;
- }
- }
- }
-
protected void setProperty( Ejb3Configuration configurator,
String propertyName,
String propertyValue ) {
Modified:
trunk/extensions/dna-connector-store-jpa/src/main/resources/org/jboss/dna/connector/store/jpa/JpaConnectorI18n.properties
===================================================================
---
trunk/extensions/dna-connector-store-jpa/src/main/resources/org/jboss/dna/connector/store/jpa/JpaConnectorI18n.properties 2009-09-03
14:52:15 UTC (rev 1189)
+++
trunk/extensions/dna-connector-store-jpa/src/main/resources/org/jboss/dna/connector/store/jpa/JpaConnectorI18n.properties 2009-09-03
16:11:39 UTC (rev 1190)
@@ -40,5 +40,6 @@
workspaceAlreadyExists = The source {0} already has a workspace named "{1}"
workspaceDoesNotExist = The source {0} has no workspace named "{1}"
unableToCreateWorkspaces = The source {0} does not allow creating workspaces
+connectionIsNoLongerOpen = This connection for source {0} has already been closed
basicModelDescription = Database model that stores node properties as opaque records and
children as transparent records. Large property values are stored separately.
Modified:
trunk/extensions/dna-connector-store-jpa/src/test/java/org/jboss/dna/connector/store/jpa/JpaSourceTest.java
===================================================================
---
trunk/extensions/dna-connector-store-jpa/src/test/java/org/jboss/dna/connector/store/jpa/JpaSourceTest.java 2009-09-03
14:52:15 UTC (rev 1189)
+++
trunk/extensions/dna-connector-store-jpa/src/test/java/org/jboss/dna/connector/store/jpa/JpaSourceTest.java 2009-09-03
16:11:39 UTC (rev 1190)
@@ -64,12 +64,8 @@
@After
public void afterEach() throws Exception {
- try {
- if (this.connection != null) {
- this.connection.close();
- }
- } finally {
- this.source.close();
+ if (this.connection != null) {
+ this.connection.close();
}
}
Modified:
trunk/extensions/dna-connector-svn/src/main/java/org/jboss/dna/connector/svn/SVNRepositorySource.java
===================================================================
---
trunk/extensions/dna-connector-svn/src/main/java/org/jboss/dna/connector/svn/SVNRepositorySource.java 2009-09-03
14:52:15 UTC (rev 1189)
+++
trunk/extensions/dna-connector-svn/src/main/java/org/jboss/dna/connector/svn/SVNRepositorySource.java 2009-09-03
16:11:39 UTC (rev 1190)
@@ -440,33 +440,32 @@
*
* @see org.jboss.dna.graph.connector.RepositorySource#getConnection()
*/
- public RepositoryConnection getConnection() throws RepositorySourceException {
-
+ public synchronized RepositoryConnection getConnection() throws
RepositorySourceException {
+
String sourceName = getName();
if (sourceName == null || sourceName.trim().length() == 0) {
I18n msg = SVNRepositoryConnectorI18n.propertyIsRequired;
throw new RepositorySourceException(getName(), msg.text("name"));
}
-
+
String sourceUsername = getUsername();
if (sourceUsername == null || sourceUsername.trim().length() == 0) {
I18n msg = SVNRepositoryConnectorI18n.propertyIsRequired;
throw new RepositorySourceException(getUsername(),
msg.text("username"));
}
-
+
String sourcePassword = getPassword();
if (sourcePassword == null) {
I18n msg = SVNRepositoryConnectorI18n.propertyIsRequired;
throw new RepositorySourceException(getPassword(),
msg.text("password"));
}
-
+
String repositoryRootURL = getRepositoryRootURL();
if (repositoryRootURL == null || repositoryRootURL.trim().length() == 0) {
I18n msg = SVNRepositoryConnectorI18n.propertyIsRequired;
throw new RepositorySourceException(getRepositoryRootURL(),
msg.text("repositoryRootURL"));
}
-
-
+
SVNRepository repos = null;
// Report the warnings for non-existant predefined workspaces
boolean reportWarnings = false;
@@ -494,7 +493,7 @@
url,
name);
}
- if (!SVNRepositoryUtil.isDirectory(repos,"")) {
+ if (!SVNRepositoryUtil.isDirectory(repos, "")) {
Logger.getLogger(getClass()).warn(SVNRepositoryConnectorI18n.pathForPredefinedWorkspaceIsNotDirectory,
url,
name);
@@ -515,13 +514,11 @@
String defaultURL = getDirectoryForDefaultWorkspace();
if (defaultURL != null) {
// Look for the entry at this path .....
- SVNRepository repository = SVNRepositoryUtil.createRepository(defaultURL,
- sourceUsername,
-
sourcePassword);
+ SVNRepository repository = SVNRepositoryUtil.createRepository(defaultURL,
sourceUsername, sourcePassword);
I18n warning = null;
if (!SVNRepositoryUtil.exist(repository)) {
warning =
SVNRepositoryConnectorI18n.pathForPredefinedWorkspaceDoesNotExist;
- } else if (!SVNRepositoryUtil.isDirectory(repository,"")) {
+ } else if (!SVNRepositoryUtil.isDirectory(repository, "")) {
warning =
SVNRepositoryConnectorI18n.pathForPredefinedWorkspaceIsNotDirectory;
} else {
// is a directory and is good to use!
@@ -537,6 +534,15 @@
sourceUsername, sourcePassword));
}
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.jboss.dna.graph.connector.RepositorySource#close()
+ */
+ public synchronized void close() {
+ this.availableWorspaceNames = null;
+ }
+
@Immutable
/* package */class SVNRepositoryCachePolicy implements CachePolicy {
private static final long serialVersionUID = 1L;