Format, organize imports, remove eclipse artifacts
This commit is contained in:
@@ -19,15 +19,16 @@ 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);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new CouchServerResourceUsageException,
|
||||
* wrapping an arbitrary HttpServerErrorException.
|
||||
*
|
||||
* @param cause the HttpServerErrorException thrown
|
||||
*/
|
||||
public CouchServerResourceUsageException(HttpServerErrorException cause) {
|
||||
super(cause != null ? cause.getMessage() : null, cause);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -17,19 +17,18 @@ 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);
|
||||
}
|
||||
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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -18,17 +18,17 @@ 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);
|
||||
}
|
||||
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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -18,21 +18,18 @@ package org.springframework.data.document.couchdb;
|
||||
import org.springframework.dao.DataRetrievalFailureException;
|
||||
|
||||
public class DocumentRetrievalFailureException extends
|
||||
DataRetrievalFailureException {
|
||||
DataRetrievalFailureException {
|
||||
|
||||
private String documentPath;
|
||||
|
||||
public DocumentRetrievalFailureException(String documentPath) {
|
||||
super("Could not find document at path = " + documentPath);
|
||||
this.documentPath = documentPath;
|
||||
}
|
||||
|
||||
public String getDocumentPath() {
|
||||
return documentPath;
|
||||
}
|
||||
|
||||
private String documentPath;
|
||||
|
||||
public DocumentRetrievalFailureException(String documentPath) {
|
||||
super("Could not find document at path = " + documentPath);
|
||||
this.documentPath = documentPath;
|
||||
}
|
||||
|
||||
public String getDocumentPath() {
|
||||
return documentPath;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -20,14 +20,15 @@ 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);
|
||||
}
|
||||
/**
|
||||
* Create a new HibernateSystemException,
|
||||
* wrapping an arbitrary HibernateException.
|
||||
*
|
||||
* @param cause the HibernateException thrown
|
||||
*/
|
||||
public UncategorizedCouchDataAccessException(RestClientException cause) {
|
||||
super(cause != null ? cause.getMessage() : null, cause);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -26,39 +26,39 @@ 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<String> listDatabases() {
|
||||
String dbs = restOperations.getForObject(databaseUrl + "_all_dbs", String.class);
|
||||
return Arrays.asList(StringUtils.commaDelimitedListToStringArray(dbs));
|
||||
}
|
||||
private String databaseUrl;
|
||||
private RestOperations restOperations = new RestTemplate();
|
||||
|
||||
public void createDatabase(String dbName) {
|
||||
org.springframework.util.Assert.hasText(dbName);
|
||||
restOperations.put(databaseUrl + dbName, null);
|
||||
public CouchAdmin(String databaseUrl) {
|
||||
|
||||
}
|
||||
if (!databaseUrl.trim().endsWith("/")) {
|
||||
this.databaseUrl = databaseUrl.trim() + "/";
|
||||
} else {
|
||||
this.databaseUrl = databaseUrl.trim();
|
||||
}
|
||||
}
|
||||
|
||||
public void deleteDatabase(String dbName) {
|
||||
org.springframework.util.Assert.hasText(dbName);
|
||||
restOperations.delete(CouchUtils.ensureTrailingSlash(databaseUrl + dbName));
|
||||
public List<String> 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 DbInfo getDatabaseInfo(String dbName) {
|
||||
String url = CouchUtils.ensureTrailingSlash(databaseUrl + dbName);
|
||||
Map dbInfoMap = (Map) restOperations.getForObject(url, Map.class);
|
||||
return new DbInfo(dbInfoMap);
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -19,16 +19,16 @@ import java.util.List;
|
||||
|
||||
public interface CouchAdminOperations {
|
||||
|
||||
|
||||
// functionality for /_special - replication, logs, UUIDs
|
||||
|
||||
List<String> listDatabases();
|
||||
|
||||
void createDatabase(String name);
|
||||
|
||||
void deleteDatabase(String name);
|
||||
|
||||
DbInfo getDatabaseInfo(String name);
|
||||
|
||||
|
||||
|
||||
// functionality for /_special - replication, logs, UUIDs
|
||||
|
||||
List<String> listDatabases();
|
||||
|
||||
void createDatabase(String name);
|
||||
|
||||
void deleteDatabase(String name);
|
||||
|
||||
DbInfo getDatabaseInfo(String name);
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -21,57 +21,52 @@ import java.util.Map;
|
||||
|
||||
public class DbInfo {
|
||||
|
||||
private Map dbInfoMap;
|
||||
|
||||
public DbInfo(Map dbInfoMap) {
|
||||
super();
|
||||
this.dbInfoMap = dbInfoMap;
|
||||
}
|
||||
private Map dbInfoMap;
|
||||
|
||||
public boolean isCompactRunning() {
|
||||
return (Boolean) this.dbInfoMap.get("compact_running");
|
||||
}
|
||||
public DbInfo(Map dbInfoMap) {
|
||||
super();
|
||||
this.dbInfoMap = dbInfoMap;
|
||||
}
|
||||
|
||||
public String getDbName() {
|
||||
return (String) this.dbInfoMap.get("db_name");
|
||||
}
|
||||
public boolean isCompactRunning() {
|
||||
return (Boolean) this.dbInfoMap.get("compact_running");
|
||||
}
|
||||
|
||||
public long getDiskFormatVersion() {
|
||||
return (Long) this.dbInfoMap.get("disk_format_version");
|
||||
}
|
||||
public String getDbName() {
|
||||
return (String) this.dbInfoMap.get("db_name");
|
||||
}
|
||||
|
||||
public long getDiskSize() {
|
||||
return (Long) this.dbInfoMap.get("disk_size");
|
||||
}
|
||||
public long getDiskFormatVersion() {
|
||||
return (Long) this.dbInfoMap.get("disk_format_version");
|
||||
}
|
||||
|
||||
public long getDocCount() {
|
||||
return (Long) this.dbInfoMap.get("doc_count");
|
||||
}
|
||||
public long getDiskSize() {
|
||||
return (Long) this.dbInfoMap.get("disk_size");
|
||||
}
|
||||
|
||||
public long getDocDeleteCount() {
|
||||
return (Long) this.dbInfoMap.get("doc_del_count");
|
||||
}
|
||||
public long getDocCount() {
|
||||
return (Long) this.dbInfoMap.get("doc_count");
|
||||
}
|
||||
|
||||
public long getInstanceStartTime() {
|
||||
return (Long) this.dbInfoMap.get("instance_start_time");
|
||||
}
|
||||
public long getDocDeleteCount() {
|
||||
return (Long) this.dbInfoMap.get("doc_del_count");
|
||||
}
|
||||
|
||||
public long getPurgeSequence() {
|
||||
return (Long) this.dbInfoMap.get("purge_seq");
|
||||
}
|
||||
public long getInstanceStartTime() {
|
||||
return (Long) this.dbInfoMap.get("instance_start_time");
|
||||
}
|
||||
|
||||
public long getUpdateSequence() {
|
||||
return (Long) this.dbInfoMap.get("update_seq");
|
||||
}
|
||||
public long getPurgeSequence() {
|
||||
return (Long) this.dbInfoMap.get("purge_seq");
|
||||
}
|
||||
|
||||
public Map getDbInfoMap() {
|
||||
return Collections.unmodifiableMap(dbInfoMap);
|
||||
}
|
||||
public long getUpdateSequence() {
|
||||
return (Long) this.dbInfoMap.get("update_seq");
|
||||
}
|
||||
|
||||
public Map getDbInfoMap() {
|
||||
return Collections.unmodifiableMap(dbInfoMap);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -27,44 +27,44 @@ 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;
|
||||
}
|
||||
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);
|
||||
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);
|
||||
|
||||
}
|
||||
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));
|
||||
}
|
||||
|
||||
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));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -21,23 +21,23 @@ 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() {
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.springframework.beans.factory.xml.NamespaceHandler#init()
|
||||
*/
|
||||
public void init() {
|
||||
|
||||
/*
|
||||
registerBeanDefinitionParser("repositories",
|
||||
new MongoRepositoryConfigDefinitionParser());
|
||||
*/
|
||||
|
||||
registerBeanDefinitionParser("jmx", new CouchJmxParser());
|
||||
}
|
||||
/*
|
||||
registerBeanDefinitionParser("repositories",
|
||||
new MongoRepositoryConfigDefinitionParser());
|
||||
*/
|
||||
|
||||
registerBeanDefinitionParser("jmx", new CouchJmxParser());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,44 +20,44 @@ import java.net.URI;
|
||||
|
||||
public interface CouchOperations {
|
||||
|
||||
/**
|
||||
* Reads a document from the database and maps it a Java object.
|
||||
* </p>
|
||||
* 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> T findOne(String id, Class<T> 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> T findOne(URI uri, Class<T> targetClass);
|
||||
|
||||
|
||||
/**
|
||||
* Maps a Java object to JSON and writes it to the database
|
||||
* </p>
|
||||
* 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);
|
||||
/**
|
||||
* Reads a document from the database and maps it a Java object.
|
||||
* </p>
|
||||
* 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> T findOne(String id, Class<T> 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> T findOne(URI uri, Class<T> targetClass);
|
||||
|
||||
|
||||
/**
|
||||
* Maps a Java object to JSON and writes it to the database
|
||||
* </p>
|
||||
* 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);
|
||||
}
|
||||
|
||||
@@ -26,128 +26,118 @@ 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.http.*;
|
||||
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;
|
||||
import org.springframework.web.client.*;
|
||||
|
||||
|
||||
public class CouchTemplate implements CouchOperations {
|
||||
|
||||
protected final Log logger = LogFactory.getLog(this.getClass());
|
||||
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);
|
||||
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> T findOne(String id, Class<T> 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);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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> T findOne(URI uri, Class<T> 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 <T> T findOne(String id, Class<T> 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> T findOne(URI uri, Class<T> 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<Map> response = restOperations.exchange(defaultDocumentUrl, HttpMethod.PUT, httpEntity, Map.class, id);
|
||||
//TODO update the document revision id on the object from the returned value
|
||||
//TODO better exception translation
|
||||
} catch (RestClientException e) {
|
||||
throw new UncategorizedCouchDataAccessException(e);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void save(URI uri, Object document) {
|
||||
Assert.notNull(document, "document must not be null for save");
|
||||
Assert.notNull(uri, "URI must not be null for save");
|
||||
HttpEntity<?> httpEntity = createHttpEntity(document);
|
||||
try {
|
||||
ResponseEntity<Map> response = restOperations.exchange(uri, HttpMethod.PUT, httpEntity, Map.class);
|
||||
//TODO update the document revision id on the object from the returned value
|
||||
//TODO better exception translation
|
||||
} catch (RestClientException e) {
|
||||
throw new UncategorizedCouchDataAccessException(e);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
private HttpEntity<?> createHttpEntity(Object document) {
|
||||
|
||||
if (document instanceof HttpEntity) {
|
||||
HttpEntity httpEntity = (HttpEntity) document;
|
||||
Assert.isTrue(httpEntity.getHeaders().getContentType().equals(MediaType.APPLICATION_JSON),
|
||||
"HttpEntity payload with non application/json content type found.");
|
||||
return httpEntity;
|
||||
}
|
||||
|
||||
HttpHeaders httpHeaders = new HttpHeaders();
|
||||
httpHeaders.setContentType(MediaType.APPLICATION_JSON);
|
||||
HttpEntity<Object> httpEntity = new HttpEntity<Object>(document, httpHeaders);
|
||||
|
||||
return httpEntity;
|
||||
public void save(String id, Object document) {
|
||||
Assert.notNull(document, "document must not be null for save");
|
||||
HttpEntity<?> httpEntity = createHttpEntity(document);
|
||||
try {
|
||||
ResponseEntity<Map> response = restOperations.exchange(defaultDocumentUrl, HttpMethod.PUT, httpEntity, Map.class, id);
|
||||
//TODO update the document revision id on the object from the returned value
|
||||
//TODO better exception translation
|
||||
} catch (RestClientException e) {
|
||||
throw new UncategorizedCouchDataAccessException(e);
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
public void save(URI uri, Object document) {
|
||||
Assert.notNull(document, "document must not be null for save");
|
||||
Assert.notNull(uri, "URI must not be null for save");
|
||||
HttpEntity<?> httpEntity = createHttpEntity(document);
|
||||
try {
|
||||
ResponseEntity<Map> response = restOperations.exchange(uri, HttpMethod.PUT, httpEntity, Map.class);
|
||||
//TODO update the document revision id on the object from the returned value
|
||||
//TODO better exception translation
|
||||
} catch (RestClientException e) {
|
||||
throw new UncategorizedCouchDataAccessException(e);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
private HttpEntity<?> createHttpEntity(Object document) {
|
||||
|
||||
if (document instanceof HttpEntity) {
|
||||
HttpEntity httpEntity = (HttpEntity) document;
|
||||
Assert.isTrue(httpEntity.getHeaders().getContentType().equals(MediaType.APPLICATION_JSON),
|
||||
"HttpEntity payload with non application/json content type found.");
|
||||
return httpEntity;
|
||||
}
|
||||
|
||||
HttpHeaders httpHeaders = new HttpHeaders();
|
||||
httpHeaders.setContentType(MediaType.APPLICATION_JSON);
|
||||
HttpEntity<Object> httpEntity = new HttpEntity<Object>(document, httpHeaders);
|
||||
|
||||
return httpEntity;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -17,20 +17,9 @@ package org.springframework.data.document.couchdb.core.support;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.Charset;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.*;
|
||||
|
||||
import org.codehaus.jackson.JsonEncoding;
|
||||
import org.codehaus.jackson.JsonGenerationException;
|
||||
import org.codehaus.jackson.JsonGenerator;
|
||||
import org.codehaus.jackson.JsonNode;
|
||||
import org.codehaus.jackson.JsonParseException;
|
||||
import org.codehaus.jackson.JsonParser;
|
||||
import org.codehaus.jackson.JsonProcessingException;
|
||||
import org.codehaus.jackson.JsonToken;
|
||||
import org.codehaus.jackson.*;
|
||||
import org.codehaus.jackson.map.JsonMappingException;
|
||||
import org.codehaus.jackson.map.ObjectMapper;
|
||||
import org.codehaus.jackson.map.type.TypeFactory;
|
||||
@@ -44,283 +33,283 @@ import org.springframework.http.converter.HttpMessageNotWritableException;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
public class CouchDbMappingJacksonHttpMessageConverter extends
|
||||
AbstractHttpMessageConverter<Object> {
|
||||
AbstractHttpMessageConverter<Object> {
|
||||
|
||||
public static final Charset DEFAULT_CHARSET = Charset.forName("UTF-8");
|
||||
public static final Charset DEFAULT_CHARSET = Charset.forName("UTF-8");
|
||||
|
||||
private static final String ROWS_FIELD_NAME = "rows";
|
||||
private static final String VALUE_FIELD_NAME = "value";
|
||||
private static final String INCLUDED_DOC_FIELD_NAME = "doc";
|
||||
private static final String TOTAL_ROWS_FIELD_NAME = "total_rows";
|
||||
private static final String ROWS_FIELD_NAME = "rows";
|
||||
private static final String VALUE_FIELD_NAME = "value";
|
||||
private static final String INCLUDED_DOC_FIELD_NAME = "doc";
|
||||
private static final String TOTAL_ROWS_FIELD_NAME = "total_rows";
|
||||
|
||||
private ObjectMapper objectMapper = new ObjectMapper();
|
||||
private ObjectMapper objectMapper = new ObjectMapper();
|
||||
|
||||
private boolean prefixJson = false;
|
||||
private boolean prefixJson = false;
|
||||
|
||||
/**
|
||||
* Construct a new {@code BindingJacksonHttpMessageConverter}.
|
||||
*/
|
||||
public CouchDbMappingJacksonHttpMessageConverter() {
|
||||
super(new MediaType("application", "json", DEFAULT_CHARSET));
|
||||
}
|
||||
/**
|
||||
* Construct a new {@code BindingJacksonHttpMessageConverter}.
|
||||
*/
|
||||
public CouchDbMappingJacksonHttpMessageConverter() {
|
||||
super(new MediaType("application", "json", DEFAULT_CHARSET));
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the {@code ObjectMapper} for this view. If not set, a default
|
||||
* {@link ObjectMapper#ObjectMapper() ObjectMapper} is used.
|
||||
* <p>
|
||||
* Setting a custom-configured {@code ObjectMapper} is one way to take
|
||||
* further control of the JSON serialization process. For example, an
|
||||
* extended {@link org.codehaus.jackson.map.SerializerFactory} can be
|
||||
* configured that provides custom serializers for specific types. The other
|
||||
* option for refining the serialization process is to use Jackson's
|
||||
* provided annotations on the types to be serialized, in which case a
|
||||
* custom-configured ObjectMapper is unnecessary.
|
||||
*/
|
||||
public void setObjectMapper(ObjectMapper objectMapper) {
|
||||
Assert.notNull(objectMapper, "'objectMapper' must not be null");
|
||||
this.objectMapper = objectMapper;
|
||||
}
|
||||
/**
|
||||
* Sets the {@code ObjectMapper} for this view. If not set, a default
|
||||
* {@link ObjectMapper#ObjectMapper() ObjectMapper} is used.
|
||||
* <p/>
|
||||
* Setting a custom-configured {@code ObjectMapper} is one way to take
|
||||
* further control of the JSON serialization process. For example, an
|
||||
* extended {@link org.codehaus.jackson.map.SerializerFactory} can be
|
||||
* configured that provides custom serializers for specific types. The other
|
||||
* option for refining the serialization process is to use Jackson's
|
||||
* provided annotations on the types to be serialized, in which case a
|
||||
* custom-configured ObjectMapper is unnecessary.
|
||||
*/
|
||||
public void setObjectMapper(ObjectMapper objectMapper) {
|
||||
Assert.notNull(objectMapper, "'objectMapper' must not be null");
|
||||
this.objectMapper = objectMapper;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates whether the JSON output by this view should be prefixed with
|
||||
* "{} &&". Default is false.
|
||||
* <p>
|
||||
* Prefixing the JSON string in this manner is used to help prevent JSON
|
||||
* Hijacking. The prefix renders the string syntactically invalid as a
|
||||
* script so that it cannot be hijacked. This prefix does not affect the
|
||||
* evaluation of JSON, but if JSON validation is performed on the string,
|
||||
* the prefix would need to be ignored.
|
||||
*/
|
||||
public void setPrefixJson(boolean prefixJson) {
|
||||
this.prefixJson = prefixJson;
|
||||
}
|
||||
/**
|
||||
* Indicates whether the JSON output by this view should be prefixed with
|
||||
* "{} &&". Default is false.
|
||||
* <p/>
|
||||
* Prefixing the JSON string in this manner is used to help prevent JSON
|
||||
* Hijacking. The prefix renders the string syntactically invalid as a
|
||||
* script so that it cannot be hijacked. This prefix does not affect the
|
||||
* evaluation of JSON, but if JSON validation is performed on the string,
|
||||
* the prefix would need to be ignored.
|
||||
*/
|
||||
public void setPrefixJson(boolean prefixJson) {
|
||||
this.prefixJson = prefixJson;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canRead(Class<?> clazz, MediaType mediaType) {
|
||||
JavaType javaType = getJavaType(clazz);
|
||||
return this.objectMapper.canDeserialize(javaType) && canRead(mediaType);
|
||||
}
|
||||
@Override
|
||||
public boolean canRead(Class<?> clazz, MediaType mediaType) {
|
||||
JavaType javaType = getJavaType(clazz);
|
||||
return this.objectMapper.canDeserialize(javaType) && canRead(mediaType);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the Jackson {@link JavaType} for the specific class.
|
||||
*
|
||||
* <p>
|
||||
* Default implementation returns
|
||||
* {@link TypeFactory#type(java.lang.reflect.Type)}, but this can be
|
||||
* overridden in subclasses, to allow for custom generic collection
|
||||
* handling. For instance:
|
||||
*
|
||||
* <pre class="code">
|
||||
* protected JavaType getJavaType(Class<?> clazz) {
|
||||
* if (List.class.isAssignableFrom(clazz)) {
|
||||
* return TypeFactory.collectionType(ArrayList.class, MyBean.class);
|
||||
* } else {
|
||||
* return super.getJavaType(clazz);
|
||||
* }
|
||||
* }
|
||||
* </pre>
|
||||
*
|
||||
* @param clazz
|
||||
* the class to return the java type for
|
||||
* @return the java type
|
||||
*/
|
||||
protected JavaType getJavaType(Class<?> clazz) {
|
||||
return TypeFactory.type(clazz);
|
||||
}
|
||||
/**
|
||||
* Returns the Jackson {@link JavaType} for the specific class.
|
||||
* <p/>
|
||||
* <p/>
|
||||
* Default implementation returns
|
||||
* {@link TypeFactory#type(java.lang.reflect.Type)}, but this can be
|
||||
* overridden in subclasses, to allow for custom generic collection
|
||||
* handling. For instance:
|
||||
* <p/>
|
||||
* <pre class="code">
|
||||
* protected JavaType getJavaType(Class<?> clazz) {
|
||||
* if (List.class.isAssignableFrom(clazz)) {
|
||||
* return TypeFactory.collectionType(ArrayList.class, MyBean.class);
|
||||
* } else {
|
||||
* return super.getJavaType(clazz);
|
||||
* }
|
||||
* }
|
||||
* </pre>
|
||||
*
|
||||
* @param clazz the class to return the java type for
|
||||
* @return the java type
|
||||
*/
|
||||
protected JavaType getJavaType(Class<?> clazz) {
|
||||
return TypeFactory.type(clazz);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canWrite(Class<?> clazz, MediaType mediaType) {
|
||||
return this.objectMapper.canSerialize(clazz) && canWrite(mediaType);
|
||||
}
|
||||
@Override
|
||||
public boolean canWrite(Class<?> clazz, MediaType mediaType) {
|
||||
return this.objectMapper.canSerialize(clazz) && canWrite(mediaType);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean supports(Class<?> clazz) {
|
||||
// should not be called, since we override canRead/Write instead
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
@Override
|
||||
protected boolean supports(Class<?> clazz) {
|
||||
// should not be called, since we override canRead/Write instead
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Object readInternal(Class<?> clazz, HttpInputMessage inputMessage)
|
||||
throws IOException, HttpMessageNotReadableException {
|
||||
JavaType javaType = getJavaType(clazz);
|
||||
try {
|
||||
return success(clazz, inputMessage);
|
||||
@Override
|
||||
protected Object readInternal(Class<?> clazz, HttpInputMessage inputMessage)
|
||||
throws IOException, HttpMessageNotReadableException {
|
||||
JavaType javaType = getJavaType(clazz);
|
||||
try {
|
||||
return success(clazz, inputMessage);
|
||||
|
||||
// return this.objectMapper.readValue(inputMessage.getBody(),
|
||||
// javaType);
|
||||
} catch (Exception ex) {
|
||||
throw new HttpMessageNotReadableException("Could not read JSON: "
|
||||
+ ex.getMessage(), ex);
|
||||
}
|
||||
}
|
||||
// return this.objectMapper.readValue(inputMessage.getBody(),
|
||||
// javaType);
|
||||
} catch (Exception ex) {
|
||||
throw new HttpMessageNotReadableException("Could not read JSON: "
|
||||
+ ex.getMessage(), ex);
|
||||
}
|
||||
}
|
||||
|
||||
private Object success(Class<?> clazz, HttpInputMessage inputMessage)
|
||||
throws JsonParseException, IOException {
|
||||
|
||||
//Note, parsing code used from ektorp project
|
||||
JsonParser jp = objectMapper.getJsonFactory().createJsonParser(
|
||||
inputMessage.getBody());
|
||||
if (jp.nextToken() != JsonToken.START_OBJECT) {
|
||||
throw new RuntimeException("Expected data to start with an Object");
|
||||
}
|
||||
Map<String, Integer> fields = readHeaderFields(jp);
|
||||
private Object success(Class<?> clazz, HttpInputMessage inputMessage)
|
||||
throws JsonParseException, IOException {
|
||||
|
||||
List result;
|
||||
if (fields.containsKey(TOTAL_ROWS_FIELD_NAME)) {
|
||||
int totalRows = fields.get(TOTAL_ROWS_FIELD_NAME);
|
||||
if (totalRows == 0) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
result = new ArrayList(totalRows);
|
||||
} else {
|
||||
result = new ArrayList();
|
||||
}
|
||||
//Note, parsing code used from ektorp project
|
||||
JsonParser jp = objectMapper.getJsonFactory().createJsonParser(
|
||||
inputMessage.getBody());
|
||||
if (jp.nextToken() != JsonToken.START_OBJECT) {
|
||||
throw new RuntimeException("Expected data to start with an Object");
|
||||
}
|
||||
Map<String, Integer> fields = readHeaderFields(jp);
|
||||
|
||||
ParseState state = new ParseState();
|
||||
List result;
|
||||
if (fields.containsKey(TOTAL_ROWS_FIELD_NAME)) {
|
||||
int totalRows = fields.get(TOTAL_ROWS_FIELD_NAME);
|
||||
if (totalRows == 0) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
result = new ArrayList(totalRows);
|
||||
} else {
|
||||
result = new ArrayList();
|
||||
}
|
||||
|
||||
Object first = parseFirstRow(jp, state, clazz);
|
||||
if (first == null) {
|
||||
return Collections.emptyList();
|
||||
} else {
|
||||
result.add(first);
|
||||
}
|
||||
ParseState state = new ParseState();
|
||||
|
||||
while (jp.getCurrentToken() != null) {
|
||||
skipToField(jp, state.docFieldName, state);
|
||||
if (atEndOfRows(jp)) {
|
||||
return result;
|
||||
}
|
||||
result.add(jp.readValueAs(clazz));
|
||||
endRow(jp, state);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
Object first = parseFirstRow(jp, state, clazz);
|
||||
if (first == null) {
|
||||
return Collections.emptyList();
|
||||
} else {
|
||||
result.add(first);
|
||||
}
|
||||
|
||||
private Object parseFirstRow(JsonParser jp, ParseState state, Class clazz)
|
||||
throws JsonParseException, IOException, JsonProcessingException,
|
||||
JsonMappingException {
|
||||
skipToField(jp, VALUE_FIELD_NAME, state);
|
||||
JsonNode value = null;
|
||||
if (atObjectStart(jp)) {
|
||||
value = jp.readValueAsTree();
|
||||
jp.nextToken();
|
||||
if (isEndOfRow(jp)) {
|
||||
state.docFieldName = VALUE_FIELD_NAME;
|
||||
Object doc = objectMapper.readValue(value, clazz);
|
||||
endRow(jp, state);
|
||||
return doc;
|
||||
}
|
||||
}
|
||||
skipToField(jp, INCLUDED_DOC_FIELD_NAME, state);
|
||||
if (atObjectStart(jp)) {
|
||||
state.docFieldName = INCLUDED_DOC_FIELD_NAME;
|
||||
Object doc = jp.readValueAs(clazz);
|
||||
endRow(jp, state);
|
||||
return doc;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
while (jp.getCurrentToken() != null) {
|
||||
skipToField(jp, state.docFieldName, state);
|
||||
if (atEndOfRows(jp)) {
|
||||
return result;
|
||||
}
|
||||
result.add(jp.readValueAs(clazz));
|
||||
endRow(jp, state);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private boolean isEndOfRow(JsonParser jp) {
|
||||
return jp.getCurrentToken() == JsonToken.END_OBJECT;
|
||||
}
|
||||
|
||||
private void endRow(JsonParser jp, ParseState state) throws IOException, JsonParseException {
|
||||
state.inRow = false;
|
||||
jp.nextToken();
|
||||
}
|
||||
|
||||
private boolean atObjectStart(JsonParser jp) {
|
||||
return jp.getCurrentToken() == JsonToken.START_OBJECT;
|
||||
}
|
||||
|
||||
private boolean atEndOfRows(JsonParser jp) {
|
||||
return jp.getCurrentToken() != JsonToken.START_OBJECT;
|
||||
}
|
||||
private void skipToField(JsonParser jp, String fieldName, ParseState state) throws JsonParseException, IOException {
|
||||
String lastFieldName = null;
|
||||
while (jp.getCurrentToken() != null) {
|
||||
switch (jp.getCurrentToken()) {
|
||||
case FIELD_NAME:
|
||||
lastFieldName = jp.getCurrentName();
|
||||
jp.nextToken();
|
||||
break;
|
||||
case START_OBJECT:
|
||||
if (!state.inRow) {
|
||||
state.inRow = true;
|
||||
jp.nextToken();
|
||||
} else {
|
||||
if (isInField(fieldName, lastFieldName)) {
|
||||
return;
|
||||
} else {
|
||||
jp.skipChildren();
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
if (isInField(fieldName, lastFieldName)) {
|
||||
jp.nextToken();
|
||||
return;
|
||||
}
|
||||
jp.nextToken();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isInField(String fieldName, String lastFieldName) {
|
||||
return lastFieldName != null && lastFieldName.equals(fieldName);
|
||||
}
|
||||
private Object parseFirstRow(JsonParser jp, ParseState state, Class clazz)
|
||||
throws JsonParseException, IOException, JsonProcessingException,
|
||||
JsonMappingException {
|
||||
skipToField(jp, VALUE_FIELD_NAME, state);
|
||||
JsonNode value = null;
|
||||
if (atObjectStart(jp)) {
|
||||
value = jp.readValueAsTree();
|
||||
jp.nextToken();
|
||||
if (isEndOfRow(jp)) {
|
||||
state.docFieldName = VALUE_FIELD_NAME;
|
||||
Object doc = objectMapper.readValue(value, clazz);
|
||||
endRow(jp, state);
|
||||
return doc;
|
||||
}
|
||||
}
|
||||
skipToField(jp, INCLUDED_DOC_FIELD_NAME, state);
|
||||
if (atObjectStart(jp)) {
|
||||
state.docFieldName = INCLUDED_DOC_FIELD_NAME;
|
||||
Object doc = jp.readValueAs(clazz);
|
||||
endRow(jp, state);
|
||||
return doc;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
private Map<String, Integer> readHeaderFields(JsonParser jp)
|
||||
throws JsonParseException, IOException {
|
||||
Map<String, Integer> map = new HashMap<String, Integer>();
|
||||
jp.nextToken();
|
||||
String nextFieldName = jp.getCurrentName();
|
||||
while (!nextFieldName.equals(ROWS_FIELD_NAME)) {
|
||||
jp.nextToken();
|
||||
map.put(nextFieldName, Integer.valueOf(jp.getIntValue()));
|
||||
jp.nextToken();
|
||||
nextFieldName = jp.getCurrentName();
|
||||
}
|
||||
return map;
|
||||
}
|
||||
private boolean isEndOfRow(JsonParser jp) {
|
||||
return jp.getCurrentToken() == JsonToken.END_OBJECT;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void writeInternal(Object o, HttpOutputMessage outputMessage)
|
||||
throws IOException, HttpMessageNotWritableException {
|
||||
private void endRow(JsonParser jp, ParseState state) throws IOException, JsonParseException {
|
||||
state.inRow = false;
|
||||
jp.nextToken();
|
||||
}
|
||||
|
||||
JsonEncoding encoding = getEncoding(outputMessage.getHeaders()
|
||||
.getContentType());
|
||||
JsonGenerator jsonGenerator = this.objectMapper.getJsonFactory()
|
||||
.createJsonGenerator(outputMessage.getBody(), encoding);
|
||||
try {
|
||||
if (this.prefixJson) {
|
||||
jsonGenerator.writeRaw("{} && ");
|
||||
}
|
||||
this.objectMapper.writeValue(jsonGenerator, o);
|
||||
} catch (JsonGenerationException ex) {
|
||||
throw new HttpMessageNotWritableException("Could not write JSON: "
|
||||
+ ex.getMessage(), ex);
|
||||
}
|
||||
}
|
||||
private boolean atObjectStart(JsonParser jp) {
|
||||
return jp.getCurrentToken() == JsonToken.START_OBJECT;
|
||||
}
|
||||
|
||||
private JsonEncoding getEncoding(MediaType contentType) {
|
||||
if (contentType != null && contentType.getCharSet() != null) {
|
||||
Charset charset = contentType.getCharSet();
|
||||
for (JsonEncoding encoding : JsonEncoding.values()) {
|
||||
if (charset.name().equals(encoding.getJavaName())) {
|
||||
return encoding;
|
||||
}
|
||||
}
|
||||
}
|
||||
return JsonEncoding.UTF8;
|
||||
}
|
||||
private boolean atEndOfRows(JsonParser jp) {
|
||||
return jp.getCurrentToken() != JsonToken.START_OBJECT;
|
||||
}
|
||||
|
||||
private static class ParseState {
|
||||
boolean inRow;
|
||||
String docFieldName = "";
|
||||
}
|
||||
private void skipToField(JsonParser jp, String fieldName, ParseState state) throws JsonParseException, IOException {
|
||||
String lastFieldName = null;
|
||||
while (jp.getCurrentToken() != null) {
|
||||
switch (jp.getCurrentToken()) {
|
||||
case FIELD_NAME:
|
||||
lastFieldName = jp.getCurrentName();
|
||||
jp.nextToken();
|
||||
break;
|
||||
case START_OBJECT:
|
||||
if (!state.inRow) {
|
||||
state.inRow = true;
|
||||
jp.nextToken();
|
||||
} else {
|
||||
if (isInField(fieldName, lastFieldName)) {
|
||||
return;
|
||||
} else {
|
||||
jp.skipChildren();
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
if (isInField(fieldName, lastFieldName)) {
|
||||
jp.nextToken();
|
||||
return;
|
||||
}
|
||||
jp.nextToken();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isInField(String fieldName, String lastFieldName) {
|
||||
return lastFieldName != null && lastFieldName.equals(fieldName);
|
||||
}
|
||||
|
||||
|
||||
private Map<String, Integer> readHeaderFields(JsonParser jp)
|
||||
throws JsonParseException, IOException {
|
||||
Map<String, Integer> map = new HashMap<String, Integer>();
|
||||
jp.nextToken();
|
||||
String nextFieldName = jp.getCurrentName();
|
||||
while (!nextFieldName.equals(ROWS_FIELD_NAME)) {
|
||||
jp.nextToken();
|
||||
map.put(nextFieldName, Integer.valueOf(jp.getIntValue()));
|
||||
jp.nextToken();
|
||||
nextFieldName = jp.getCurrentName();
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void writeInternal(Object o, HttpOutputMessage outputMessage)
|
||||
throws IOException, HttpMessageNotWritableException {
|
||||
|
||||
JsonEncoding encoding = getEncoding(outputMessage.getHeaders()
|
||||
.getContentType());
|
||||
JsonGenerator jsonGenerator = this.objectMapper.getJsonFactory()
|
||||
.createJsonGenerator(outputMessage.getBody(), encoding);
|
||||
try {
|
||||
if (this.prefixJson) {
|
||||
jsonGenerator.writeRaw("{} && ");
|
||||
}
|
||||
this.objectMapper.writeValue(jsonGenerator, o);
|
||||
} catch (JsonGenerationException ex) {
|
||||
throw new HttpMessageNotWritableException("Could not write JSON: "
|
||||
+ ex.getMessage(), ex);
|
||||
}
|
||||
}
|
||||
|
||||
private JsonEncoding getEncoding(MediaType contentType) {
|
||||
if (contentType != null && contentType.getCharSet() != null) {
|
||||
Charset charset = contentType.getCharSet();
|
||||
for (JsonEncoding encoding : JsonEncoding.values()) {
|
||||
if (charset.name().equals(encoding.getJavaName())) {
|
||||
return encoding;
|
||||
}
|
||||
}
|
||||
}
|
||||
return JsonEncoding.UTF8;
|
||||
}
|
||||
|
||||
private static class ParseState {
|
||||
boolean inRow;
|
||||
String docFieldName = "";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,32 +15,27 @@
|
||||
*/
|
||||
package org.springframework.data.document.couchdb.monitor;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
|
||||
/**
|
||||
* Base class to encapsulate common configuration settings when connecting to a CouchDB database
|
||||
*
|
||||
* @author Mark Pollack
|
||||
*
|
||||
* @author Mark Pollack
|
||||
*/
|
||||
public abstract class AbstractMonitor {
|
||||
|
||||
|
||||
protected RestTemplate restTemplate;
|
||||
protected String databaseUrl;
|
||||
|
||||
/**
|
||||
* Gets the databaseUrl used to connect to CouchDB
|
||||
* @return
|
||||
*/
|
||||
public String getDatabaseUrl() {
|
||||
return this.databaseUrl;
|
||||
}
|
||||
|
||||
|
||||
protected RestTemplate restTemplate;
|
||||
protected String databaseUrl;
|
||||
|
||||
/**
|
||||
* Gets the databaseUrl used to connect to CouchDB
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public String getDatabaseUrl() {
|
||||
return this.databaseUrl;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -24,40 +24,39 @@ import org.springframework.jmx.export.annotation.ManagedResource;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
|
||||
/**
|
||||
* Expose basic server information via JMX
|
||||
*
|
||||
* @author Mark Pollack
|
||||
* Expose basic server information via JMX
|
||||
*
|
||||
* @author Mark Pollack
|
||||
*/
|
||||
@ManagedResource(description="Server Information")
|
||||
@ManagedResource(description = "Server Information")
|
||||
public class ServerInfo extends AbstractMonitor {
|
||||
|
||||
|
||||
public ServerInfo(String databaseUrl) {
|
||||
this.databaseUrl = databaseUrl;
|
||||
this.restTemplate = new RestTemplate();
|
||||
}
|
||||
|
||||
|
||||
@ManagedOperation(description="Server host name")
|
||||
public String getHostName() throws UnknownHostException {
|
||||
return InetAddress.getLocalHost().getHostName();
|
||||
}
|
||||
|
||||
|
||||
@ManagedOperation(description="CouchDB Server Version")
|
||||
public String getVersion() {
|
||||
return (String) getRoot().get("version");
|
||||
}
|
||||
|
||||
@ManagedOperation(description="Message of the day")
|
||||
public String getMotd() {
|
||||
return (String) getRoot().get("greeting");
|
||||
}
|
||||
|
||||
public Map getRoot() {
|
||||
Map map = restTemplate.getForObject(getDatabaseUrl(),Map.class);
|
||||
return map;
|
||||
}
|
||||
public ServerInfo(String databaseUrl) {
|
||||
this.databaseUrl = databaseUrl;
|
||||
this.restTemplate = new RestTemplate();
|
||||
}
|
||||
|
||||
|
||||
@ManagedOperation(description = "Server host name")
|
||||
public String getHostName() throws UnknownHostException {
|
||||
return InetAddress.getLocalHost().getHostName();
|
||||
}
|
||||
|
||||
|
||||
@ManagedOperation(description = "CouchDB Server Version")
|
||||
public String getVersion() {
|
||||
return (String) getRoot().get("version");
|
||||
}
|
||||
|
||||
@ManagedOperation(description = "Message of the day")
|
||||
public String getMotd() {
|
||||
return (String) getRoot().get("greeting");
|
||||
}
|
||||
|
||||
public Map getRoot() {
|
||||
Map map = restTemplate.getForObject(getDatabaseUrl(), Map.class);
|
||||
return map;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -17,11 +17,10 @@
|
||||
package org.springframework.data.document.couchdb.support;
|
||||
|
||||
import org.springframework.dao.DataAccessException;
|
||||
import org.springframework.data.document.UncategorizedDocumentStoreException;
|
||||
|
||||
/**
|
||||
* Helper class featuring helper methods for internal CouchDB classes.
|
||||
*
|
||||
* <p/>
|
||||
* <p>Mainly intended for internal use within the framework.
|
||||
*
|
||||
* @author Thomas Risberg
|
||||
@@ -30,49 +29,53 @@ import org.springframework.data.document.UncategorizedDocumentStoreException;
|
||||
*/
|
||||
public abstract class CouchUtils {
|
||||
|
||||
/**
|
||||
* Convert the given runtime exception to an appropriate exception from the
|
||||
* <code>org.springframework.dao</code> hierarchy.
|
||||
* Return null if no translation is appropriate: any other exception may
|
||||
* have resulted from user code, and should not be translated.
|
||||
* @param ex runtime exception that occurred
|
||||
* @return the corresponding DataAccessException instance,
|
||||
* or <code>null</code> if the exception should not be translated
|
||||
*/
|
||||
public static DataAccessException translateCouchExceptionIfPossible(RuntimeException ex) {
|
||||
/**
|
||||
* Convert the given runtime exception to an appropriate exception from the
|
||||
* <code>org.springframework.dao</code> hierarchy.
|
||||
* Return null if no translation is appropriate: any other exception may
|
||||
* have resulted from user code, and should not be translated.
|
||||
*
|
||||
* @param ex runtime exception that occurred
|
||||
* @return the corresponding DataAccessException instance,
|
||||
* or <code>null</code> if the exception should not be translated
|
||||
*/
|
||||
public static DataAccessException translateCouchExceptionIfPossible(RuntimeException ex) {
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds an id variable to a URL
|
||||
* @param url the URL to modify
|
||||
* @return the modified URL
|
||||
*/
|
||||
public static String addId(String url) {
|
||||
return ensureTrailingSlash(url) + "{id}";
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Adds a 'changes since' variable to a URL
|
||||
* @param url
|
||||
* @return
|
||||
*/
|
||||
public static String addChangesSince(String url) {
|
||||
return ensureTrailingSlash(url) + "_changes?since={seq}";
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensures that a URL ends with a slash.
|
||||
* @param url the URL to modify
|
||||
* @return the modified URL
|
||||
*/
|
||||
public static String ensureTrailingSlash(String url) {
|
||||
if (!url.endsWith("/")) {
|
||||
url += "/";
|
||||
}
|
||||
return url;
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds an id variable to a URL
|
||||
*
|
||||
* @param url the URL to modify
|
||||
* @return the modified URL
|
||||
*/
|
||||
public static String addId(String url) {
|
||||
return ensureTrailingSlash(url) + "{id}";
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Adds a 'changes since' variable to a URL
|
||||
*
|
||||
* @param url
|
||||
* @return
|
||||
*/
|
||||
public static String addChangesSince(String url) {
|
||||
return ensureTrailingSlash(url) + "_changes?since={seq}";
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensures that a URL ends with a slash.
|
||||
*
|
||||
* @param url the URL to modify
|
||||
* @return the modified URL
|
||||
*/
|
||||
public static String ensureTrailingSlash(String url) {
|
||||
if (!url.endsWith("/")) {
|
||||
url += "/";
|
||||
}
|
||||
return url;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,33 +1,33 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<xsd:schema xmlns="http://www.springframework.org/schema/data/couch"
|
||||
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
|
||||
xmlns:tool="http://www.springframework.org/schema/tool"
|
||||
xmlns:context="http://www.springframework.org/schema/context"
|
||||
xmlns:repository="http://www.springframework.org/schema/data/repository"
|
||||
targetNamespace="http://www.springframework.org/schema/data/couch"
|
||||
elementFormDefault="qualified" attributeFormDefault="unqualified">
|
||||
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
|
||||
xmlns:tool="http://www.springframework.org/schema/tool"
|
||||
xmlns:context="http://www.springframework.org/schema/context"
|
||||
xmlns:repository="http://www.springframework.org/schema/data/repository"
|
||||
targetNamespace="http://www.springframework.org/schema/data/couch"
|
||||
elementFormDefault="qualified" attributeFormDefault="unqualified">
|
||||
|
||||
<xsd:import namespace="http://www.springframework.org/schema/tool" />
|
||||
<xsd:import namespace="http://www.springframework.org/schema/context"
|
||||
schemaLocation="http://www.springframework.org/schema/context/spring-context.xsd" />
|
||||
<xsd:import namespace="http://www.springframework.org/schema/data/repository"
|
||||
schemaLocation="http://www.springframework.org/schema/data/repository/spring-repository.xsd" />
|
||||
<xsd:import namespace="http://www.springframework.org/schema/tool"/>
|
||||
<xsd:import namespace="http://www.springframework.org/schema/context"
|
||||
schemaLocation="http://www.springframework.org/schema/context/spring-context.xsd"/>
|
||||
<xsd:import namespace="http://www.springframework.org/schema/data/repository"
|
||||
schemaLocation="http://www.springframework.org/schema/data/repository/spring-repository.xsd"/>
|
||||
|
||||
|
||||
<xsd:element name="jmx">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
<xsd:element name="jmx">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
Defines a JMX Model MBeans for monitoring a CouchDB server'.
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="database-url" type="xsd:string" use="optional">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
</xsd:annotation>
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="database-url" type="xsd:string" use="optional">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
The database URL of the CouchDB]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
|
||||
</xsd:schema>
|
||||
@@ -16,62 +16,62 @@
|
||||
|
||||
package org.springframework.data.document.couchdb;
|
||||
|
||||
import org.codehaus.jackson.annotate.JsonIgnoreProperties;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
import org.codehaus.jackson.annotate.JsonIgnoreProperties;
|
||||
|
||||
/**
|
||||
* @author Tareq Abedrabbo (tareq.abedrabbo@opencredo.com)
|
||||
* @since 13/01/2011
|
||||
*/
|
||||
@JsonIgnoreProperties(ignoreUnknown=true)
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public class DummyDocument {
|
||||
|
||||
private String message;
|
||||
private String message;
|
||||
|
||||
private String timestamp = new Date().toString();
|
||||
private String timestamp = new Date().toString();
|
||||
|
||||
public DummyDocument() {
|
||||
}
|
||||
public DummyDocument() {
|
||||
}
|
||||
|
||||
public DummyDocument(String message) {
|
||||
this.message = message;
|
||||
}
|
||||
public DummyDocument(String message) {
|
||||
this.message = message;
|
||||
}
|
||||
|
||||
public String getMessage() {
|
||||
return message;
|
||||
}
|
||||
public String getMessage() {
|
||||
return message;
|
||||
}
|
||||
|
||||
public void setMessage(String message) {
|
||||
this.message = message;
|
||||
}
|
||||
public void setMessage(String message) {
|
||||
this.message = message;
|
||||
}
|
||||
|
||||
public String getTimestamp() {
|
||||
return timestamp;
|
||||
}
|
||||
public String getTimestamp() {
|
||||
return timestamp;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
|
||||
DummyDocument document = (DummyDocument) o;
|
||||
DummyDocument document = (DummyDocument) o;
|
||||
|
||||
if (message != null ? !message.equals(document.message) : document.message != null) return false;
|
||||
if (message != null ? !message.equals(document.message) : document.message != null) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return message != null ? message.hashCode() : 0;
|
||||
}
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return message != null ? message.hashCode() : 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "DummyDocument{" +
|
||||
"message='" + message + '\'' +
|
||||
", timestamp=" + timestamp +
|
||||
'}';
|
||||
}
|
||||
@Override
|
||||
public String toString() {
|
||||
return "DummyDocument{" +
|
||||
"message='" + message + '\'' +
|
||||
", timestamp=" + timestamp +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,28 +24,29 @@ import org.springframework.http.HttpEntity;
|
||||
|
||||
/**
|
||||
* Matches the content of the body of an HttpEntity.
|
||||
*
|
||||
* @author Tareq Abedrabbo
|
||||
* @since 31/01/2011
|
||||
*/
|
||||
public class IsBodyEqual extends TypeSafeMatcher<HttpEntity> {
|
||||
|
||||
private Object object;
|
||||
private Object object;
|
||||
|
||||
public IsBodyEqual(Object object) {
|
||||
this.object = object;
|
||||
}
|
||||
public IsBodyEqual(Object object) {
|
||||
this.object = object;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean matchesSafely(HttpEntity httpEntity) {
|
||||
return httpEntity.getBody().equals(object);
|
||||
}
|
||||
@Override
|
||||
public boolean matchesSafely(HttpEntity httpEntity) {
|
||||
return httpEntity.getBody().equals(object);
|
||||
}
|
||||
|
||||
public void describeTo(Description description) {
|
||||
description.appendText("body equals ").appendValue(object);
|
||||
}
|
||||
public void describeTo(Description description) {
|
||||
description.appendText("body equals ").appendValue(object);
|
||||
}
|
||||
|
||||
@Factory
|
||||
public static Matcher<HttpEntity> bodyEqual(Object object) {
|
||||
return new IsBodyEqual(object);
|
||||
}
|
||||
@Factory
|
||||
public static Matcher<HttpEntity> bodyEqual(Object object) {
|
||||
return new IsBodyEqual(object);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,22 +18,21 @@ package org.springframework.data.document.couchdb.admin;
|
||||
import java.util.List;
|
||||
|
||||
import junit.framework.Assert;
|
||||
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
import org.springframework.data.document.couchdb.core.CouchConstants;
|
||||
|
||||
public class CouchAdminIntegrationTests {
|
||||
|
||||
@Test
|
||||
@Ignore("until CI has couch server running")
|
||||
public void dbLifecycle() {
|
||||
|
||||
CouchAdmin admin = new CouchAdmin(CouchConstants.COUCHDB_URL);
|
||||
admin.deleteDatabase("foo");
|
||||
List<String> dbs = admin.listDatabases();
|
||||
admin.createDatabase("foo");
|
||||
List<String> newDbs = admin.listDatabases();
|
||||
Assert.assertEquals(dbs.size()+1, newDbs.size());
|
||||
}
|
||||
@Test
|
||||
@Ignore("until CI has couch server running")
|
||||
public void dbLifecycle() {
|
||||
|
||||
CouchAdmin admin = new CouchAdmin(CouchConstants.COUCHDB_URL);
|
||||
admin.deleteDatabase("foo");
|
||||
List<String> dbs = admin.listDatabases();
|
||||
admin.createDatabase("foo");
|
||||
List<String> newDbs = admin.listDatabases();
|
||||
Assert.assertEquals(dbs.size() + 1, newDbs.size());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,28 +16,22 @@
|
||||
|
||||
package org.springframework.data.document.couchdb.core;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.junit.Before;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.http.HttpEntity;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.http.client.ClientHttpResponse;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
import org.springframework.web.client.DefaultResponseErrorHandler;
|
||||
import org.springframework.web.client.RestClientException;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
import static org.junit.Assume.assumeNoException;
|
||||
import static org.junit.Assume.assumeTrue;
|
||||
import static org.springframework.http.HttpStatus.OK;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.UUID;
|
||||
|
||||
import static org.junit.Assume.assumeNoException;
|
||||
import static org.junit.Assume.assumeTrue;
|
||||
import static org.springframework.http.HttpStatus.OK;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.junit.Before;
|
||||
import org.junit.BeforeClass;
|
||||
import org.springframework.http.*;
|
||||
import org.springframework.http.client.ClientHttpResponse;
|
||||
import org.springframework.web.client.DefaultResponseErrorHandler;
|
||||
import org.springframework.web.client.RestClientException;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
|
||||
/**
|
||||
* Base class for CouchDB integration tests. Checks whether CouchDB is available before running each test,
|
||||
@@ -50,75 +44,75 @@ import static org.springframework.http.HttpStatus.OK;
|
||||
public abstract class AbstractCouchTemplateIntegrationTests {
|
||||
|
||||
|
||||
protected static final Log log = LogFactory.getLog(AbstractCouchTemplateIntegrationTests.class);
|
||||
protected static final Log log = LogFactory.getLog(AbstractCouchTemplateIntegrationTests.class);
|
||||
|
||||
protected static final RestTemplate restTemplate = new RestTemplate();
|
||||
protected static final RestTemplate restTemplate = new RestTemplate();
|
||||
|
||||
/**
|
||||
* This methods ensures that the database is running. Otherwise, the test is ignored.
|
||||
*/
|
||||
@BeforeClass
|
||||
public static void assumeDatabaseIsUpAndRunning() {
|
||||
try {
|
||||
ResponseEntity<String> responseEntity = restTemplate.getForEntity(CouchConstants.COUCHDB_URL, String.class);
|
||||
assumeTrue(responseEntity.getStatusCode().equals(OK));
|
||||
log.debug("CouchDB is running on " + CouchConstants.COUCHDB_URL +
|
||||
" with status " + responseEntity.getStatusCode());
|
||||
} catch (RestClientException e) {
|
||||
log.debug("CouchDB is not running on " + CouchConstants.COUCHDB_URL);
|
||||
assumeNoException(e);
|
||||
}
|
||||
/**
|
||||
* This methods ensures that the database is running. Otherwise, the test is ignored.
|
||||
*/
|
||||
@BeforeClass
|
||||
public static void assumeDatabaseIsUpAndRunning() {
|
||||
try {
|
||||
ResponseEntity<String> responseEntity = restTemplate.getForEntity(CouchConstants.COUCHDB_URL, String.class);
|
||||
assumeTrue(responseEntity.getStatusCode().equals(OK));
|
||||
log.debug("CouchDB is running on " + CouchConstants.COUCHDB_URL +
|
||||
" with status " + responseEntity.getStatusCode());
|
||||
} catch (RestClientException e) {
|
||||
log.debug("CouchDB is not running on " + CouchConstants.COUCHDB_URL);
|
||||
assumeNoException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Before
|
||||
public void setUpTestDatabase() throws Exception {
|
||||
RestTemplate template = new RestTemplate();
|
||||
template.setErrorHandler(new DefaultResponseErrorHandler(){
|
||||
@Override
|
||||
public void handleError(ClientHttpResponse response) throws IOException {
|
||||
// do nothing, error status will be handled in the switch statement
|
||||
}
|
||||
});
|
||||
ResponseEntity<String> response = template.getForEntity(CouchConstants.TEST_DATABASE_URL, String.class);
|
||||
HttpStatus statusCode = response.getStatusCode();
|
||||
switch (statusCode) {
|
||||
case NOT_FOUND:
|
||||
createNewTestDatabase();
|
||||
break;
|
||||
case OK:
|
||||
deleteExisitingTestDatabase();
|
||||
createNewTestDatabase();
|
||||
break;
|
||||
default:
|
||||
throw new IllegalStateException("Unsupported http status [" + statusCode + "]");
|
||||
}
|
||||
@Before
|
||||
public void setUpTestDatabase() throws Exception {
|
||||
RestTemplate template = new RestTemplate();
|
||||
template.setErrorHandler(new DefaultResponseErrorHandler() {
|
||||
@Override
|
||||
public void handleError(ClientHttpResponse response) throws IOException {
|
||||
// do nothing, error status will be handled in the switch statement
|
||||
}
|
||||
});
|
||||
ResponseEntity<String> response = template.getForEntity(CouchConstants.TEST_DATABASE_URL, String.class);
|
||||
HttpStatus statusCode = response.getStatusCode();
|
||||
switch (statusCode) {
|
||||
case NOT_FOUND:
|
||||
createNewTestDatabase();
|
||||
break;
|
||||
case OK:
|
||||
deleteExisitingTestDatabase();
|
||||
createNewTestDatabase();
|
||||
break;
|
||||
default:
|
||||
throw new IllegalStateException("Unsupported http status [" + statusCode + "]");
|
||||
}
|
||||
}
|
||||
|
||||
private void deleteExisitingTestDatabase() {
|
||||
restTemplate.delete(CouchConstants.TEST_DATABASE_URL);
|
||||
}
|
||||
private void deleteExisitingTestDatabase() {
|
||||
restTemplate.delete(CouchConstants.TEST_DATABASE_URL);
|
||||
}
|
||||
|
||||
private void createNewTestDatabase() {
|
||||
restTemplate.put(CouchConstants.TEST_DATABASE_URL, null);
|
||||
}
|
||||
private void createNewTestDatabase() {
|
||||
restTemplate.put(CouchConstants.TEST_DATABASE_URL, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads a CouchDB document and converts it to the expected type.
|
||||
*/
|
||||
protected <T> T getDocument(String id, Class<T> expectedType) {
|
||||
String url = CouchConstants.TEST_DATABASE_URL + "{id}";
|
||||
return restTemplate.getForObject(url, expectedType, id);
|
||||
}
|
||||
/**
|
||||
* Reads a CouchDB document and converts it to the expected type.
|
||||
*/
|
||||
protected <T> T getDocument(String id, Class<T> expectedType) {
|
||||
String url = CouchConstants.TEST_DATABASE_URL + "{id}";
|
||||
return restTemplate.getForObject(url, expectedType, id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes a CouchDB document
|
||||
*/
|
||||
protected String putDocument(Object document) {
|
||||
HttpHeaders headers = new HttpHeaders();
|
||||
headers.setContentType(MediaType.APPLICATION_JSON);
|
||||
HttpEntity request = new HttpEntity(document, headers);
|
||||
String id = UUID.randomUUID().toString();
|
||||
restTemplate.put(CouchConstants.TEST_DATABASE_URL + "{id}", request, id);
|
||||
return id;
|
||||
}
|
||||
/**
|
||||
* Writes a CouchDB document
|
||||
*/
|
||||
protected String putDocument(Object document) {
|
||||
HttpHeaders headers = new HttpHeaders();
|
||||
headers.setContentType(MediaType.APPLICATION_JSON);
|
||||
HttpEntity request = new HttpEntity(document, headers);
|
||||
String id = UUID.randomUUID().toString();
|
||||
restTemplate.put(CouchConstants.TEST_DATABASE_URL + "{id}", request, id);
|
||||
return id;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,11 +17,11 @@ package org.springframework.data.document.couchdb.core;
|
||||
|
||||
public abstract class CouchConstants {
|
||||
|
||||
public static final String COUCHDB_URL = "http://127.0.0.1:5984/";
|
||||
public static final String TEST_DATABASE_URL = COUCHDB_URL + "si_couchdb_test/";
|
||||
public static final String COUCHDB_URL = "http://127.0.0.1:5984/";
|
||||
public static final String TEST_DATABASE_URL = COUCHDB_URL + "si_couchdb_test/";
|
||||
|
||||
public CouchConstants() {
|
||||
// TODO Auto-generated constructor stub
|
||||
}
|
||||
public CouchConstants() {
|
||||
// TODO Auto-generated constructor stub
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -19,22 +19,21 @@ package org.springframework.data.document.couchdb.core;
|
||||
import java.util.UUID;
|
||||
|
||||
import junit.framework.Assert;
|
||||
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
import org.springframework.data.document.couchdb.DummyDocument;
|
||||
|
||||
public class CouchTemplateIntegrationTests extends AbstractCouchTemplateIntegrationTests {
|
||||
|
||||
|
||||
@Test
|
||||
@Ignore("until CI has couch server running")
|
||||
public void saveAndFindTest() {
|
||||
CouchTemplate template = new CouchTemplate(CouchConstants.TEST_DATABASE_URL);
|
||||
DummyDocument document = new DummyDocument("hello");
|
||||
String id = UUID.randomUUID().toString();
|
||||
template.save(id, document);
|
||||
DummyDocument foundDocument = template.findOne(id, DummyDocument.class);
|
||||
Assert.assertEquals(document.getMessage(), foundDocument.getMessage());
|
||||
}
|
||||
|
||||
@Test
|
||||
@Ignore("until CI has couch server running")
|
||||
public void saveAndFindTest() {
|
||||
CouchTemplate template = new CouchTemplate(CouchConstants.TEST_DATABASE_URL);
|
||||
DummyDocument document = new DummyDocument("hello");
|
||||
String id = UUID.randomUUID().toString();
|
||||
template.save(id, document);
|
||||
DummyDocument foundDocument = template.findOne(id, DummyDocument.class);
|
||||
Assert.assertEquals(document.getMessage(), foundDocument.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,13 +20,11 @@ import org.junit.Test;
|
||||
|
||||
/**
|
||||
* Unit tests for CouchTemplate with mocks
|
||||
*
|
||||
*
|
||||
*/
|
||||
public class CouchTemplateTests {
|
||||
|
||||
@Test
|
||||
public void foo() {
|
||||
|
||||
}
|
||||
@Test
|
||||
public void foo() {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,17 +20,17 @@ import org.springframework.context.support.ClassPathXmlApplicationContext;
|
||||
|
||||
/**
|
||||
* Server application to test JMX functionality.
|
||||
*
|
||||
*
|
||||
* @author Mark Pollack
|
||||
*/
|
||||
public class JmxServer {
|
||||
|
||||
public static void main(String[] args) {
|
||||
new JmxServer().run();
|
||||
}
|
||||
public static void main(String[] args) {
|
||||
new JmxServer().run();
|
||||
}
|
||||
|
||||
public void run() {
|
||||
new ClassPathXmlApplicationContext(new String[] {"server-jmx.xml"} );
|
||||
}
|
||||
public void run() {
|
||||
new ClassPathXmlApplicationContext(new String[]{"server-jmx.xml"});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,25 +1,24 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<beans xmlns="http://www.springframework.org/schema/beans"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:context="http://www.springframework.org/schema/context"
|
||||
xmlns:p="http://www.springframework.org/schema/p"
|
||||
xmlns:couch="http://www.springframework.org/schema/data/couch"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:context="http://www.springframework.org/schema/context"
|
||||
xmlns:p="http://www.springframework.org/schema/p"
|
||||
xmlns:couch="http://www.springframework.org/schema/data/couch"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
|
||||
http://www.springframework.org/schema/data/couch http://www.springframework.org/schema/data/couch/spring-couch-1.0.xsd
|
||||
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd">
|
||||
|
||||
|
||||
|
||||
<couch:jmx/>
|
||||
<couch:jmx/>
|
||||
|
||||
<context:mbean-export/>
|
||||
<context:mbean-export/>
|
||||
|
||||
<bean id="registry" class="org.springframework.remoting.rmi.RmiRegistryFactoryBean"
|
||||
p:port="1099"/>
|
||||
|
||||
<!-- Expose JMX over RMI -->
|
||||
<bean id="serverConnector" class="org.springframework.jmx.support.ConnectorServerFactoryBean" depends-on="registry"
|
||||
p:objectName="connector:name=rmi"
|
||||
p:serviceUrl="service:jmx:rmi://localhost/jndi/rmi://localhost:1099/myconnector"/>
|
||||
|
||||
<bean id="registry" class="org.springframework.remoting.rmi.RmiRegistryFactoryBean"
|
||||
p:port="1099" />
|
||||
|
||||
<!-- Expose JMX over RMI -->
|
||||
<bean id="serverConnector" class="org.springframework.jmx.support.ConnectorServerFactoryBean" depends-on="registry"
|
||||
p:objectName="connector:name=rmi"
|
||||
p:serviceUrl="service:jmx:rmi://localhost/jndi/rmi://localhost:1099/myconnector" />
|
||||
|
||||
</beans>
|
||||
Reference in New Issue
Block a user