From 0baad6740a0e027f1e4ee073db445812cf69950f Mon Sep 17 00:00:00 2001
From: Mark Pollack
Date: Mon, 7 Mar 2011 14:54:12 -0500
Subject: [PATCH] Simple CouchDB integration
---
spring-data-couchdb/.classpath | 3 +
spring-data-couchdb/pom.xml | 70 +++-
.../CannotGetCouchDbConnectionException.java | 11 -
.../document/couchdb/CouchDbFactoryBean.java | 96 ------
.../CouchServerResourceUsageException.java | 33 ++
.../data/document/couchdb/CouchTemplate.java | 52 ---
.../document/couchdb/CouchUsageException.java | 35 ++
.../couchdb/DocumentExistsException.java | 34 ++
.../DocumentRetrievalFailureException.java | 38 ++
...UncategorizedCouchDataAccessException.java | 33 ++
.../document/couchdb/admin/CouchAdmin.java | 64 ++++
.../couchdb/admin/CouchAdminOperations.java | 34 ++
.../data/document/couchdb/admin/DbInfo.java | 77 +++++
.../couchdb/config/CouchJmxParser.java | 70 ++++
.../couchdb/config/CouchNamespaceHandler.java | 43 +++
.../couchdb/core/CouchOperations.java | 63 ++++
.../document/couchdb/core/CouchTemplate.java | 153 ++++++++
...hDbMappingJacksonHttpMessageConverter.java | 326 ++++++++++++++++++
.../couchdb/monitor/AbstractMonitor.java | 46 +++
.../document/couchdb/monitor/ServerInfo.java | 63 ++++
.../couchdb/monitor/package-info.java | 4 +
.../CouchUtils.java} | 49 ++-
.../main/resources/META-INF/spring.handlers | 1 +
.../main/resources/META-INF/spring.schemas | 2 +
.../main/resources/META-INF/spring.tooling | 4 +
.../couchdb/config/spring-couch-1.0.xsd | 33 ++
.../data/document/couchdb/DummyDocument.java | 77 +++++
.../data/document/couchdb/IsBodyEqual.java | 51 +++
.../admin/CouchAdminIntegrationTests.java | 37 ++
...AbstractCouchTemplateIntegrationTests.java | 124 +++++++
.../document/couchdb/core/CouchConstants.java | 27 ++
.../core/CouchTemplateIntegrationTests.java | 41 +++
.../couchdb/core/CouchTemplateTests.java | 32 ++
.../document/couchdb/monitor/JmxServer.java | 36 ++
.../src/test/resources/log4j.properties | 13 +
.../src/test/resources/server-jmx.xml | 25 ++
spring-data-couchdb/template.mf | 7 +-
spring-data-document-parent/pom.xml | 1 +
.../mongodb/analytics/MvcAnalyticsTests.java | 2 +
39 files changed, 1730 insertions(+), 180 deletions(-)
delete mode 100644 spring-data-couchdb/src/main/java/org/springframework/data/document/couchdb/CannotGetCouchDbConnectionException.java
delete mode 100644 spring-data-couchdb/src/main/java/org/springframework/data/document/couchdb/CouchDbFactoryBean.java
create mode 100644 spring-data-couchdb/src/main/java/org/springframework/data/document/couchdb/CouchServerResourceUsageException.java
delete mode 100644 spring-data-couchdb/src/main/java/org/springframework/data/document/couchdb/CouchTemplate.java
create mode 100644 spring-data-couchdb/src/main/java/org/springframework/data/document/couchdb/CouchUsageException.java
create mode 100644 spring-data-couchdb/src/main/java/org/springframework/data/document/couchdb/DocumentExistsException.java
create mode 100644 spring-data-couchdb/src/main/java/org/springframework/data/document/couchdb/DocumentRetrievalFailureException.java
create mode 100644 spring-data-couchdb/src/main/java/org/springframework/data/document/couchdb/UncategorizedCouchDataAccessException.java
create mode 100644 spring-data-couchdb/src/main/java/org/springframework/data/document/couchdb/admin/CouchAdmin.java
create mode 100644 spring-data-couchdb/src/main/java/org/springframework/data/document/couchdb/admin/CouchAdminOperations.java
create mode 100644 spring-data-couchdb/src/main/java/org/springframework/data/document/couchdb/admin/DbInfo.java
create mode 100644 spring-data-couchdb/src/main/java/org/springframework/data/document/couchdb/config/CouchJmxParser.java
create mode 100644 spring-data-couchdb/src/main/java/org/springframework/data/document/couchdb/config/CouchNamespaceHandler.java
create mode 100644 spring-data-couchdb/src/main/java/org/springframework/data/document/couchdb/core/CouchOperations.java
create mode 100644 spring-data-couchdb/src/main/java/org/springframework/data/document/couchdb/core/CouchTemplate.java
create mode 100644 spring-data-couchdb/src/main/java/org/springframework/data/document/couchdb/core/support/CouchDbMappingJacksonHttpMessageConverter.java
create mode 100644 spring-data-couchdb/src/main/java/org/springframework/data/document/couchdb/monitor/AbstractMonitor.java
create mode 100644 spring-data-couchdb/src/main/java/org/springframework/data/document/couchdb/monitor/ServerInfo.java
create mode 100644 spring-data-couchdb/src/main/java/org/springframework/data/document/couchdb/monitor/package-info.java
rename spring-data-couchdb/src/main/java/org/springframework/data/document/couchdb/{CouchDbUtils.java => support/CouchUtils.java} (61%)
create mode 100644 spring-data-couchdb/src/main/resources/META-INF/spring.handlers
create mode 100644 spring-data-couchdb/src/main/resources/META-INF/spring.schemas
create mode 100644 spring-data-couchdb/src/main/resources/META-INF/spring.tooling
create mode 100644 spring-data-couchdb/src/main/resources/org/springframework/data/document/couchdb/config/spring-couch-1.0.xsd
create mode 100644 spring-data-couchdb/src/test/java/org/springframework/data/document/couchdb/DummyDocument.java
create mode 100644 spring-data-couchdb/src/test/java/org/springframework/data/document/couchdb/IsBodyEqual.java
create mode 100644 spring-data-couchdb/src/test/java/org/springframework/data/document/couchdb/admin/CouchAdminIntegrationTests.java
create mode 100644 spring-data-couchdb/src/test/java/org/springframework/data/document/couchdb/core/AbstractCouchTemplateIntegrationTests.java
create mode 100644 spring-data-couchdb/src/test/java/org/springframework/data/document/couchdb/core/CouchConstants.java
create mode 100644 spring-data-couchdb/src/test/java/org/springframework/data/document/couchdb/core/CouchTemplateIntegrationTests.java
create mode 100644 spring-data-couchdb/src/test/java/org/springframework/data/document/couchdb/core/CouchTemplateTests.java
create mode 100644 spring-data-couchdb/src/test/java/org/springframework/data/document/couchdb/monitor/JmxServer.java
create mode 100644 spring-data-couchdb/src/test/resources/log4j.properties
create mode 100644 spring-data-couchdb/src/test/resources/server-jmx.xml
diff --git a/spring-data-couchdb/.classpath b/spring-data-couchdb/.classpath
index 0bb7ad5ca..2064dbb9b 100644
--- a/spring-data-couchdb/.classpath
+++ b/spring-data-couchdb/.classpath
@@ -1,6 +1,9 @@
+
+
+
diff --git a/spring-data-couchdb/pom.xml b/spring-data-couchdb/pom.xml
index e9fbd9cbb..6914e22c0 100644
--- a/spring-data-couchdb/pom.xml
+++ b/spring-data-couchdb/pom.xml
@@ -10,6 +10,43 @@
spring-data-couchdbjarSpring Data CouchDB Support
+
+
+
+
+ The Apache Software License, Version 2.0
+ http://www.apache.org/licenses/LICENSE-2.0.txt
+ repo
+
+
+
+
+
+ tareq.abedrabbo
+ Tareq Abedrabbo
+ tareq.abedrabbo@opencredo.com
+ OpenCredo
+ http://www.opencredo.org
+
+ Project Admin
+ Developer
+
+ +0
+
+
+ tomas.lukosius
+ Tomas Lukosius
+ tomas.lukosius@opencredo.com
+ OpenCredo
+ http://www.opencredo.org
+
+ Project Admin
+ Developer
+
+ +0
+
+
+
@@ -21,6 +58,12 @@
org.springframeworkspring-tx
+
+
+ org.springframework
+ spring-test
+ test
+
@@ -28,6 +71,18 @@
spring-data-document-core
+
+
+ org.codehaus.jackson
+ jackson-core-asl
+ 1.6.1
+
+
+ org.codehaus.jackson
+ jackson-mapper-asl
+ 1.6.1
+
+
org.slf4j
@@ -82,16 +137,18 @@
junitjunit
+ test
-
-
+
- com.google.code.jcouchdb
- jcouchdb
- 0.11.0-1
-
+ org.hamcrest
+ hamcrest-all
+ 1.1
+ test
+
+
diff --git a/spring-data-couchdb/src/main/java/org/springframework/data/document/couchdb/CannotGetCouchDbConnectionException.java b/spring-data-couchdb/src/main/java/org/springframework/data/document/couchdb/CannotGetCouchDbConnectionException.java
deleted file mode 100644
index a2fb40054..000000000
--- a/spring-data-couchdb/src/main/java/org/springframework/data/document/couchdb/CannotGetCouchDbConnectionException.java
+++ /dev/null
@@ -1,11 +0,0 @@
-package org.springframework.data.document.couchdb;
-
-import org.springframework.dao.DataAccessResourceFailureException;
-
-public class CannotGetCouchDbConnectionException extends DataAccessResourceFailureException {
-
- public CannotGetCouchDbConnectionException(String msg, Throwable cause) {
- super(msg, cause);
- }
-
-}
diff --git a/spring-data-couchdb/src/main/java/org/springframework/data/document/couchdb/CouchDbFactoryBean.java b/spring-data-couchdb/src/main/java/org/springframework/data/document/couchdb/CouchDbFactoryBean.java
deleted file mode 100644
index e243dee4c..000000000
--- a/spring-data-couchdb/src/main/java/org/springframework/data/document/couchdb/CouchDbFactoryBean.java
+++ /dev/null
@@ -1,96 +0,0 @@
-/*
- * Copyright 2010 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.springframework.data.document.couchdb;
-
-import org.jcouchdb.db.Database;
-import org.springframework.beans.factory.FactoryBean;
-import org.springframework.beans.factory.InitializingBean;
-import org.springframework.dao.DataAccessException;
-import org.springframework.dao.support.PersistenceExceptionTranslator;
-import org.springframework.util.Assert;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-
-/**
- * Convenient factory for configuring MongoDB.
- *
- * @author Thomas Risberg
- * @since 1.0
- */
-public class CouchDbFactoryBean implements FactoryBean, InitializingBean,
- PersistenceExceptionTranslator {
-
- /**
- * Logger, available to subclasses.
- */
- protected final Log logger = LogFactory.getLog(getClass());
-
- private String host;
- private Integer port;
- private String databaseName;
-
- public void setDatabaseName(String databaseName) {
- this.databaseName = databaseName;
- }
-
- public void setHost(String host) {
- this.host = host;
- }
-
- public void setPort(int port) {
- this.port = port;
- }
-
- public Database getObject() throws Exception {
- Assert.hasText(host, "Host must not be empty");
- Assert.hasText(databaseName, "Database name must not be empty");
- if (port == null) {
- return new Database(host, databaseName);
- }
- else {
- return new Database(host, port, databaseName);
- }
- }
-
- public Class extends Database> getObjectType() {
- return Database.class;
- }
-
- public boolean isSingleton() {
- return false;
- }
-
- public void afterPropertiesSet() throws Exception {
- // apply defaults - convenient when used to configure for tests
- // in an application context
- if (host == null) {
- logger.warn("Property host not specified. Using default 'localhost'");
- databaseName = "localhost";
- }
- if (databaseName == null) {
- logger.warn("Property databaseName not specified. Using default name 'test'");
- databaseName = "test";
- }
- }
-
- public DataAccessException translateExceptionIfPossible(RuntimeException ex) {
- logger.debug("Translating " + ex);
- return CouchDbUtils.translateCouchExceptionIfPossible(ex);
- }
-
-}
diff --git a/spring-data-couchdb/src/main/java/org/springframework/data/document/couchdb/CouchServerResourceUsageException.java b/spring-data-couchdb/src/main/java/org/springframework/data/document/couchdb/CouchServerResourceUsageException.java
new file mode 100644
index 000000000..ce8dee340
--- /dev/null
+++ b/spring-data-couchdb/src/main/java/org/springframework/data/document/couchdb/CouchServerResourceUsageException.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2011 the original author or authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.springframework.data.document.couchdb;
+
+import org.springframework.dao.InvalidDataAccessResourceUsageException;
+import org.springframework.web.client.HttpServerErrorException;
+
+public class CouchServerResourceUsageException extends InvalidDataAccessResourceUsageException {
+
+ /**
+ * Create a new CouchServerResourceUsageException,
+ * wrapping an arbitrary HttpServerErrorException.
+ * @param cause the HttpServerErrorException thrown
+ */
+ public CouchServerResourceUsageException(HttpServerErrorException cause) {
+ super(cause != null ? cause.getMessage() : null, cause);
+ }
+
+}
+
diff --git a/spring-data-couchdb/src/main/java/org/springframework/data/document/couchdb/CouchTemplate.java b/spring-data-couchdb/src/main/java/org/springframework/data/document/couchdb/CouchTemplate.java
deleted file mode 100644
index 0e646ab02..000000000
--- a/spring-data-couchdb/src/main/java/org/springframework/data/document/couchdb/CouchTemplate.java
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * Copyright 2010 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.springframework.data.document.couchdb;
-
-
-import org.jcouchdb.db.Database;
-import org.jcouchdb.document.BaseDocument;
-import org.springframework.data.document.AbstractDocumentStoreTemplate;
-
- public class CouchTemplate extends AbstractDocumentStoreTemplate {
-
- private Database database;
-
- public CouchTemplate() {
- super();
- }
-
- public CouchTemplate(String host, String databaseName) {
- super();
- database = new Database(host, databaseName);
- }
-
- public CouchTemplate(Database database) {
- super();
- this.database = database;
- }
-
- public void save(BaseDocument document) {
- getConnection().createDocument(document);
- }
-
- @Override
- public Database getConnection() {
- return database;
- }
-
-
-}
diff --git a/spring-data-couchdb/src/main/java/org/springframework/data/document/couchdb/CouchUsageException.java b/spring-data-couchdb/src/main/java/org/springframework/data/document/couchdb/CouchUsageException.java
new file mode 100644
index 000000000..95f17ef92
--- /dev/null
+++ b/spring-data-couchdb/src/main/java/org/springframework/data/document/couchdb/CouchUsageException.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2011 the original author or authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.springframework.data.document.couchdb;
+
+import org.springframework.dao.InvalidDataAccessApiUsageException;
+import org.springframework.web.client.HttpClientErrorException;
+import org.springframework.web.client.HttpServerErrorException;
+
+public class CouchUsageException extends InvalidDataAccessApiUsageException
+ {
+
+ /**
+ * Create a new CouchUsageException,
+ * wrapping an arbitrary HttpServerErrorException.
+ * @param cause the HttpServerErrorException thrown
+ */
+ public CouchUsageException(HttpClientErrorException cause) {
+ super(cause != null ? cause.getMessage() : null, cause);
+ }
+
+}
+
diff --git a/spring-data-couchdb/src/main/java/org/springframework/data/document/couchdb/DocumentExistsException.java b/spring-data-couchdb/src/main/java/org/springframework/data/document/couchdb/DocumentExistsException.java
new file mode 100644
index 000000000..d564211a8
--- /dev/null
+++ b/spring-data-couchdb/src/main/java/org/springframework/data/document/couchdb/DocumentExistsException.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2011 the original author or authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.springframework.data.document.couchdb;
+
+import org.springframework.dao.DataIntegrityViolationException;
+import org.springframework.web.client.HttpStatusCodeException;
+
+public class DocumentExistsException extends DataIntegrityViolationException
+ {
+
+ /**
+ * Create a new DocumentExistsException,
+ * wrapping an arbitrary HttpServerErrorException.
+ * @param cause the HttpServerErrorException thrown
+ */
+ public DocumentExistsException(String documentId, HttpStatusCodeException cause) {
+ super(cause != null ? cause.getMessage() : null, cause);
+ }
+
+}
+
diff --git a/spring-data-couchdb/src/main/java/org/springframework/data/document/couchdb/DocumentRetrievalFailureException.java b/spring-data-couchdb/src/main/java/org/springframework/data/document/couchdb/DocumentRetrievalFailureException.java
new file mode 100644
index 000000000..c35a1ff6d
--- /dev/null
+++ b/spring-data-couchdb/src/main/java/org/springframework/data/document/couchdb/DocumentRetrievalFailureException.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.springframework.data.document.couchdb;
+
+import org.springframework.dao.DataRetrievalFailureException;
+
+public class DocumentRetrievalFailureException extends
+ DataRetrievalFailureException {
+
+ private String documentPath;
+
+ public DocumentRetrievalFailureException(String documentPath) {
+ super("Could not find document at path = " + documentPath);
+ this.documentPath = documentPath;
+ }
+
+ public String getDocumentPath() {
+ return documentPath;
+ }
+
+
+
+
+
+}
diff --git a/spring-data-couchdb/src/main/java/org/springframework/data/document/couchdb/UncategorizedCouchDataAccessException.java b/spring-data-couchdb/src/main/java/org/springframework/data/document/couchdb/UncategorizedCouchDataAccessException.java
new file mode 100644
index 000000000..d951e5353
--- /dev/null
+++ b/spring-data-couchdb/src/main/java/org/springframework/data/document/couchdb/UncategorizedCouchDataAccessException.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2011 the original author or authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.springframework.data.document.couchdb;
+
+import org.springframework.dao.UncategorizedDataAccessException;
+import org.springframework.web.client.RestClientException;
+
+public class UncategorizedCouchDataAccessException extends UncategorizedDataAccessException {
+
+ /**
+ * Create a new HibernateSystemException,
+ * wrapping an arbitrary HibernateException.
+ * @param cause the HibernateException thrown
+ */
+ public UncategorizedCouchDataAccessException(RestClientException cause) {
+ super(cause != null ? cause.getMessage() : null, cause);
+ }
+
+}
+
diff --git a/spring-data-couchdb/src/main/java/org/springframework/data/document/couchdb/admin/CouchAdmin.java b/spring-data-couchdb/src/main/java/org/springframework/data/document/couchdb/admin/CouchAdmin.java
new file mode 100644
index 000000000..f9c0eb62d
--- /dev/null
+++ b/spring-data-couchdb/src/main/java/org/springframework/data/document/couchdb/admin/CouchAdmin.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright 2011 the original author or authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.springframework.data.document.couchdb.admin;
+
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+
+import org.springframework.data.document.couchdb.support.CouchUtils;
+import org.springframework.util.StringUtils;
+import org.springframework.web.client.RestOperations;
+import org.springframework.web.client.RestTemplate;
+
+public class CouchAdmin implements CouchAdminOperations {
+
+ private String databaseUrl;
+ private RestOperations restOperations = new RestTemplate();
+
+ public CouchAdmin(String databaseUrl) {
+
+ if (!databaseUrl.trim().endsWith("/")) {
+ this.databaseUrl = databaseUrl.trim() + "/";
+ } else {
+ this.databaseUrl = databaseUrl.trim();
+ }
+ }
+
+ public List listDatabases() {
+ String dbs = restOperations.getForObject(databaseUrl + "_all_dbs", String.class);
+ return Arrays.asList(StringUtils.commaDelimitedListToStringArray(dbs));
+ }
+
+ public void createDatabase(String dbName) {
+ org.springframework.util.Assert.hasText(dbName);
+ restOperations.put(databaseUrl + dbName, null);
+
+ }
+
+ public void deleteDatabase(String dbName) {
+ org.springframework.util.Assert.hasText(dbName);
+ restOperations.delete(CouchUtils.ensureTrailingSlash(databaseUrl + dbName));
+
+ }
+
+ public DbInfo getDatabaseInfo(String dbName) {
+ String url = CouchUtils.ensureTrailingSlash(databaseUrl + dbName);
+ Map dbInfoMap = (Map) restOperations.getForObject(url, Map.class);
+ return new DbInfo(dbInfoMap);
+ }
+
+}
\ No newline at end of file
diff --git a/spring-data-couchdb/src/main/java/org/springframework/data/document/couchdb/admin/CouchAdminOperations.java b/spring-data-couchdb/src/main/java/org/springframework/data/document/couchdb/admin/CouchAdminOperations.java
new file mode 100644
index 000000000..4c00dd68e
--- /dev/null
+++ b/spring-data-couchdb/src/main/java/org/springframework/data/document/couchdb/admin/CouchAdminOperations.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2011 the original author or authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.springframework.data.document.couchdb.admin;
+
+import java.util.List;
+
+public interface CouchAdminOperations {
+
+
+ // functionality for /_special - replication, logs, UUIDs
+
+ List listDatabases();
+
+ void createDatabase(String name);
+
+ void deleteDatabase(String name);
+
+ DbInfo getDatabaseInfo(String name);
+
+
+}
diff --git a/spring-data-couchdb/src/main/java/org/springframework/data/document/couchdb/admin/DbInfo.java b/spring-data-couchdb/src/main/java/org/springframework/data/document/couchdb/admin/DbInfo.java
new file mode 100644
index 000000000..d8aa62b42
--- /dev/null
+++ b/spring-data-couchdb/src/main/java/org/springframework/data/document/couchdb/admin/DbInfo.java
@@ -0,0 +1,77 @@
+/*
+ * Copyright 2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.data.document.couchdb.admin;
+
+import java.util.Collections;
+import java.util.Map;
+
+public class DbInfo {
+
+ private Map dbInfoMap;
+
+ public DbInfo(Map dbInfoMap) {
+ super();
+ this.dbInfoMap = dbInfoMap;
+ }
+
+ public boolean isCompactRunning() {
+ return (Boolean) this.dbInfoMap.get("compact_running");
+ }
+
+ public String getDbName() {
+ return (String) this.dbInfoMap.get("db_name");
+ }
+
+ public long getDiskFormatVersion() {
+ return (Long) this.dbInfoMap.get("disk_format_version");
+ }
+
+ public long getDiskSize() {
+ return (Long) this.dbInfoMap.get("disk_size");
+ }
+
+ public long getDocCount() {
+ return (Long) this.dbInfoMap.get("doc_count");
+ }
+
+ public long getDocDeleteCount() {
+ return (Long) this.dbInfoMap.get("doc_del_count");
+ }
+
+ public long getInstanceStartTime() {
+ return (Long) this.dbInfoMap.get("instance_start_time");
+ }
+
+ public long getPurgeSequence() {
+ return (Long) this.dbInfoMap.get("purge_seq");
+ }
+
+ public long getUpdateSequence() {
+ return (Long) this.dbInfoMap.get("update_seq");
+ }
+
+ public Map getDbInfoMap() {
+ return Collections.unmodifiableMap(dbInfoMap);
+ }
+
+
+
+
+
+
+
+}
diff --git a/spring-data-couchdb/src/main/java/org/springframework/data/document/couchdb/config/CouchJmxParser.java b/spring-data-couchdb/src/main/java/org/springframework/data/document/couchdb/config/CouchJmxParser.java
new file mode 100644
index 000000000..4521dc838
--- /dev/null
+++ b/spring-data-couchdb/src/main/java/org/springframework/data/document/couchdb/config/CouchJmxParser.java
@@ -0,0 +1,70 @@
+/*
+ * Copyright 2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.springframework.data.document.couchdb.config;
+
+import org.springframework.beans.factory.config.BeanDefinition;
+import org.springframework.beans.factory.parsing.BeanComponentDefinition;
+import org.springframework.beans.factory.parsing.CompositeComponentDefinition;
+import org.springframework.beans.factory.support.BeanDefinitionBuilder;
+import org.springframework.beans.factory.xml.BeanDefinitionParser;
+import org.springframework.beans.factory.xml.ParserContext;
+import org.springframework.data.document.couchdb.monitor.ServerInfo;
+import org.springframework.util.StringUtils;
+import org.w3c.dom.Element;
+
+public class CouchJmxParser implements BeanDefinitionParser {
+
+ public BeanDefinition parse(Element element, ParserContext parserContext) {
+ String databaseUrl = element.getAttribute("database-url");
+ if (!StringUtils.hasText(databaseUrl)) {
+ databaseUrl = "http://localhost:5984";
+ }
+ registerJmxComponents(databaseUrl, element, parserContext);
+ return null;
+ }
+
+ protected void registerJmxComponents(String databaseUrl, Element element, ParserContext parserContext) {
+ Object eleSource = parserContext.extractSource(element);
+
+ CompositeComponentDefinition compositeDef = new CompositeComponentDefinition(element.getTagName(), eleSource);
+
+ /*
+ createBeanDefEntry(AssertMetrics.class, compositeDef, mongoRefName, eleSource, parserContext);
+ createBeanDefEntry(BackgroundFlushingMetrics.class, compositeDef, mongoRefName, eleSource, parserContext);
+ createBeanDefEntry(BtreeIndexCounters.class, compositeDef, mongoRefName, eleSource, parserContext);
+ createBeanDefEntry(ConnectionMetrics.class, compositeDef, mongoRefName, eleSource, parserContext);
+ createBeanDefEntry(GlobalLockMetrics.class, compositeDef, mongoRefName, eleSource, parserContext);
+ createBeanDefEntry(MemoryMetrics.class, compositeDef, mongoRefName, eleSource, parserContext);
+ createBeanDefEntry(OperationCounters.class, compositeDef, mongoRefName, eleSource, parserContext);
+ */
+ createBeanDefEntry(ServerInfo.class, compositeDef, databaseUrl, eleSource, parserContext);
+ //createBeanDefEntry(MongoAdmin.class, compositeDef, mongoRefName, eleSource, parserContext);
+
+
+ parserContext.registerComponent(compositeDef);
+
+ }
+
+ protected void createBeanDefEntry(Class clazz, CompositeComponentDefinition compositeDef, String databaseUrl, Object eleSource, ParserContext parserContext) {
+ BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(clazz);
+ builder.getRawBeanDefinition().setSource(eleSource);
+ builder.addConstructorArg(databaseUrl);
+ BeanDefinition assertDef = builder.getBeanDefinition();
+ String assertName = parserContext.getReaderContext().registerWithGeneratedName(assertDef);
+ compositeDef.addNestedComponent(new BeanComponentDefinition(assertDef, assertName));
+ }
+
+}
diff --git a/spring-data-couchdb/src/main/java/org/springframework/data/document/couchdb/config/CouchNamespaceHandler.java b/spring-data-couchdb/src/main/java/org/springframework/data/document/couchdb/config/CouchNamespaceHandler.java
new file mode 100644
index 000000000..d47e1c76b
--- /dev/null
+++ b/spring-data-couchdb/src/main/java/org/springframework/data/document/couchdb/config/CouchNamespaceHandler.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.springframework.data.document.couchdb.config;
+
+import org.springframework.beans.factory.xml.NamespaceHandlerSupport;
+
+
+/**
+ * {@link org.springframework.beans.factory.xml.NamespaceHandler} for Couch DB
+ * based repositories.
+ *
+ * @author Oliver Gierke
+ */
+public class CouchNamespaceHandler extends NamespaceHandlerSupport {
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.springframework.beans.factory.xml.NamespaceHandler#init()
+ */
+ public void init() {
+
+ /*
+ registerBeanDefinitionParser("repositories",
+ new MongoRepositoryConfigDefinitionParser());
+ */
+
+ registerBeanDefinitionParser("jmx", new CouchJmxParser());
+ }
+}
diff --git a/spring-data-couchdb/src/main/java/org/springframework/data/document/couchdb/core/CouchOperations.java b/spring-data-couchdb/src/main/java/org/springframework/data/document/couchdb/core/CouchOperations.java
new file mode 100644
index 000000000..b1573dc00
--- /dev/null
+++ b/spring-data-couchdb/src/main/java/org/springframework/data/document/couchdb/core/CouchOperations.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright 2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.springframework.data.document.couchdb.core;
+
+import java.net.URI;
+
+
+public interface CouchOperations {
+
+ /**
+ * Reads a document from the database and maps it a Java object.
+ *
+ * This method is intended to work when a default database
+ * is set on the CouchDbDocumentOperations instance.
+ *
+ * @param id the id of the CouchDB document to read
+ * @param targetClass the target type to map to
+ * @return the mapped object
+ */
+ T findOne(String id, Class targetClass);
+
+ /**
+ * Reads a document from the database and maps it a Java object.
+ *
+ * @param uri the full URI of the document to read
+ * @param targetClass the target type to map to
+ * @return the mapped object
+ */
+ T findOne(URI uri, Class targetClass);
+
+
+ /**
+ * Maps a Java object to JSON and writes it to the database
+ *
+ * This method is intended to work when a default database
+ * is set on the CouchDbDocumentOperations instance.
+ *
+ * @param id the id of the document to write
+ * @param document the object to write
+ */
+ void save(String id, Object document);
+
+ /**
+ * Maps a Java object to JSON and writes it to the database
+ *
+ * @param uri the full URI of the document to write
+ * @param document the object to write
+ */
+ void save(URI uri, Object document);
+}
diff --git a/spring-data-couchdb/src/main/java/org/springframework/data/document/couchdb/core/CouchTemplate.java b/spring-data-couchdb/src/main/java/org/springframework/data/document/couchdb/core/CouchTemplate.java
new file mode 100644
index 000000000..8cb7014ec
--- /dev/null
+++ b/spring-data-couchdb/src/main/java/org/springframework/data/document/couchdb/core/CouchTemplate.java
@@ -0,0 +1,153 @@
+/*
+ * Copyright 2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.data.document.couchdb.core;
+
+import java.net.URI;
+import java.util.Map;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.springframework.data.document.couchdb.CouchServerResourceUsageException;
+import org.springframework.data.document.couchdb.CouchUsageException;
+import org.springframework.data.document.couchdb.DocumentRetrievalFailureException;
+import org.springframework.data.document.couchdb.UncategorizedCouchDataAccessException;
+import org.springframework.data.document.couchdb.support.CouchUtils;
+import org.springframework.http.HttpEntity;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.HttpMethod;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.MediaType;
+import org.springframework.http.ResponseEntity;
+import org.springframework.util.Assert;
+import org.springframework.web.client.HttpClientErrorException;
+import org.springframework.web.client.HttpServerErrorException;
+import org.springframework.web.client.RestClientException;
+import org.springframework.web.client.RestOperations;
+import org.springframework.web.client.RestTemplate;
+
+
+public class CouchTemplate implements CouchOperations {
+
+ protected final Log logger = LogFactory.getLog(this.getClass());
+
+ private String defaultDocumentUrl;
+
+ private RestOperations restOperations = new RestTemplate();
+
+ /**
+ * Constructs an instance of CouchDbDocumentTemplate with a default database
+ * @param defaultDatabaseUrl the default database to connect to
+ */
+ public CouchTemplate(String defaultDatabaseUrl) {
+ Assert.hasText(defaultDatabaseUrl, "defaultDatabaseUrl must not be empty");
+ defaultDocumentUrl = CouchUtils.addId(defaultDatabaseUrl);
+ }
+
+ /**
+ * Constructs an instance of CouchDbDocumentTemplate with a default database
+ * @param defaultDatabaseUrl the default database to connect to
+ */
+ public CouchTemplate(String defaultDatabaseUrl, RestOperations restOperations) {
+ this(defaultDatabaseUrl);
+ Assert.notNull(restOperations, "restOperations must not be null");
+ this.restOperations = restOperations;
+ }
+
+
+
+
+
+ public T findOne(String id, Class targetClass) {
+ Assert.state(defaultDocumentUrl != null, "defaultDatabaseUrl must be set to use this method");
+ try {
+ return restOperations.getForObject(defaultDocumentUrl, targetClass, id);
+ //TODO check this exception translation and centralize.
+ } catch (HttpClientErrorException clientError) {
+ if (clientError.getStatusCode() == HttpStatus.NOT_FOUND) {
+ throw new DocumentRetrievalFailureException(defaultDocumentUrl + "/" + id);
+ }
+ throw new CouchUsageException(clientError);
+ } catch (HttpServerErrorException serverError) {
+ throw new CouchServerResourceUsageException(serverError);
+ } catch (RestClientException otherError) {
+ throw new UncategorizedCouchDataAccessException(otherError);
+ }
+ }
+
+ public T findOne(URI uri, Class targetClass) {
+ Assert.state(uri != null, "uri must be set to use this method");
+ try {
+ return restOperations.getForObject(uri, targetClass);
+ //TODO check this exception translation and centralize.
+ } catch (HttpClientErrorException clientError) {
+ if (clientError.getStatusCode() == HttpStatus.NOT_FOUND) {
+ throw new DocumentRetrievalFailureException(uri.getPath());
+ }
+ throw new CouchUsageException(clientError);
+ } catch (HttpServerErrorException serverError) {
+ throw new CouchServerResourceUsageException(serverError);
+ } catch (RestClientException otherError) {
+ throw new UncategorizedCouchDataAccessException(otherError);
+ }
+ }
+
+ public void save(String id, Object document) {
+ Assert.notNull(document, "document must not be null for save");
+ HttpEntity> httpEntity = createHttpEntity(document);
+ try {
+ ResponseEntity