Format, organize imports, remove eclipse artifacts

This commit is contained in:
J. Brisbin
2011-03-15 11:57:55 -05:00
parent d4f358abd0
commit 032de81478
217 changed files with 14868 additions and 14762 deletions

1
.gitignore vendored
View File

@@ -1,6 +1,7 @@
.DS_Store .DS_Store
*.iml *.iml
*.ipr *.ipr
*.iws
target target
.springBeans .springBeans
.ant-targets-build.xml .ant-targets-build.xml

View File

@@ -1,17 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>spring-data-document-dist</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.maven.ide.eclipse.maven2Builder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.maven.ide.eclipse.maven2Nature</nature>
</natures>
</projectDescription>

View File

@@ -1,9 +0,0 @@
#Fri Oct 08 14:31:54 EDT 2010
activeProfiles=
eclipse.preferences.version=1
fullBuildGoals=process-test-resources
includeModules=false
resolveWorkspaceProjects=true
resourceFilterGoals=process-resources resources\:testResources
skipCompilerPlugin=true
version=1

486
pom.xml
View File

@@ -1,257 +1,257 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<groupId>org.springframework.data</groupId> <groupId>org.springframework.data</groupId>
<artifactId>spring-data-document-dist</artifactId> <artifactId>spring-data-document-dist</artifactId>
<name>Spring Data Document Distribution</name> <name>Spring Data Document Distribution</name>
<version>1.0.0.BUILD-SNAPSHOT</version> <version>1.0.0.BUILD-SNAPSHOT</version>
<packaging>pom</packaging> <packaging>pom</packaging>
<modules> <modules>
<module>spring-data-document-parent</module> <module>spring-data-document-parent</module>
<module>spring-data-document-core</module> <module>spring-data-document-core</module>
<module>spring-data-mongodb</module> <module>spring-data-mongodb</module>
<module>spring-data-mongodb-cross-store</module> <module>spring-data-mongodb-cross-store</module>
<module>spring-data-couchdb</module> <module>spring-data-couchdb</module>
</modules> </modules>
<developers> <developers>
<developer> <developer>
<id>trisberg</id> <id>trisberg</id>
<name>Thomas Risberg</name> <name>Thomas Risberg</name>
<email>trisberg at vmware.com</email> <email>trisberg at vmware.com</email>
<organization>SpringSource</organization> <organization>SpringSource</organization>
<organizationUrl>http://www.SpringSource.com</organizationUrl> <organizationUrl>http://www.SpringSource.com</organizationUrl>
<roles> <roles>
<role>Project Admin</role> <role>Project Admin</role>
<role>Developer</role> <role>Developer</role>
</roles> </roles>
<timezone>-5</timezone> <timezone>-5</timezone>
</developer> </developer>
<developer> <developer>
<id>mpollack</id> <id>mpollack</id>
<name>Mark Pollack</name> <name>Mark Pollack</name>
<email>mpollack at vmware.com</email> <email>mpollack at vmware.com</email>
<organization>SpringSource</organization> <organization>SpringSource</organization>
<organizationUrl>http://www.SpringSource.com</organizationUrl> <organizationUrl>http://www.SpringSource.com</organizationUrl>
<roles> <roles>
<role>Project Admin</role> <role>Project Admin</role>
<role>Developer</role> <role>Developer</role>
</roles> </roles>
<timezone>-5</timezone> <timezone>-5</timezone>
</developer> </developer>
<developer> <developer>
<id>ogierke</id> <id>ogierke</id>
<name>Oliver Gierke</name> <name>Oliver Gierke</name>
<email>ogierke at vmware.com</email> <email>ogierke at vmware.com</email>
<organization>SpringSource</organization> <organization>SpringSource</organization>
<organizationUrl>http://www.springsource.com</organizationUrl> <organizationUrl>http://www.springsource.com</organizationUrl>
<roles> <roles>
<role>Developer</role> <role>Developer</role>
</roles> </roles>
<timezone>+1</timezone> <timezone>+1</timezone>
</developer> </developer>
</developers> </developers>
<licenses> <licenses>
<license> <license>
<name>Apache License, Version 2.0</name> <name>Apache License, Version 2.0</name>
<url>http://www.apache.org/licenses/LICENSE-2.0</url> <url>http://www.apache.org/licenses/LICENSE-2.0</url>
<comments> <comments>
Copyright 2010 the original author or authors. 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.
</comments>
</license>
</licenses>
<properties> Licensed under the Apache License, Version 2.0 (the "License");
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> you may not use this file except in compliance with the License.
<!-- dist.* properties are used by the antrun tasks below --> You may obtain a copy of the License at
<dist.id>spring-data-document</dist.id>
<dist.name>Spring Data</dist.name>
<dist.key>DATADOC</dist.key>
<dist.version>${project.version}</dist.version>
<dist.releaseType>snapshot</dist.releaseType>
<dist.finalName>${dist.id}-${dist.version}</dist.finalName>
<dist.fileName>${dist.finalName}.zip</dist.fileName>
<dist.filePath>target/${dist.fileName}</dist.filePath>
<dist.bucketName>dist.springframework.org</dist.bucketName>
<!-- these properties should be in ~/.m2/settings.xml
<dist.accessKey>s3 access key</dist.accessKey>
<dist.secretKey>s3 secret key</dist.secretKey>
-->
</properties>
<build> http://www.apache.org/licenses/LICENSE-2.0
<extensions>
<extension>
<groupId>org.springframework.build.aws</groupId>
<artifactId>org.springframework.build.aws.maven</artifactId>
<version>3.1.0.RELEASE</version>
</extension>
</extensions>
<plugins> Unless required by applicable law or agreed to in writing, software
<plugin> distributed under the License is distributed on an "AS IS" BASIS,
<artifactId>maven-compiler-plugin</artifactId> WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
<configuration> implied.
<source>1.6</source> See the License for the specific language governing permissions and
<target>1.6</target> limitations under the License.
</configuration> </comments>
</plugin> </license>
</licenses>
<plugin> <properties>
<groupId>com.agilejava.docbkx</groupId> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<artifactId>docbkx-maven-plugin</artifactId> <!-- dist.* properties are used by the antrun tasks below -->
<version>2.0.7</version> <dist.id>spring-data-document</dist.id>
<executions> <dist.name>Spring Data</dist.name>
<execution> <dist.key>DATADOC</dist.key>
<goals> <dist.version>${project.version}</dist.version>
<goal>generate-html</goal> <dist.releaseType>snapshot</dist.releaseType>
<goal>generate-pdf</goal> <dist.finalName>${dist.id}-${dist.version}</dist.finalName>
</goals> <dist.fileName>${dist.finalName}.zip</dist.fileName>
<phase>pre-site</phase> <dist.filePath>target/${dist.fileName}</dist.filePath>
</execution> <dist.bucketName>dist.springframework.org</dist.bucketName>
</executions> <!-- these properties should be in ~/.m2/settings.xml
<dependencies> <dist.accessKey>s3 access key</dist.accessKey>
<dependency> <dist.secretKey>s3 secret key</dist.secretKey>
<groupId>org.docbook</groupId> -->
<artifactId>docbook-xml</artifactId> </properties>
<version>4.4</version>
<scope>runtime</scope> <build>
</dependency> <extensions>
</dependencies> <extension>
<configuration> <groupId>org.springframework.build.aws</groupId>
<includes>index.xml</includes> <artifactId>org.springframework.build.aws.maven</artifactId>
<xincludeSupported>true</xincludeSupported> <version>3.1.0.RELEASE</version>
<foCustomization>${project.basedir}/src/docbkx/resources/xsl/fopdf.xsl</foCustomization> </extension>
<htmlStylesheet>css/html.css</htmlStylesheet> </extensions>
<chunkedOutput>false</chunkedOutput>
<htmlCustomization>${project.basedir}/src/docbkx/resources/xsl/html.xsl</htmlCustomization> <plugins>
<useExtensions>1</useExtensions> <plugin>
<highlightSource>1</highlightSource> <artifactId>maven-compiler-plugin</artifactId>
<highlightDefaultLanguage></highlightDefaultLanguage> <configuration>
<source>1.6</source>
<target>1.6</target>
</configuration>
</plugin>
<plugin>
<groupId>com.agilejava.docbkx</groupId>
<artifactId>docbkx-maven-plugin</artifactId>
<version>2.0.7</version>
<executions>
<execution>
<goals>
<goal>generate-html</goal>
<goal>generate-pdf</goal>
</goals>
<phase>pre-site</phase>
</execution>
</executions>
<dependencies>
<dependency>
<groupId>org.docbook</groupId>
<artifactId>docbook-xml</artifactId>
<version>4.4</version>
<scope>runtime</scope>
</dependency>
</dependencies>
<configuration>
<includes>index.xml</includes>
<xincludeSupported>true</xincludeSupported>
<foCustomization>${project.basedir}/src/docbkx/resources/xsl/fopdf.xsl</foCustomization>
<htmlStylesheet>css/html.css</htmlStylesheet>
<chunkedOutput>false</chunkedOutput>
<htmlCustomization>${project.basedir}/src/docbkx/resources/xsl/html.xsl</htmlCustomization>
<useExtensions>1</useExtensions>
<highlightSource>1</highlightSource>
<highlightDefaultLanguage></highlightDefaultLanguage>
<!-- callouts --> <!-- callouts -->
<entities> <entities>
<entity> <entity>
<name>version</name> <name>version</name>
<value>${pom.version}</value> <value>${pom.version}</value>
</entity> </entity>
</entities> </entities>
<postProcess> <postProcess>
<copy todir="${project.basedir}/target/site/reference"> <copy todir="${project.basedir}/target/site/reference">
<fileset dir="${project.basedir}/target/docbkx"> <fileset dir="${project.basedir}/target/docbkx">
<include name="**/*.html" /> <include name="**/*.html"/>
<include name="**/*.pdf" /> <include name="**/*.pdf"/>
</fileset> </fileset>
</copy> </copy>
<copy todir="${project.basedir}/target/site/reference/html"> <copy todir="${project.basedir}/target/site/reference/html">
<fileset dir="${project.basedir}/src/docbkx/resources"> <fileset dir="${project.basedir}/src/docbkx/resources">
<include name="**/*.css" /> <include name="**/*.css"/>
<include name="**/*.png" /> <include name="**/*.png"/>
<include name="**/*.gif" /> <include name="**/*.gif"/>
<include name="**/*.jpg" /> <include name="**/*.jpg"/>
</fileset> </fileset>
</copy> </copy>
<move file="${project.basedir}/target/site/reference/pdf/index.pdf" <move file="${project.basedir}/target/site/reference/pdf/index.pdf"
tofile="${project.basedir}/target/site/reference/pdf/spring-data-document-reference.pdf" tofile="${project.basedir}/target/site/reference/pdf/spring-data-document-reference.pdf"
failonerror="false" /> failonerror="false"/>
</postProcess> </postProcess>
</configuration> </configuration>
</plugin> </plugin>
<plugin> <plugin>
<artifactId>maven-javadoc-plugin</artifactId> <artifactId>maven-javadoc-plugin</artifactId>
<version>2.5</version> <version>2.5</version>
<configuration> <configuration>
<javadoc:aggregate>true</javadoc:aggregate> <javadoc:aggregate>true</javadoc:aggregate>
<breakiterator>true</breakiterator> <breakiterator>true</breakiterator>
<header>Spring Data Graph</header> <header>Spring Data Graph</header>
<source>1.6</source> <source>1.6</source>
<quiet>true</quiet> <quiet>true</quiet>
<javadocDirectory>${project.basedir}/src/main/javadoc</javadocDirectory> <javadocDirectory>${project.basedir}/src/main/javadoc</javadocDirectory>
<overview>${project.basedir}/src/main/javadoc/overview.html</overview> <overview>${project.basedir}/src/main/javadoc/overview.html</overview>
<stylesheetfile>${project.basedir}/src/main/javadoc/spring-javadoc.css</stylesheetfile> <stylesheetfile>${project.basedir}/src/main/javadoc/spring-javadoc.css</stylesheetfile>
<!-- copies doc-files subdirectory which contains image resources --> <!-- copies doc-files subdirectory which contains image resources -->
<docfilessubdirs>true</docfilessubdirs> <docfilessubdirs>true</docfilessubdirs>
<links> <links>
<link>http://static.springframework.org/spring/docs/3.0.x/javadoc-api</link> <link>http://static.springframework.org/spring/docs/3.0.x/javadoc-api</link>
<link>http://java.sun.com/javase/6/docs/api</link> <link>http://java.sun.com/javase/6/docs/api</link>
<link>http://api.mongodb.org/java/2.3</link> <link>http://api.mongodb.org/java/2.3</link>
</links> </links>
</configuration> </configuration>
</plugin> </plugin>
<plugin><!-- <plugin><!--
run `mvn package assembly:assembly` to trigger assembly creation. run `mvn package assembly:assembly` to trigger assembly creation.
see http://www.sonatype.com/books/mvnref-book/reference/assemblies-set-dist-assemblies.html --> see http://www.sonatype.com/books/mvnref-book/reference/assemblies-set-dist-assemblies.html -->
<artifactId>maven-assembly-plugin</artifactId> <artifactId>maven-assembly-plugin</artifactId>
<version>2.2-beta-5</version> <version>2.2-beta-5</version>
<inherited>false</inherited> <inherited>false</inherited>
<executions> <executions>
<execution> <execution>
<id>distribution</id> <id>distribution</id>
<goals> <goals>
<goal>single</goal> <goal>single</goal>
</goals> </goals>
<phase>package</phase> <phase>package</phase>
<configuration> <configuration>
<descriptors> <descriptors>
<descriptor>${project.basedir}/src/assembly/distribution.xml</descriptor> <descriptor>${project.basedir}/src/assembly/distribution.xml</descriptor>
</descriptors> </descriptors>
<appendAssemblyId>false</appendAssemblyId> <appendAssemblyId>false</appendAssemblyId>
</configuration> </configuration>
</execution> </execution>
</executions> </executions>
</plugin> </plugin>
<plugin> <plugin>
<groupId>org.apache.maven.plugins</groupId> <groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-antrun-plugin</artifactId> <artifactId>maven-antrun-plugin</artifactId>
<version>1.4</version> <version>1.4</version>
<executions> <executions>
<execution> <execution>
<id>upload-dist</id> <id>upload-dist</id>
<phase>deploy</phase> <phase>deploy</phase>
<configuration> <configuration>
<tasks> <tasks>
<ant antfile="${basedir}/src/ant/upload-dist.xml"> <ant antfile="${basedir}/src/ant/upload-dist.xml">
<target name="upload-dist"/> <target name="upload-dist"/>
</ant> </ant>
</tasks> </tasks>
</configuration> </configuration>
<goals> <goals>
<goal>run</goal> <goal>run</goal>
</goals> </goals>
</execution> </execution>
</executions> </executions>
<dependencies> <dependencies>
<dependency> <dependency>
<groupId>org.springframework.build</groupId> <groupId>org.springframework.build</groupId>
<artifactId>org.springframework.build.aws.ant</artifactId> <artifactId>org.springframework.build.aws.ant</artifactId>
<version>3.0.5.RELEASE</version> <version>3.0.5.RELEASE</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>net.java.dev.jets3t</groupId> <groupId>net.java.dev.jets3t</groupId>
<artifactId>jets3t</artifactId> <artifactId>jets3t</artifactId>
<version>0.7.2</version> <version>0.7.2</version>
</dependency> </dependency>
</dependencies> </dependencies>
</plugin> </plugin>
</plugins> </plugins>
<!-- the name of this project is 'spring-data-document-dist'; <!-- the name of this project is 'spring-data-document-dist';
make sure the zip file is just 'spring-data-document'. --> make sure the zip file is just 'spring-data-document'. -->
<finalName>${dist.finalName}</finalName> <finalName>${dist.finalName}</finalName>
</build> </build>
<distributionManagement> <distributionManagement>
<!-- see 'staging' profile for dry-run deployment settings --> <!-- see 'staging' profile for dry-run deployment settings -->

View File

@@ -1,10 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="src" output="target/classes" path="src/main/java"/>
<classpathentry kind="src" path="src/test/java"/>
<classpathentry kind="src" path="src/test/resources"/>
<classpathentry kind="src" path="src/main/resources"/>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/J2SE-1.5"/>
<classpathentry kind="con" path="org.maven.ide.eclipse.MAVEN2_CLASSPATH_CONTAINER"/>
<classpathentry kind="output" path="target/classes"/>
</classpath>

View File

@@ -1,23 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>spring-data-couchdb</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.maven.ide.eclipse.maven2Builder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.jdt.core.javanature</nature>
<nature>org.maven.ide.eclipse.maven2Nature</nature>
</natures>
</projectDescription>

View File

@@ -1,6 +0,0 @@
#Wed Oct 06 14:49:48 EDT 2010
eclipse.preferences.version=1
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.5
org.eclipse.jdt.core.compiler.compliance=1.5
org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
org.eclipse.jdt.core.compiler.source=1.5

View File

@@ -1,9 +0,0 @@
#Wed Oct 06 14:49:46 EDT 2010
activeProfiles=
eclipse.preferences.version=1
fullBuildGoals=process-test-resources
includeModules=false
resolveWorkspaceProjects=true
resourceFilterGoals=process-resources resources\:testResources
skipCompilerPlugin=true
version=1

View File

@@ -19,15 +19,16 @@ import org.springframework.dao.InvalidDataAccessResourceUsageException;
import org.springframework.web.client.HttpServerErrorException; import org.springframework.web.client.HttpServerErrorException;
public class CouchServerResourceUsageException extends InvalidDataAccessResourceUsageException { public class CouchServerResourceUsageException extends InvalidDataAccessResourceUsageException {
/** /**
* Create a new CouchServerResourceUsageException, * Create a new CouchServerResourceUsageException,
* wrapping an arbitrary HttpServerErrorException. * wrapping an arbitrary HttpServerErrorException.
* @param cause the HttpServerErrorException thrown *
*/ * @param cause the HttpServerErrorException thrown
public CouchServerResourceUsageException(HttpServerErrorException cause) { */
super(cause != null ? cause.getMessage() : null, cause); public CouchServerResourceUsageException(HttpServerErrorException cause) {
} super(cause != null ? cause.getMessage() : null, cause);
}
} }

View File

@@ -17,19 +17,18 @@ package org.springframework.data.document.couchdb;
import org.springframework.dao.InvalidDataAccessApiUsageException; import org.springframework.dao.InvalidDataAccessApiUsageException;
import org.springframework.web.client.HttpClientErrorException; import org.springframework.web.client.HttpClientErrorException;
import org.springframework.web.client.HttpServerErrorException;
public class CouchUsageException extends InvalidDataAccessApiUsageException public class CouchUsageException extends InvalidDataAccessApiUsageException {
{
/**
/** * Create a new CouchUsageException,
* Create a new CouchUsageException, * wrapping an arbitrary HttpServerErrorException.
* wrapping an arbitrary HttpServerErrorException. *
* @param cause the HttpServerErrorException thrown * @param cause the HttpServerErrorException thrown
*/ */
public CouchUsageException(HttpClientErrorException cause) { public CouchUsageException(HttpClientErrorException cause) {
super(cause != null ? cause.getMessage() : null, cause); super(cause != null ? cause.getMessage() : null, cause);
} }
} }

View File

@@ -18,17 +18,17 @@ package org.springframework.data.document.couchdb;
import org.springframework.dao.DataIntegrityViolationException; import org.springframework.dao.DataIntegrityViolationException;
import org.springframework.web.client.HttpStatusCodeException; import org.springframework.web.client.HttpStatusCodeException;
public class DocumentExistsException extends DataIntegrityViolationException public class DocumentExistsException extends DataIntegrityViolationException {
{
/**
/** * Create a new DocumentExistsException,
* Create a new DocumentExistsException, * wrapping an arbitrary HttpServerErrorException.
* wrapping an arbitrary HttpServerErrorException. *
* @param cause the HttpServerErrorException thrown * @param cause the HttpServerErrorException thrown
*/ */
public DocumentExistsException(String documentId, HttpStatusCodeException cause) { public DocumentExistsException(String documentId, HttpStatusCodeException cause) {
super(cause != null ? cause.getMessage() : null, cause); super(cause != null ? cause.getMessage() : null, cause);
} }
} }

View File

@@ -18,21 +18,18 @@ package org.springframework.data.document.couchdb;
import org.springframework.dao.DataRetrievalFailureException; import org.springframework.dao.DataRetrievalFailureException;
public class DocumentRetrievalFailureException extends public class DocumentRetrievalFailureException extends
DataRetrievalFailureException { DataRetrievalFailureException {
private String documentPath; private String documentPath;
public DocumentRetrievalFailureException(String documentPath) { public DocumentRetrievalFailureException(String documentPath) {
super("Could not find document at path = " + documentPath); super("Could not find document at path = " + documentPath);
this.documentPath = documentPath; this.documentPath = documentPath;
} }
public String getDocumentPath() { public String getDocumentPath() {
return documentPath; return documentPath;
} }
} }

View File

@@ -20,14 +20,15 @@ import org.springframework.web.client.RestClientException;
public class UncategorizedCouchDataAccessException extends UncategorizedDataAccessException { public class UncategorizedCouchDataAccessException extends UncategorizedDataAccessException {
/** /**
* Create a new HibernateSystemException, * Create a new HibernateSystemException,
* wrapping an arbitrary HibernateException. * wrapping an arbitrary HibernateException.
* @param cause the HibernateException thrown *
*/ * @param cause the HibernateException thrown
public UncategorizedCouchDataAccessException(RestClientException cause) { */
super(cause != null ? cause.getMessage() : null, cause); public UncategorizedCouchDataAccessException(RestClientException cause) {
} super(cause != null ? cause.getMessage() : null, cause);
}
} }

View File

@@ -26,39 +26,39 @@ import org.springframework.web.client.RestTemplate;
public class CouchAdmin implements CouchAdminOperations { public class CouchAdmin implements CouchAdminOperations {
private String databaseUrl; private String databaseUrl;
private RestOperations restOperations = new RestTemplate(); 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));
}
public void createDatabase(String dbName) { public CouchAdmin(String databaseUrl) {
org.springframework.util.Assert.hasText(dbName);
restOperations.put(databaseUrl + dbName, null);
} if (!databaseUrl.trim().endsWith("/")) {
this.databaseUrl = databaseUrl.trim() + "/";
} else {
this.databaseUrl = databaseUrl.trim();
}
}
public void deleteDatabase(String dbName) { public List<String> listDatabases() {
org.springframework.util.Assert.hasText(dbName); String dbs = restOperations.getForObject(databaseUrl + "_all_dbs", String.class);
restOperations.delete(CouchUtils.ensureTrailingSlash(databaseUrl + dbName)); 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); public void deleteDatabase(String dbName) {
return new DbInfo(dbInfoMap); 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);
}
} }

View File

@@ -19,16 +19,16 @@ import java.util.List;
public interface CouchAdminOperations { public interface CouchAdminOperations {
// functionality for /_special - replication, logs, UUIDs // functionality for /_special - replication, logs, UUIDs
List<String> listDatabases(); List<String> listDatabases();
void createDatabase(String name); void createDatabase(String name);
void deleteDatabase(String name); void deleteDatabase(String name);
DbInfo getDatabaseInfo(String name); DbInfo getDatabaseInfo(String name);
} }

View File

@@ -21,57 +21,52 @@ import java.util.Map;
public class DbInfo { public class DbInfo {
private Map dbInfoMap; private Map dbInfoMap;
public DbInfo(Map dbInfoMap) {
super();
this.dbInfoMap = dbInfoMap;
}
public boolean isCompactRunning() { public DbInfo(Map dbInfoMap) {
return (Boolean) this.dbInfoMap.get("compact_running"); super();
} this.dbInfoMap = dbInfoMap;
}
public String getDbName() { public boolean isCompactRunning() {
return (String) this.dbInfoMap.get("db_name"); return (Boolean) this.dbInfoMap.get("compact_running");
} }
public long getDiskFormatVersion() { public String getDbName() {
return (Long) this.dbInfoMap.get("disk_format_version"); return (String) this.dbInfoMap.get("db_name");
} }
public long getDiskSize() { public long getDiskFormatVersion() {
return (Long) this.dbInfoMap.get("disk_size"); return (Long) this.dbInfoMap.get("disk_format_version");
} }
public long getDocCount() { public long getDiskSize() {
return (Long) this.dbInfoMap.get("doc_count"); return (Long) this.dbInfoMap.get("disk_size");
} }
public long getDocDeleteCount() { public long getDocCount() {
return (Long) this.dbInfoMap.get("doc_del_count"); return (Long) this.dbInfoMap.get("doc_count");
} }
public long getInstanceStartTime() { public long getDocDeleteCount() {
return (Long) this.dbInfoMap.get("instance_start_time"); return (Long) this.dbInfoMap.get("doc_del_count");
} }
public long getPurgeSequence() { public long getInstanceStartTime() {
return (Long) this.dbInfoMap.get("purge_seq"); return (Long) this.dbInfoMap.get("instance_start_time");
} }
public long getUpdateSequence() { public long getPurgeSequence() {
return (Long) this.dbInfoMap.get("update_seq"); return (Long) this.dbInfoMap.get("purge_seq");
} }
public Map getDbInfoMap() { public long getUpdateSequence() {
return Collections.unmodifiableMap(dbInfoMap); return (Long) this.dbInfoMap.get("update_seq");
} }
public Map getDbInfoMap() {
return Collections.unmodifiableMap(dbInfoMap);
}
} }

View File

@@ -27,44 +27,44 @@ import org.w3c.dom.Element;
public class CouchJmxParser implements BeanDefinitionParser { public class CouchJmxParser implements BeanDefinitionParser {
public BeanDefinition parse(Element element, ParserContext parserContext) { public BeanDefinition parse(Element element, ParserContext parserContext) {
String databaseUrl = element.getAttribute("database-url"); String databaseUrl = element.getAttribute("database-url");
if (!StringUtils.hasText(databaseUrl)) { if (!StringUtils.hasText(databaseUrl)) {
databaseUrl = "http://localhost:5984"; databaseUrl = "http://localhost:5984";
} }
registerJmxComponents(databaseUrl, element, parserContext); registerJmxComponents(databaseUrl, element, parserContext);
return null; return null;
} }
protected void registerJmxComponents(String databaseUrl, Element element, ParserContext parserContext) { protected void registerJmxComponents(String databaseUrl, Element element, ParserContext parserContext) {
Object eleSource = parserContext.extractSource(element); Object eleSource = parserContext.extractSource(element);
CompositeComponentDefinition compositeDef = new CompositeComponentDefinition(element.getTagName(), eleSource); CompositeComponentDefinition compositeDef = new CompositeComponentDefinition(element.getTagName(), eleSource);
/* /*
createBeanDefEntry(AssertMetrics.class, compositeDef, mongoRefName, eleSource, parserContext); createBeanDefEntry(AssertMetrics.class, compositeDef, mongoRefName, eleSource, parserContext);
createBeanDefEntry(BackgroundFlushingMetrics.class, compositeDef, mongoRefName, eleSource, parserContext); createBeanDefEntry(BackgroundFlushingMetrics.class, compositeDef, mongoRefName, eleSource, parserContext);
createBeanDefEntry(BtreeIndexCounters.class, compositeDef, mongoRefName, eleSource, parserContext); createBeanDefEntry(BtreeIndexCounters.class, compositeDef, mongoRefName, eleSource, parserContext);
createBeanDefEntry(ConnectionMetrics.class, compositeDef, mongoRefName, eleSource, parserContext); createBeanDefEntry(ConnectionMetrics.class, compositeDef, mongoRefName, eleSource, parserContext);
createBeanDefEntry(GlobalLockMetrics.class, compositeDef, mongoRefName, eleSource, parserContext); createBeanDefEntry(GlobalLockMetrics.class, compositeDef, mongoRefName, eleSource, parserContext);
createBeanDefEntry(MemoryMetrics.class, compositeDef, mongoRefName, eleSource, parserContext); createBeanDefEntry(MemoryMetrics.class, compositeDef, mongoRefName, eleSource, parserContext);
createBeanDefEntry(OperationCounters.class, compositeDef, mongoRefName, eleSource, parserContext); createBeanDefEntry(OperationCounters.class, compositeDef, mongoRefName, eleSource, parserContext);
*/ */
createBeanDefEntry(ServerInfo.class, compositeDef, databaseUrl, eleSource, parserContext); createBeanDefEntry(ServerInfo.class, compositeDef, databaseUrl, eleSource, parserContext);
//createBeanDefEntry(MongoAdmin.class, compositeDef, mongoRefName, eleSource, parserContext); //createBeanDefEntry(MongoAdmin.class, compositeDef, mongoRefName, eleSource, parserContext);
parserContext.registerComponent(compositeDef); 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));
}
} }

View File

@@ -21,23 +21,23 @@ import org.springframework.beans.factory.xml.NamespaceHandlerSupport;
/** /**
* {@link org.springframework.beans.factory.xml.NamespaceHandler} for Couch DB * {@link org.springframework.beans.factory.xml.NamespaceHandler} for Couch DB
* based repositories. * based repositories.
* *
* @author Oliver Gierke * @author Oliver Gierke
*/ */
public class CouchNamespaceHandler extends NamespaceHandlerSupport { public class CouchNamespaceHandler extends NamespaceHandlerSupport {
/* /*
* (non-Javadoc) * (non-Javadoc)
* *
* @see org.springframework.beans.factory.xml.NamespaceHandler#init() * @see org.springframework.beans.factory.xml.NamespaceHandler#init()
*/ */
public void init() { public void init() {
/* /*
registerBeanDefinitionParser("repositories", registerBeanDefinitionParser("repositories",
new MongoRepositoryConfigDefinitionParser()); new MongoRepositoryConfigDefinitionParser());
*/ */
registerBeanDefinitionParser("jmx", new CouchJmxParser()); registerBeanDefinitionParser("jmx", new CouchJmxParser());
} }
} }

View File

@@ -20,44 +20,44 @@ import java.net.URI;
public interface CouchOperations { public interface CouchOperations {
/** /**
* Reads a document from the database and maps it a Java object. * Reads a document from the database and maps it a Java object.
* </p> * </p>
* This method is intended to work when a default database * This method is intended to work when a default database
* is set on the CouchDbDocumentOperations instance. * is set on the CouchDbDocumentOperations instance.
* *
* @param id the id of the CouchDB document to read * @param id the id of the CouchDB document to read
* @param targetClass the target type to map to * @param targetClass the target type to map to
* @return the mapped object * @return the mapped object
*/ */
<T> T findOne(String id, Class<T> targetClass); <T> T findOne(String id, Class<T> targetClass);
/** /**
* Reads a document from the database and maps it a Java object. * Reads a document from the database and maps it a Java object.
* *
* @param uri the full URI of the document to read * @param uri the full URI of the document to read
* @param targetClass the target type to map to * @param targetClass the target type to map to
* @return the mapped object * @return the mapped object
*/ */
<T> T findOne(URI uri, Class<T> targetClass); <T> T findOne(URI uri, Class<T> targetClass);
/** /**
* Maps a Java object to JSON and writes it to the database * Maps a Java object to JSON and writes it to the database
* </p> * </p>
* This method is intended to work when a default database * This method is intended to work when a default database
* is set on the CouchDbDocumentOperations instance. * is set on the CouchDbDocumentOperations instance.
* *
* @param id the id of the document to write * @param id the id of the document to write
* @param document the object to write * @param document the object to write
*/ */
void save(String id, Object document); void save(String id, Object document);
/** /**
* Maps a Java object to JSON and writes it to the database * Maps a Java object to JSON and writes it to the database
* *
* @param uri the full URI of the document to write * @param uri the full URI of the document to write
* @param document the object to write * @param document the object to write
*/ */
void save(URI uri, Object document); void save(URI uri, Object document);
} }

View File

@@ -26,128 +26,118 @@ import org.springframework.data.document.couchdb.CouchUsageException;
import org.springframework.data.document.couchdb.DocumentRetrievalFailureException; import org.springframework.data.document.couchdb.DocumentRetrievalFailureException;
import org.springframework.data.document.couchdb.UncategorizedCouchDataAccessException; import org.springframework.data.document.couchdb.UncategorizedCouchDataAccessException;
import org.springframework.data.document.couchdb.support.CouchUtils; import org.springframework.data.document.couchdb.support.CouchUtils;
import org.springframework.http.HttpEntity; import org.springframework.http.*;
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.util.Assert;
import org.springframework.web.client.HttpClientErrorException; import org.springframework.web.client.*;
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 { 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 String defaultDocumentUrl;
private RestOperations restOperations = new RestTemplate(); private RestOperations restOperations = new RestTemplate();
/** /**
* Constructs an instance of CouchDbDocumentTemplate with a default database * Constructs an instance of CouchDbDocumentTemplate with a default database
* @param defaultDatabaseUrl the default database to connect to *
*/ * @param defaultDatabaseUrl the default database to connect to
public CouchTemplate(String defaultDatabaseUrl) { */
Assert.hasText(defaultDatabaseUrl, "defaultDatabaseUrl must not be empty"); public CouchTemplate(String defaultDatabaseUrl) {
defaultDocumentUrl = CouchUtils.addId(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 public <T> T findOne(URI uri, Class<T> targetClass) {
* @param defaultDatabaseUrl the default database to connect to Assert.state(uri != null, "uri must be set to use this method");
*/ try {
public CouchTemplate(String defaultDatabaseUrl, RestOperations restOperations) { return restOperations.getForObject(uri, targetClass);
this(defaultDatabaseUrl); //TODO check this exception translation and centralize.
Assert.notNull(restOperations, "restOperations must not be null"); } catch (HttpClientErrorException clientError) {
this.restOperations = restOperations; 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) { public void save(String id, Object document) {
Assert.state(uri != null, "uri must be set to use this method"); Assert.notNull(document, "document must not be null for save");
try { HttpEntity<?> httpEntity = createHttpEntity(document);
return restOperations.getForObject(uri, targetClass); try {
//TODO check this exception translation and centralize. ResponseEntity<Map> response = restOperations.exchange(defaultDocumentUrl, HttpMethod.PUT, httpEntity, Map.class, id);
} catch (HttpClientErrorException clientError) { //TODO update the document revision id on the object from the returned value
if (clientError.getStatusCode() == HttpStatus.NOT_FOUND) { //TODO better exception translation
throw new DocumentRetrievalFailureException(uri.getPath()); } catch (RestClientException e) {
} throw new UncategorizedCouchDataAccessException(e);
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(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;
}
} }

View File

@@ -17,20 +17,9 @@ package org.springframework.data.document.couchdb.core.support;
import java.io.IOException; import java.io.IOException;
import java.nio.charset.Charset; import java.nio.charset.Charset;
import java.util.ArrayList; import java.util.*;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.codehaus.jackson.JsonEncoding; import org.codehaus.jackson.*;
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.map.JsonMappingException; import org.codehaus.jackson.map.JsonMappingException;
import org.codehaus.jackson.map.ObjectMapper; import org.codehaus.jackson.map.ObjectMapper;
import org.codehaus.jackson.map.type.TypeFactory; import org.codehaus.jackson.map.type.TypeFactory;
@@ -44,283 +33,283 @@ import org.springframework.http.converter.HttpMessageNotWritableException;
import org.springframework.util.Assert; import org.springframework.util.Assert;
public class CouchDbMappingJacksonHttpMessageConverter extends 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 ROWS_FIELD_NAME = "rows";
private static final String VALUE_FIELD_NAME = "value"; private static final String VALUE_FIELD_NAME = "value";
private static final String INCLUDED_DOC_FIELD_NAME = "doc"; private static final String INCLUDED_DOC_FIELD_NAME = "doc";
private static final String TOTAL_ROWS_FIELD_NAME = "total_rows"; 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}. * Construct a new {@code BindingJacksonHttpMessageConverter}.
*/ */
public CouchDbMappingJacksonHttpMessageConverter() { public CouchDbMappingJacksonHttpMessageConverter() {
super(new MediaType("application", "json", DEFAULT_CHARSET)); super(new MediaType("application", "json", DEFAULT_CHARSET));
} }
/** /**
* Sets the {@code ObjectMapper} for this view. If not set, a default * Sets the {@code ObjectMapper} for this view. If not set, a default
* {@link ObjectMapper#ObjectMapper() ObjectMapper} is used. * {@link ObjectMapper#ObjectMapper() ObjectMapper} is used.
* <p> * <p/>
* Setting a custom-configured {@code ObjectMapper} is one way to take * Setting a custom-configured {@code ObjectMapper} is one way to take
* further control of the JSON serialization process. For example, an * further control of the JSON serialization process. For example, an
* extended {@link org.codehaus.jackson.map.SerializerFactory} can be * extended {@link org.codehaus.jackson.map.SerializerFactory} can be
* configured that provides custom serializers for specific types. The other * configured that provides custom serializers for specific types. The other
* option for refining the serialization process is to use Jackson's * option for refining the serialization process is to use Jackson's
* provided annotations on the types to be serialized, in which case a * provided annotations on the types to be serialized, in which case a
* custom-configured ObjectMapper is unnecessary. * custom-configured ObjectMapper is unnecessary.
*/ */
public void setObjectMapper(ObjectMapper objectMapper) { public void setObjectMapper(ObjectMapper objectMapper) {
Assert.notNull(objectMapper, "'objectMapper' must not be null"); Assert.notNull(objectMapper, "'objectMapper' must not be null");
this.objectMapper = objectMapper; this.objectMapper = objectMapper;
} }
/** /**
* Indicates whether the JSON output by this view should be prefixed with * Indicates whether the JSON output by this view should be prefixed with
* "{} &&". Default is false. * "{} &&". Default is false.
* <p> * <p/>
* Prefixing the JSON string in this manner is used to help prevent JSON * Prefixing the JSON string in this manner is used to help prevent JSON
* Hijacking. The prefix renders the string syntactically invalid as a * Hijacking. The prefix renders the string syntactically invalid as a
* script so that it cannot be hijacked. This prefix does not affect the * 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, * evaluation of JSON, but if JSON validation is performed on the string,
* the prefix would need to be ignored. * the prefix would need to be ignored.
*/ */
public void setPrefixJson(boolean prefixJson) { public void setPrefixJson(boolean prefixJson) {
this.prefixJson = prefixJson; this.prefixJson = prefixJson;
} }
@Override @Override
public boolean canRead(Class<?> clazz, MediaType mediaType) { public boolean canRead(Class<?> clazz, MediaType mediaType) {
JavaType javaType = getJavaType(clazz); JavaType javaType = getJavaType(clazz);
return this.objectMapper.canDeserialize(javaType) && canRead(mediaType); return this.objectMapper.canDeserialize(javaType) && canRead(mediaType);
} }
/** /**
* Returns the Jackson {@link JavaType} for the specific class. * Returns the Jackson {@link JavaType} for the specific class.
* * <p/>
* <p> * <p/>
* Default implementation returns * Default implementation returns
* {@link TypeFactory#type(java.lang.reflect.Type)}, but this can be * {@link TypeFactory#type(java.lang.reflect.Type)}, but this can be
* overridden in subclasses, to allow for custom generic collection * overridden in subclasses, to allow for custom generic collection
* handling. For instance: * handling. For instance:
* * <p/>
* <pre class="code"> * <pre class="code">
* protected JavaType getJavaType(Class&lt;?&gt; clazz) { * protected JavaType getJavaType(Class&lt;?&gt; clazz) {
* if (List.class.isAssignableFrom(clazz)) { * if (List.class.isAssignableFrom(clazz)) {
* return TypeFactory.collectionType(ArrayList.class, MyBean.class); * return TypeFactory.collectionType(ArrayList.class, MyBean.class);
* } else { * } else {
* return super.getJavaType(clazz); * return super.getJavaType(clazz);
* } * }
* } * }
* </pre> * </pre>
* *
* @param clazz * @param clazz the class to return the java type for
* the class to return the java type for * @return the java type
* @return the java type */
*/ protected JavaType getJavaType(Class<?> clazz) {
protected JavaType getJavaType(Class<?> clazz) { return TypeFactory.type(clazz);
return TypeFactory.type(clazz); }
}
@Override @Override
public boolean canWrite(Class<?> clazz, MediaType mediaType) { public boolean canWrite(Class<?> clazz, MediaType mediaType) {
return this.objectMapper.canSerialize(clazz) && canWrite(mediaType); return this.objectMapper.canSerialize(clazz) && canWrite(mediaType);
} }
@Override @Override
protected boolean supports(Class<?> clazz) { protected boolean supports(Class<?> clazz) {
// should not be called, since we override canRead/Write instead // should not be called, since we override canRead/Write instead
throw new UnsupportedOperationException(); throw new UnsupportedOperationException();
} }
@Override @Override
protected Object readInternal(Class<?> clazz, HttpInputMessage inputMessage) protected Object readInternal(Class<?> clazz, HttpInputMessage inputMessage)
throws IOException, HttpMessageNotReadableException { throws IOException, HttpMessageNotReadableException {
JavaType javaType = getJavaType(clazz); JavaType javaType = getJavaType(clazz);
try { try {
return success(clazz, inputMessage); return success(clazz, inputMessage);
// return this.objectMapper.readValue(inputMessage.getBody(), // return this.objectMapper.readValue(inputMessage.getBody(),
// javaType); // javaType);
} catch (Exception ex) { } catch (Exception ex) {
throw new HttpMessageNotReadableException("Could not read JSON: " throw new HttpMessageNotReadableException("Could not read JSON: "
+ ex.getMessage(), ex); + ex.getMessage(), ex);
} }
} }
private Object success(Class<?> clazz, HttpInputMessage inputMessage) private Object success(Class<?> clazz, HttpInputMessage inputMessage)
throws JsonParseException, IOException { 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);
List result; //Note, parsing code used from ektorp project
if (fields.containsKey(TOTAL_ROWS_FIELD_NAME)) { JsonParser jp = objectMapper.getJsonFactory().createJsonParser(
int totalRows = fields.get(TOTAL_ROWS_FIELD_NAME); inputMessage.getBody());
if (totalRows == 0) { if (jp.nextToken() != JsonToken.START_OBJECT) {
return Collections.emptyList(); throw new RuntimeException("Expected data to start with an Object");
} }
result = new ArrayList(totalRows); Map<String, Integer> fields = readHeaderFields(jp);
} else {
result = new ArrayList();
}
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); ParseState state = new ParseState();
if (first == null) {
return Collections.emptyList();
} else {
result.add(first);
}
while (jp.getCurrentToken() != null) { Object first = parseFirstRow(jp, state, clazz);
skipToField(jp, state.docFieldName, state); if (first == null) {
if (atEndOfRows(jp)) { return Collections.emptyList();
return result; } else {
} result.add(first);
result.add(jp.readValueAs(clazz)); }
endRow(jp, state);
}
return result;
}
private Object parseFirstRow(JsonParser jp, ParseState state, Class clazz) while (jp.getCurrentToken() != null) {
throws JsonParseException, IOException, JsonProcessingException, skipToField(jp, state.docFieldName, state);
JsonMappingException { if (atEndOfRows(jp)) {
skipToField(jp, VALUE_FIELD_NAME, state); return result;
JsonNode value = null; }
if (atObjectStart(jp)) { result.add(jp.readValueAs(clazz));
value = jp.readValueAsTree(); endRow(jp, state);
jp.nextToken(); }
if (isEndOfRow(jp)) { return result;
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 boolean isEndOfRow(JsonParser jp) { private Object parseFirstRow(JsonParser jp, ParseState state, Class clazz)
return jp.getCurrentToken() == JsonToken.END_OBJECT; throws JsonParseException, IOException, JsonProcessingException,
} JsonMappingException {
skipToField(jp, VALUE_FIELD_NAME, state);
private void endRow(JsonParser jp, ParseState state) throws IOException, JsonParseException { JsonNode value = null;
state.inRow = false; if (atObjectStart(jp)) {
jp.nextToken(); value = jp.readValueAsTree();
} jp.nextToken();
if (isEndOfRow(jp)) {
private boolean atObjectStart(JsonParser jp) { state.docFieldName = VALUE_FIELD_NAME;
return jp.getCurrentToken() == JsonToken.START_OBJECT; Object doc = objectMapper.readValue(value, clazz);
} endRow(jp, state);
return doc;
private boolean atEndOfRows(JsonParser jp) { }
return jp.getCurrentToken() != JsonToken.START_OBJECT; }
} skipToField(jp, INCLUDED_DOC_FIELD_NAME, state);
private void skipToField(JsonParser jp, String fieldName, ParseState state) throws JsonParseException, IOException { if (atObjectStart(jp)) {
String lastFieldName = null; state.docFieldName = INCLUDED_DOC_FIELD_NAME;
while (jp.getCurrentToken() != null) { Object doc = jp.readValueAs(clazz);
switch (jp.getCurrentToken()) { endRow(jp, state);
case FIELD_NAME: return doc;
lastFieldName = jp.getCurrentName(); }
jp.nextToken(); return null;
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) private boolean isEndOfRow(JsonParser jp) {
throws JsonParseException, IOException { return jp.getCurrentToken() == JsonToken.END_OBJECT;
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 private void endRow(JsonParser jp, ParseState state) throws IOException, JsonParseException {
protected void writeInternal(Object o, HttpOutputMessage outputMessage) state.inRow = false;
throws IOException, HttpMessageNotWritableException { jp.nextToken();
}
JsonEncoding encoding = getEncoding(outputMessage.getHeaders() private boolean atObjectStart(JsonParser jp) {
.getContentType()); return jp.getCurrentToken() == JsonToken.START_OBJECT;
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) { private boolean atEndOfRows(JsonParser jp) {
if (contentType != null && contentType.getCharSet() != null) { return jp.getCurrentToken() != JsonToken.START_OBJECT;
Charset charset = contentType.getCharSet(); }
for (JsonEncoding encoding : JsonEncoding.values()) {
if (charset.name().equals(encoding.getJavaName())) {
return encoding;
}
}
}
return JsonEncoding.UTF8;
}
private static class ParseState { private void skipToField(JsonParser jp, String fieldName, ParseState state) throws JsonParseException, IOException {
boolean inRow; String lastFieldName = null;
String docFieldName = ""; 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 = "";
}
} }

View File

@@ -15,32 +15,27 @@
*/ */
package org.springframework.data.document.couchdb.monitor; 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; import org.springframework.web.client.RestTemplate;
/** /**
* Base class to encapsulate common configuration settings when connecting to a CouchDB database * Base class to encapsulate common configuration settings when connecting to a CouchDB database
*
* @author Mark Pollack
* *
* @author Mark Pollack
*/ */
public abstract class AbstractMonitor { 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;
}
} }

View File

@@ -24,40 +24,39 @@ import org.springframework.jmx.export.annotation.ManagedResource;
import org.springframework.web.client.RestTemplate; import org.springframework.web.client.RestTemplate;
/** /**
* Expose basic server information via JMX * Expose basic server information via JMX
*
* @author Mark Pollack
* *
* @author Mark Pollack
*/ */
@ManagedResource(description="Server Information") @ManagedResource(description = "Server Information")
public class ServerInfo extends AbstractMonitor { 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 ServerInfo(String databaseUrl) {
public String getVersion() { this.databaseUrl = databaseUrl;
return (String) getRoot().get("version"); this.restTemplate = new RestTemplate();
} }
@ManagedOperation(description="Message of the day")
public String getMotd() { @ManagedOperation(description = "Server host name")
return (String) getRoot().get("greeting"); public String getHostName() throws UnknownHostException {
} return InetAddress.getLocalHost().getHostName();
}
public Map getRoot() {
Map map = restTemplate.getForObject(getDatabaseUrl(),Map.class);
return map; @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;
}
} }

View File

@@ -17,11 +17,10 @@
package org.springframework.data.document.couchdb.support; package org.springframework.data.document.couchdb.support;
import org.springframework.dao.DataAccessException; import org.springframework.dao.DataAccessException;
import org.springframework.data.document.UncategorizedDocumentStoreException;
/** /**
* Helper class featuring helper methods for internal CouchDB classes. * Helper class featuring helper methods for internal CouchDB classes.
* * <p/>
* <p>Mainly intended for internal use within the framework. * <p>Mainly intended for internal use within the framework.
* *
* @author Thomas Risberg * @author Thomas Risberg
@@ -30,49 +29,53 @@ import org.springframework.data.document.UncategorizedDocumentStoreException;
*/ */
public abstract class CouchUtils { public abstract class CouchUtils {
/** /**
* Convert the given runtime exception to an appropriate exception from the * Convert the given runtime exception to an appropriate exception from the
* <code>org.springframework.dao</code> hierarchy. * <code>org.springframework.dao</code> hierarchy.
* Return null if no translation is appropriate: any other exception may * Return null if no translation is appropriate: any other exception may
* have resulted from user code, and should not be translated. * have resulted from user code, and should not be translated.
* @param ex runtime exception that occurred *
* @return the corresponding DataAccessException instance, * @param ex runtime exception that occurred
* or <code>null</code> if the exception should not be translated * @return the corresponding DataAccessException instance,
*/ * or <code>null</code> if the exception should not be translated
public static DataAccessException translateCouchExceptionIfPossible(RuntimeException ex) { */
public static DataAccessException translateCouchExceptionIfPossible(RuntimeException ex) {
return null; return null;
} }
/** /**
* Adds an id variable to a URL * Adds an id variable to a URL
* @param url the URL to modify *
* @return the modified URL * @param url the URL to modify
*/ * @return the modified URL
public static String addId(String url) { */
return ensureTrailingSlash(url) + "{id}"; public static String addId(String url) {
} return ensureTrailingSlash(url) + "{id}";
}
/**
* Adds a 'changes since' variable to a URL /**
* @param url * Adds a 'changes since' variable to a URL
* @return *
*/ * @param url
public static String addChangesSince(String url) { * @return
return ensureTrailingSlash(url) + "_changes?since={seq}"; */
} 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 * Ensures that a URL ends with a slash.
*/ *
public static String ensureTrailingSlash(String url) { * @param url the URL to modify
if (!url.endsWith("/")) { * @return the modified URL
url += "/"; */
} public static String ensureTrailingSlash(String url) {
return url; if (!url.endsWith("/")) {
url += "/";
} }
return url;
}
} }

View File

@@ -1,33 +1,33 @@
<?xml version="1.0" encoding="UTF-8" ?> <?xml version="1.0" encoding="UTF-8" ?>
<xsd:schema xmlns="http://www.springframework.org/schema/data/couch" <xsd:schema xmlns="http://www.springframework.org/schema/data/couch"
xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:tool="http://www.springframework.org/schema/tool" xmlns:tool="http://www.springframework.org/schema/tool"
xmlns:context="http://www.springframework.org/schema/context" xmlns:context="http://www.springframework.org/schema/context"
xmlns:repository="http://www.springframework.org/schema/data/repository" xmlns:repository="http://www.springframework.org/schema/data/repository"
targetNamespace="http://www.springframework.org/schema/data/couch" targetNamespace="http://www.springframework.org/schema/data/couch"
elementFormDefault="qualified" attributeFormDefault="unqualified"> elementFormDefault="qualified" attributeFormDefault="unqualified">
<xsd:import namespace="http://www.springframework.org/schema/tool" /> <xsd:import namespace="http://www.springframework.org/schema/tool"/>
<xsd:import namespace="http://www.springframework.org/schema/context" <xsd:import namespace="http://www.springframework.org/schema/context"
schemaLocation="http://www.springframework.org/schema/context/spring-context.xsd" /> schemaLocation="http://www.springframework.org/schema/context/spring-context.xsd"/>
<xsd:import namespace="http://www.springframework.org/schema/data/repository" <xsd:import namespace="http://www.springframework.org/schema/data/repository"
schemaLocation="http://www.springframework.org/schema/data/repository/spring-repository.xsd" /> schemaLocation="http://www.springframework.org/schema/data/repository/spring-repository.xsd"/>
<xsd:element name="jmx"> <xsd:element name="jmx">
<xsd:annotation> <xsd:annotation>
<xsd:documentation><![CDATA[ <xsd:documentation><![CDATA[
Defines a JMX Model MBeans for monitoring a CouchDB server'. Defines a JMX Model MBeans for monitoring a CouchDB server'.
]]></xsd:documentation> ]]></xsd:documentation>
</xsd:annotation> </xsd:annotation>
<xsd:complexType> <xsd:complexType>
<xsd:attribute name="database-url" type="xsd:string" use="optional"> <xsd:attribute name="database-url" type="xsd:string" use="optional">
<xsd:annotation> <xsd:annotation>
<xsd:documentation><![CDATA[ <xsd:documentation><![CDATA[
The database URL of the CouchDB]]></xsd:documentation> The database URL of the CouchDB]]></xsd:documentation>
</xsd:annotation> </xsd:annotation>
</xsd:attribute> </xsd:attribute>
</xsd:complexType> </xsd:complexType>
</xsd:element> </xsd:element>
</xsd:schema> </xsd:schema>

View File

@@ -16,62 +16,62 @@
package org.springframework.data.document.couchdb; package org.springframework.data.document.couchdb;
import org.codehaus.jackson.annotate.JsonIgnoreProperties;
import java.util.Date; import java.util.Date;
import org.codehaus.jackson.annotate.JsonIgnoreProperties;
/** /**
* @author Tareq Abedrabbo (tareq.abedrabbo@opencredo.com) * @author Tareq Abedrabbo (tareq.abedrabbo@opencredo.com)
* @since 13/01/2011 * @since 13/01/2011
*/ */
@JsonIgnoreProperties(ignoreUnknown=true) @JsonIgnoreProperties(ignoreUnknown = true)
public class DummyDocument { 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) { public DummyDocument(String message) {
this.message = message; this.message = message;
} }
public String getMessage() { public String getMessage() {
return message; return message;
} }
public void setMessage(String message) { public void setMessage(String message) {
this.message = message; this.message = message;
} }
public String getTimestamp() { public String getTimestamp() {
return timestamp; return timestamp;
} }
@Override @Override
public boolean equals(Object o) { public boolean equals(Object o) {
if (this == o) return true; if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false; 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 @Override
public int hashCode() { public int hashCode() {
return message != null ? message.hashCode() : 0; return message != null ? message.hashCode() : 0;
} }
@Override @Override
public String toString() { public String toString() {
return "DummyDocument{" + return "DummyDocument{" +
"message='" + message + '\'' + "message='" + message + '\'' +
", timestamp=" + timestamp + ", timestamp=" + timestamp +
'}'; '}';
} }
} }

View File

@@ -24,28 +24,29 @@ import org.springframework.http.HttpEntity;
/** /**
* Matches the content of the body of an HttpEntity. * Matches the content of the body of an HttpEntity.
*
* @author Tareq Abedrabbo * @author Tareq Abedrabbo
* @since 31/01/2011 * @since 31/01/2011
*/ */
public class IsBodyEqual extends TypeSafeMatcher<HttpEntity> { public class IsBodyEqual extends TypeSafeMatcher<HttpEntity> {
private Object object; private Object object;
public IsBodyEqual(Object object) { public IsBodyEqual(Object object) {
this.object = object; this.object = object;
} }
@Override @Override
public boolean matchesSafely(HttpEntity httpEntity) { public boolean matchesSafely(HttpEntity httpEntity) {
return httpEntity.getBody().equals(object); return httpEntity.getBody().equals(object);
} }
public void describeTo(Description description) { public void describeTo(Description description) {
description.appendText("body equals ").appendValue(object); description.appendText("body equals ").appendValue(object);
} }
@Factory @Factory
public static Matcher<HttpEntity> bodyEqual(Object object) { public static Matcher<HttpEntity> bodyEqual(Object object) {
return new IsBodyEqual(object); return new IsBodyEqual(object);
} }
} }

View File

@@ -18,22 +18,21 @@ package org.springframework.data.document.couchdb.admin;
import java.util.List; import java.util.List;
import junit.framework.Assert; import junit.framework.Assert;
import org.junit.Ignore; import org.junit.Ignore;
import org.junit.Test; import org.junit.Test;
import org.springframework.data.document.couchdb.core.CouchConstants; import org.springframework.data.document.couchdb.core.CouchConstants;
public class CouchAdminIntegrationTests { public class CouchAdminIntegrationTests {
@Test @Test
@Ignore("until CI has couch server running") @Ignore("until CI has couch server running")
public void dbLifecycle() { public void dbLifecycle() {
CouchAdmin admin = new CouchAdmin(CouchConstants.COUCHDB_URL); CouchAdmin admin = new CouchAdmin(CouchConstants.COUCHDB_URL);
admin.deleteDatabase("foo"); admin.deleteDatabase("foo");
List<String> dbs = admin.listDatabases(); List<String> dbs = admin.listDatabases();
admin.createDatabase("foo"); admin.createDatabase("foo");
List<String> newDbs = admin.listDatabases(); List<String> newDbs = admin.listDatabases();
Assert.assertEquals(dbs.size()+1, newDbs.size()); Assert.assertEquals(dbs.size() + 1, newDbs.size());
} }
} }

View File

@@ -16,28 +16,22 @@
package org.springframework.data.document.couchdb.core; package org.springframework.data.document.couchdb.core;
import org.apache.commons.logging.Log; import static org.junit.Assume.assumeNoException;
import org.apache.commons.logging.LogFactory; import static org.junit.Assume.assumeTrue;
import org.junit.Before; import static org.springframework.http.HttpStatus.OK;
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 java.io.IOException; import java.io.IOException;
import java.util.UUID; import java.util.UUID;
import static org.junit.Assume.assumeNoException; import org.apache.commons.logging.Log;
import static org.junit.Assume.assumeTrue; import org.apache.commons.logging.LogFactory;
import static org.springframework.http.HttpStatus.OK; 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, * 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 { 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. * This methods ensures that the database is running. Otherwise, the test is ignored.
*/ */
@BeforeClass @BeforeClass
public static void assumeDatabaseIsUpAndRunning() { public static void assumeDatabaseIsUpAndRunning() {
try { try {
ResponseEntity<String> responseEntity = restTemplate.getForEntity(CouchConstants.COUCHDB_URL, String.class); ResponseEntity<String> responseEntity = restTemplate.getForEntity(CouchConstants.COUCHDB_URL, String.class);
assumeTrue(responseEntity.getStatusCode().equals(OK)); assumeTrue(responseEntity.getStatusCode().equals(OK));
log.debug("CouchDB is running on " + CouchConstants.COUCHDB_URL + log.debug("CouchDB is running on " + CouchConstants.COUCHDB_URL +
" with status " + responseEntity.getStatusCode()); " with status " + responseEntity.getStatusCode());
} catch (RestClientException e) { } catch (RestClientException e) {
log.debug("CouchDB is not running on " + CouchConstants.COUCHDB_URL); log.debug("CouchDB is not running on " + CouchConstants.COUCHDB_URL);
assumeNoException(e); assumeNoException(e);
}
} }
}
@Before @Before
public void setUpTestDatabase() throws Exception { public void setUpTestDatabase() throws Exception {
RestTemplate template = new RestTemplate(); RestTemplate template = new RestTemplate();
template.setErrorHandler(new DefaultResponseErrorHandler(){ template.setErrorHandler(new DefaultResponseErrorHandler() {
@Override @Override
public void handleError(ClientHttpResponse response) throws IOException { public void handleError(ClientHttpResponse response) throws IOException {
// do nothing, error status will be handled in the switch statement // do nothing, error status will be handled in the switch statement
} }
}); });
ResponseEntity<String> response = template.getForEntity(CouchConstants.TEST_DATABASE_URL, String.class); ResponseEntity<String> response = template.getForEntity(CouchConstants.TEST_DATABASE_URL, String.class);
HttpStatus statusCode = response.getStatusCode(); HttpStatus statusCode = response.getStatusCode();
switch (statusCode) { switch (statusCode) {
case NOT_FOUND: case NOT_FOUND:
createNewTestDatabase(); createNewTestDatabase();
break; break;
case OK: case OK:
deleteExisitingTestDatabase(); deleteExisitingTestDatabase();
createNewTestDatabase(); createNewTestDatabase();
break; break;
default: default:
throw new IllegalStateException("Unsupported http status [" + statusCode + "]"); throw new IllegalStateException("Unsupported http status [" + statusCode + "]");
}
} }
}
private void deleteExisitingTestDatabase() { private void deleteExisitingTestDatabase() {
restTemplate.delete(CouchConstants.TEST_DATABASE_URL); restTemplate.delete(CouchConstants.TEST_DATABASE_URL);
} }
private void createNewTestDatabase() { private void createNewTestDatabase() {
restTemplate.put(CouchConstants.TEST_DATABASE_URL, null); restTemplate.put(CouchConstants.TEST_DATABASE_URL, null);
} }
/** /**
* Reads a CouchDB document and converts it to the expected type. * Reads a CouchDB document and converts it to the expected type.
*/ */
protected <T> T getDocument(String id, Class<T> expectedType) { protected <T> T getDocument(String id, Class<T> expectedType) {
String url = CouchConstants.TEST_DATABASE_URL + "{id}"; String url = CouchConstants.TEST_DATABASE_URL + "{id}";
return restTemplate.getForObject(url, expectedType, id); return restTemplate.getForObject(url, expectedType, id);
} }
/** /**
* Writes a CouchDB document * Writes a CouchDB document
*/ */
protected String putDocument(Object document) { protected String putDocument(Object document) {
HttpHeaders headers = new HttpHeaders(); HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON); headers.setContentType(MediaType.APPLICATION_JSON);
HttpEntity request = new HttpEntity(document, headers); HttpEntity request = new HttpEntity(document, headers);
String id = UUID.randomUUID().toString(); String id = UUID.randomUUID().toString();
restTemplate.put(CouchConstants.TEST_DATABASE_URL + "{id}", request, id); restTemplate.put(CouchConstants.TEST_DATABASE_URL + "{id}", request, id);
return id; return id;
} }
} }

View File

@@ -17,11 +17,11 @@ package org.springframework.data.document.couchdb.core;
public abstract class CouchConstants { public abstract class CouchConstants {
public static final String COUCHDB_URL = "http://127.0.0.1:5984/"; 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 TEST_DATABASE_URL = COUCHDB_URL + "si_couchdb_test/";
public CouchConstants() { public CouchConstants() {
// TODO Auto-generated constructor stub // TODO Auto-generated constructor stub
} }
} }

View File

@@ -19,22 +19,21 @@ package org.springframework.data.document.couchdb.core;
import java.util.UUID; import java.util.UUID;
import junit.framework.Assert; import junit.framework.Assert;
import org.junit.Ignore; import org.junit.Ignore;
import org.junit.Test; import org.junit.Test;
import org.springframework.data.document.couchdb.DummyDocument; import org.springframework.data.document.couchdb.DummyDocument;
public class CouchTemplateIntegrationTests extends AbstractCouchTemplateIntegrationTests { public class CouchTemplateIntegrationTests extends AbstractCouchTemplateIntegrationTests {
@Test @Test
@Ignore("until CI has couch server running") @Ignore("until CI has couch server running")
public void saveAndFindTest() { public void saveAndFindTest() {
CouchTemplate template = new CouchTemplate(CouchConstants.TEST_DATABASE_URL); CouchTemplate template = new CouchTemplate(CouchConstants.TEST_DATABASE_URL);
DummyDocument document = new DummyDocument("hello"); DummyDocument document = new DummyDocument("hello");
String id = UUID.randomUUID().toString(); String id = UUID.randomUUID().toString();
template.save(id, document); template.save(id, document);
DummyDocument foundDocument = template.findOne(id, DummyDocument.class); DummyDocument foundDocument = template.findOne(id, DummyDocument.class);
Assert.assertEquals(document.getMessage(), foundDocument.getMessage()); Assert.assertEquals(document.getMessage(), foundDocument.getMessage());
} }
} }

View File

@@ -20,13 +20,11 @@ import org.junit.Test;
/** /**
* Unit tests for CouchTemplate with mocks * Unit tests for CouchTemplate with mocks
*
*
*/ */
public class CouchTemplateTests { public class CouchTemplateTests {
@Test @Test
public void foo() { public void foo() {
} }
} }

View File

@@ -20,17 +20,17 @@ import org.springframework.context.support.ClassPathXmlApplicationContext;
/** /**
* Server application to test JMX functionality. * Server application to test JMX functionality.
* *
* @author Mark Pollack * @author Mark Pollack
*/ */
public class JmxServer { public class JmxServer {
public static void main(String[] args) { public static void main(String[] args) {
new JmxServer().run(); new JmxServer().run();
} }
public void run() { public void run() {
new ClassPathXmlApplicationContext(new String[] {"server-jmx.xml"} ); new ClassPathXmlApplicationContext(new String[]{"server-jmx.xml"});
} }
} }

View File

@@ -1,25 +1,24 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" <beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context" xmlns:context="http://www.springframework.org/schema/context"
xmlns:p="http://www.springframework.org/schema/p" xmlns:p="http://www.springframework.org/schema/p"
xmlns:couch="http://www.springframework.org/schema/data/couch" 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 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/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"> 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> </beans>

View File

@@ -1,12 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="src" output="target/classes" path="src/main/java"/>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/J2SE-1.5"/>
<classpathentry kind="con" path="org.maven.ide.eclipse.MAVEN2_CLASSPATH_CONTAINER">
<attributes>
<attribute name="org.eclipse.jst.component.nondependency" value=""/>
</attributes>
</classpathentry>
<classpathentry kind="con" path="org.eclipse.jst.j2ee.internal.module.container"/>
<classpathentry kind="output" path="target/classes"/>
</classpath>

View File

@@ -1,36 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>spring-data-document-core</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.wst.common.project.facet.core.builder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.maven.ide.eclipse.maven2Builder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.wst.validation.validationbuilder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.jem.workbench.JavaEMFNature</nature>
<nature>org.eclipse.wst.common.modulecore.ModuleCoreNature</nature>
<nature>org.eclipse.jdt.core.javanature</nature>
<nature>org.maven.ide.eclipse.maven2Nature</nature>
<nature>org.eclipse.wst.common.project.facet.core.nature</nature>
</natures>
</projectDescription>

View File

@@ -1,9 +0,0 @@
#Wed Mar 09 13:51:17 EST 2011
eclipse.preferences.version=1
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
org.eclipse.jdt.core.compiler.compliance=1.6
org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
org.eclipse.jdt.core.compiler.source=1.6

View File

@@ -1,6 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project-modules id="moduleCoreId" project-version="1.5.0">
<wb-module deploy-name="spring-datastore-document-core">
<wb-resource deploy-path="/" source-path="/src/main/java"/>
</wb-module>
</project-modules>

View File

@@ -1,5 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<faceted-project>
<installed facet="jst.utility" version="1.0"/>
<installed facet="java" version="1.6"/>
</faceted-project>

View File

@@ -1,9 +0,0 @@
#Wed Oct 06 14:49:46 EDT 2010
activeProfiles=
eclipse.preferences.version=1
fullBuildGoals=process-test-resources
includeModules=false
resolveWorkspaceProjects=true
resourceFilterGoals=process-resources resources\:testResources
skipCompilerPlugin=true
version=1

View File

@@ -18,16 +18,15 @@ package org.springframework.data.document;
public abstract class AbstractDocumentStoreTemplate<C> { public abstract class AbstractDocumentStoreTemplate<C> {
public abstract C getConnection();
public <T> T execute(DocumentStoreConnectionCallback<C, T> action) { public abstract C getConnection();
try {
return action.doInConnection(getConnection()); public <T> T execute(DocumentStoreConnectionCallback<C, T> action) {
} try {
catch (Exception e) { return action.doInConnection(getConnection());
throw new UncategorizedDocumentStoreException("Failure executing using datastore connection", e); } catch (Exception e) {
} throw new UncategorizedDocumentStoreException("Failure executing using datastore connection", e);
} }
}
} }

View File

@@ -23,7 +23,7 @@ package org.springframework.data.document;
* @since 1.0 * @since 1.0
*/ */
public interface DocumentMapper<D, T> { public interface DocumentMapper<D, T> {
T mapDocument(D document); T mapDocument(D document);
} }

View File

@@ -18,5 +18,5 @@ package org.springframework.data.document;
public interface DocumentStoreConnectionCallback<C, T> { public interface DocumentStoreConnectionCallback<C, T> {
T doInConnection(C con) throws Exception; T doInConnection(C con) throws Exception;
} }

View File

@@ -20,12 +20,12 @@ import org.springframework.dao.InvalidDataAccessApiUsageException;
public class InvalidDocumentStoreApiUsageException extends InvalidDataAccessApiUsageException { public class InvalidDocumentStoreApiUsageException extends InvalidDataAccessApiUsageException {
public InvalidDocumentStoreApiUsageException(String msg) { public InvalidDocumentStoreApiUsageException(String msg) {
super(msg); super(msg);
} }
public InvalidDocumentStoreApiUsageException(String msg, Throwable cause) { public InvalidDocumentStoreApiUsageException(String msg, Throwable cause) {
super(msg, cause); super(msg, cause);
} }
} }

View File

@@ -20,8 +20,8 @@ import org.springframework.dao.UncategorizedDataAccessException;
public class UncategorizedDocumentStoreException extends UncategorizedDataAccessException { public class UncategorizedDocumentStoreException extends UncategorizedDataAccessException {
public UncategorizedDocumentStoreException(String msg, Throwable cause) { public UncategorizedDocumentStoreException(String msg, Throwable cause) {
super(msg, cause); super(msg, cause);
} }
} }

View File

@@ -1,45 +1,43 @@
package org.springframework.data.document.analytics; package org.springframework.data.document.analytics;
import java.util.Date;
import java.util.Map; import java.util.Map;
public class ControllerCounter { public class ControllerCounter {
public String getName() {
return name;
}
public void setName(String name) { public String getName() {
this.name = name; return name;
} }
public double getCount() { public void setName(String name) {
return count; this.name = name;
} }
public void setCount(double count) { public double getCount() {
this.count = count; return count;
} }
public Map<String, Double> getMethods() { public void setCount(double count) {
return methods; this.count = count;
} }
public void setMethods(Map<String, Double> methods) { public Map<String, Double> getMethods() {
this.methods = methods; return methods;
} }
private String name;
public void setMethods(Map<String, Double> methods) {
private double count; this.methods = methods;
}
private Map<String, Double> methods;
private String name;
@Override
public String toString() { private double count;
return "ControllerCounter [name=" + name + ", count=" + count
+ ", methods=" + methods + "]"; private Map<String, Double> methods;
}
@Override
public String toString() {
return "ControllerCounter [name=" + name + ", count=" + count
+ ", methods=" + methods + "]";
}
} }

View File

@@ -4,81 +4,80 @@ import java.util.Date;
public class MvcEvent { public class MvcEvent {
private String controller; private String controller;
private String action;
private Parameters parameters;
private Date date;
private String requestUri;
private String requestAddress;
private String remoteUser;
private String view;
public String getController() { private String action;
return controller;
}
public void setController(String controller) { private Parameters parameters;
this.controller = controller;
}
public String getAction() { private Date date;
return action;
}
public void setAction(String action) { private String requestUri;
this.action = action;
}
public Parameters getParameters() { private String requestAddress;
return parameters;
}
public void setParameters(Parameters parameters) { private String remoteUser;
this.parameters = parameters;
}
public Date getDate() { private String view;
return date;
}
public void setDate(Date date) { public String getController() {
this.date = date; return controller;
} }
public String getRequestUri() { public void setController(String controller) {
return requestUri; this.controller = controller;
} }
public void setRequestUri(String requestUri) { public String getAction() {
this.requestUri = requestUri; return action;
} }
public String getRequestAddress() { public void setAction(String action) {
return requestAddress; this.action = action;
} }
public void setRequestAddress(String requestAddress) { public Parameters getParameters() {
this.requestAddress = requestAddress; return parameters;
} }
public void setParameters(Parameters parameters) {
this.parameters = parameters;
}
public Date getDate() {
return date;
}
public void setDate(Date date) {
this.date = date;
}
public String getRequestUri() {
return requestUri;
}
public void setRequestUri(String requestUri) {
this.requestUri = requestUri;
}
public String getRequestAddress() {
return requestAddress;
}
public void setRequestAddress(String requestAddress) {
this.requestAddress = requestAddress;
}
public String getRemoteUser() {
return remoteUser;
}
public void setRemoteUser(String remoteUser) {
this.remoteUser = remoteUser;
}
//TODO
//Map sessionAttributes
public String getRemoteUser() {
return remoteUser;
}
public void setRemoteUser(String remoteUser) {
this.remoteUser = remoteUser;
}
//TODO
//Map sessionAttributes
} }

View File

@@ -2,34 +2,34 @@ package org.springframework.data.document.analytics;
public class Parameters { public class Parameters {
private String p1; private String p1;
private String p2;
private String p3;
public String getP1() { private String p2;
return p1;
}
public void setP1(String p1) { private String p3;
this.p1 = p1;
}
public String getP2() { public String getP1() {
return p2; return p1;
} }
public void setP2(String p2) { public void setP1(String p1) {
this.p2 = p2; this.p1 = p1;
} }
public String getP3() { public String getP2() {
return p3; return p2;
} }
public void setP2(String p2) {
this.p2 = p2;
}
public String getP3() {
return p3;
}
public void setP3(String p3) {
this.p3 = p3;
}
public void setP3(String p3) {
this.p3 = p3;
}
} }

View File

@@ -22,40 +22,37 @@ import org.springframework.web.servlet.ModelAndView;
public class ActionExecutedContext extends ActionExecutingContext { public class ActionExecutedContext extends ActionExecutingContext {
private ModelAndView modelAndView; private ModelAndView modelAndView;
private Exception exception;
public ActionExecutedContext(ActionExecutingContext actionExecutingContext, ModelAndView modelAndView, Exception exception) {
super(actionExecutingContext.getServletWebRequest(), actionExecutingContext.getHandler(),
actionExecutingContext.getHandlerMethod(), actionExecutingContext.getHandlerParameters(),
actionExecutingContext.getImplicitModel());
this.modelAndView = modelAndView;
this.exception = exception;
}
@Override private Exception exception;
public String toString() {
return "ActionExecutedContext [handler=" + getHandler() public ActionExecutedContext(ActionExecutingContext actionExecutingContext, ModelAndView modelAndView, Exception exception) {
+ ", servletWebRequest=" + getServletWebRequest() super(actionExecutingContext.getServletWebRequest(), actionExecutingContext.getHandler(),
+ ", implicitModel=" + getImplicitModel() + ", handlerMethod=" actionExecutingContext.getHandlerMethod(), actionExecutingContext.getHandlerParameters(),
+ getHandlerMethod() + ", handlerParameters=" actionExecutingContext.getImplicitModel());
+ Arrays.toString(getHandlerParameters()) + ",modelAndView=" + modelAndView this.modelAndView = modelAndView;
+ ", exception=" + exception + "]"; this.exception = exception;
} }
@Override
public String toString() {
return "ActionExecutedContext [handler=" + getHandler()
+ ", servletWebRequest=" + getServletWebRequest()
+ ", implicitModel=" + getImplicitModel() + ", handlerMethod="
+ getHandlerMethod() + ", handlerParameters="
+ Arrays.toString(getHandlerParameters()) + ",modelAndView=" + modelAndView
+ ", exception=" + exception + "]";
}
public ModelAndView getModelAndView() { public ModelAndView getModelAndView() {
return modelAndView; return modelAndView;
} }
public Exception getException() { public Exception getException() {
return exception; return exception;
} }
} }

View File

@@ -17,7 +17,6 @@ package org.springframework.data.document.web.servlet;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.util.Arrays; import java.util.Arrays;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
@@ -26,67 +25,65 @@ import org.springframework.web.context.request.ServletWebRequest;
public class ActionExecutingContext { public class ActionExecutingContext {
private Object handler;
private ServletWebRequest servletWebRequest;
private ExtendedModelMap implicitModel;
private Method handlerMethod;
private Object[] handlerParameters;
public ActionExecutingContext(ServletWebRequest servletWebRequest, private Object handler;
Object handler, Method handlerMethod, Object[] handlerParameters,
ExtendedModelMap implicitModel) {
super();
this.servletWebRequest = servletWebRequest;
this.handler = handler;
this.handlerMethod = handlerMethod;
this.handlerParameters = handlerParameters;
this.implicitModel = implicitModel;
}
public HttpServletRequest getHttpServletRequest() { private ServletWebRequest servletWebRequest;
return servletWebRequest.getRequest();
}
public HttpServletResponse getHttpServletResponse() { private ExtendedModelMap implicitModel;
return servletWebRequest.getResponse();
}
public Object getHandler() { private Method handlerMethod;
return handler;
}
public ServletWebRequest getServletWebRequest() { private Object[] handlerParameters;
return servletWebRequest;
}
public ExtendedModelMap getImplicitModel() {
return implicitModel;
}
public Method getHandlerMethod() { public ActionExecutingContext(ServletWebRequest servletWebRequest,
return handlerMethod; Object handler, Method handlerMethod, Object[] handlerParameters,
} ExtendedModelMap implicitModel) {
super();
this.servletWebRequest = servletWebRequest;
this.handler = handler;
this.handlerMethod = handlerMethod;
this.handlerParameters = handlerParameters;
this.implicitModel = implicitModel;
}
public HttpServletRequest getHttpServletRequest() {
return servletWebRequest.getRequest();
}
public HttpServletResponse getHttpServletResponse() {
return servletWebRequest.getResponse();
}
public Object getHandler() {
return handler;
}
public ServletWebRequest getServletWebRequest() {
return servletWebRequest;
}
public ExtendedModelMap getImplicitModel() {
return implicitModel;
}
public Method getHandlerMethod() {
return handlerMethod;
}
public Object[] getHandlerParameters() {
return handlerParameters;
}
@Override
public String toString() {
return "ActionExecutingContext [handler=" + handler
+ ", servletWebRequest=" + servletWebRequest
+ ", implicitModel=" + implicitModel + ", handlerMethod="
+ handlerMethod + ", handlerParameters="
+ Arrays.toString(handlerParameters) + "]";
}
public Object[] getHandlerParameters() {
return handlerParameters;
}
@Override
public String toString() {
return "ActionExecutingContext [handler=" + handler
+ ", servletWebRequest=" + servletWebRequest
+ ", implicitModel=" + implicitModel + ", handlerMethod="
+ handlerMethod + ", handlerParameters="
+ Arrays.toString(handlerParameters) + "]";
}
} }

View File

@@ -17,9 +17,9 @@ package org.springframework.data.document.web.servlet;
public interface ActionInterceptor { public interface ActionInterceptor {
boolean preHandle(ActionExecutingContext actionExecutingContext); boolean preHandle(ActionExecutingContext actionExecutingContext);
void postHandle(ActionExecutedContext actionExecutedContext); void postHandle(ActionExecutedContext actionExecutedContext);
void afterCompletion(ActionExecutedContext actionExecutedContext); void afterCompletion(ActionExecutedContext actionExecutedContext);
} }

View File

@@ -34,110 +34,108 @@ import org.springframework.web.util.WebUtils;
*/ */
abstract class ServletAnnotationMappingUtils { abstract class ServletAnnotationMappingUtils {
/** /**
* Check whether the given request matches the specified request methods. * Check whether the given request matches the specified request methods.
* @param methods the HTTP request methods to check against *
* @param request the current HTTP request to check * @param methods the HTTP request methods to check against
*/ * @param request the current HTTP request to check
public static boolean checkRequestMethod(RequestMethod[] methods, HttpServletRequest request) { */
if (ObjectUtils.isEmpty(methods)) { public static boolean checkRequestMethod(RequestMethod[] methods, HttpServletRequest request) {
return true; if (ObjectUtils.isEmpty(methods)) {
} return true;
for (RequestMethod method : methods) { }
if (method.name().equals(request.getMethod())) { for (RequestMethod method : methods) {
return true; if (method.name().equals(request.getMethod())) {
} return true;
} }
return false; }
} return false;
}
/** /**
* Check whether the given request matches the specified parameter conditions. * Check whether the given request matches the specified parameter conditions.
* @param params the parameter conditions, following *
* {@link org.springframework.web.bind.annotation.RequestMapping#params() RequestMapping.#params()} * @param params the parameter conditions, following
* @param request the current HTTP request to check * {@link org.springframework.web.bind.annotation.RequestMapping#params() RequestMapping.#params()}
*/ * @param request the current HTTP request to check
public static boolean checkParameters(String[] params, HttpServletRequest request) { */
if (!ObjectUtils.isEmpty(params)) { public static boolean checkParameters(String[] params, HttpServletRequest request) {
for (String param : params) { if (!ObjectUtils.isEmpty(params)) {
int separator = param.indexOf('='); for (String param : params) {
if (separator == -1) { int separator = param.indexOf('=');
if (param.startsWith("!")) { if (separator == -1) {
if (WebUtils.hasSubmitParameter(request, param.substring(1))) { if (param.startsWith("!")) {
return false; if (WebUtils.hasSubmitParameter(request, param.substring(1))) {
} return false;
} }
else if (!WebUtils.hasSubmitParameter(request, param)) { } else if (!WebUtils.hasSubmitParameter(request, param)) {
return false; return false;
} }
} } else {
else { boolean negated = separator > 0 && param.charAt(separator - 1) == '!';
boolean negated = separator > 0 && param.charAt(separator - 1) == '!'; String key = !negated ? param.substring(0, separator) : param.substring(0, separator - 1);
String key = !negated ? param.substring(0, separator) : param.substring(0, separator - 1); String value = param.substring(separator + 1);
String value = param.substring(separator + 1); if (!value.equals(request.getParameter(key))) {
if (!value.equals(request.getParameter(key))) { return negated;
return negated; }
} }
} }
} }
} return true;
return true; }
}
/** /**
* Check whether the given request matches the specified header conditions. * Check whether the given request matches the specified header conditions.
* @param headers the header conditions, following *
* {@link org.springframework.web.bind.annotation.RequestMapping#headers() RequestMapping.headers()} * @param headers the header conditions, following
* @param request the current HTTP request to check * {@link org.springframework.web.bind.annotation.RequestMapping#headers() RequestMapping.headers()}
*/ * @param request the current HTTP request to check
public static boolean checkHeaders(String[] headers, HttpServletRequest request) { */
if (!ObjectUtils.isEmpty(headers)) { public static boolean checkHeaders(String[] headers, HttpServletRequest request) {
for (String header : headers) { if (!ObjectUtils.isEmpty(headers)) {
int separator = header.indexOf('='); for (String header : headers) {
if (separator == -1) { int separator = header.indexOf('=');
if (header.startsWith("!")) { if (separator == -1) {
if (request.getHeader(header.substring(1)) != null) { if (header.startsWith("!")) {
return false; if (request.getHeader(header.substring(1)) != null) {
} return false;
} }
else if (request.getHeader(header) == null) { } else if (request.getHeader(header) == null) {
return false; return false;
} }
} } else {
else { boolean negated = separator > 0 && header.charAt(separator - 1) == '!';
boolean negated = separator > 0 && header.charAt(separator - 1) == '!'; String key = !negated ? header.substring(0, separator) : header.substring(0, separator - 1);
String key = !negated ? header.substring(0, separator) : header.substring(0, separator - 1); String value = header.substring(separator + 1);
String value = header.substring(separator + 1); if (isMediaTypeHeader(key)) {
if (isMediaTypeHeader(key)) { List<MediaType> requestMediaTypes = MediaType.parseMediaTypes(request.getHeader(key));
List<MediaType> requestMediaTypes = MediaType.parseMediaTypes(request.getHeader(key)); List<MediaType> valueMediaTypes = MediaType.parseMediaTypes(value);
List<MediaType> valueMediaTypes = MediaType.parseMediaTypes(value); boolean found = false;
boolean found = false; for (Iterator<MediaType> valIter = valueMediaTypes.iterator(); valIter.hasNext() && !found;) {
for (Iterator<MediaType> valIter = valueMediaTypes.iterator(); valIter.hasNext() && !found;) { MediaType valueMediaType = valIter.next();
MediaType valueMediaType = valIter.next(); for (Iterator<MediaType> reqIter = requestMediaTypes.iterator();
for (Iterator<MediaType> reqIter = requestMediaTypes.iterator(); reqIter.hasNext() && !found;) {
reqIter.hasNext() && !found;) { MediaType requestMediaType = reqIter.next();
MediaType requestMediaType = reqIter.next(); if (valueMediaType.includes(requestMediaType)) {
if (valueMediaType.includes(requestMediaType)) { found = true;
found = true; }
} }
}
} }
if (!found) { if (!found) {
return negated; return negated;
} }
} } else if (!value.equals(request.getHeader(key))) {
else if (!value.equals(request.getHeader(key))) { return negated;
return negated; }
} }
} }
} }
} return true;
return true; }
}
private static boolean isMediaTypeHeader(String headerName) { private static boolean isMediaTypeHeader(String headerName) {
return "Accept".equalsIgnoreCase(headerName) || "Content-Type".equalsIgnoreCase(headerName); return "Accept".equalsIgnoreCase(headerName) || "Content-Type".equalsIgnoreCase(headerName);
} }
} }

View File

@@ -1,17 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>spring-data-document-parent</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.maven.ide.eclipse.maven2Builder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.maven.ide.eclipse.maven2Nature</nature>
</natures>
</projectDescription>

View File

@@ -1,9 +0,0 @@
#Tue Jun 29 21:59:00 EDT 2010
activeProfiles=
eclipse.preferences.version=1
fullBuildGoals=process-test-resources
includeModules=false
resolveWorkspaceProjects=true
resourceFilterGoals=process-resources resources\:testResources
skipCompilerPlugin=true
version=1

View File

@@ -1,91 +1,92 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<groupId>org.springframework.data</groupId> <groupId>org.springframework.data</groupId>
<artifactId>spring-data-document-parent</artifactId> <artifactId>spring-data-document-parent</artifactId>
<name>Spring Data Document Parent</name> <name>Spring Data Document Parent</name>
<url>http://www.springsource.org/spring-data/data-document</url> <url>http://www.springsource.org/spring-data/data-document</url>
<version>1.0.0.BUILD-SNAPSHOT</version> <version>1.0.0.BUILD-SNAPSHOT</version>
<packaging>pom</packaging> <packaging>pom</packaging>
<properties> <properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<!-- versions for commonly-used dependencies --> <!-- versions for commonly-used dependencies -->
<junit.version>4.8.1</junit.version> <junit.version>4.8.1</junit.version>
<log4j.version>1.2.15</log4j.version> <log4j.version>1.2.15</log4j.version>
<org.mockito.version>1.8.4</org.mockito.version> <org.mockito.version>1.8.4</org.mockito.version>
<org.slf4j.version>1.5.10</org.slf4j.version> <org.slf4j.version>1.5.10</org.slf4j.version>
<org.codehaus.jackson.version>1.6.1</org.codehaus.jackson.version> <org.codehaus.jackson.version>1.6.1</org.codehaus.jackson.version>
<org.springframework.version>3.0.5.RELEASE</org.springframework.version> <org.springframework.version>3.0.5.RELEASE</org.springframework.version>
<data.commons.version>1.0.0.BUILD-SNAPSHOT</data.commons.version> <data.commons.version>1.0.0.BUILD-SNAPSHOT</data.commons.version>
<aspectj.version>1.6.11.M2</aspectj.version> <aspectj.version>1.6.11.M2</aspectj.version>
</properties> </properties>
<profiles> <profiles>
<profile> <profile>
<id>strict</id> <id>strict</id>
<properties> <properties>
<maven.test.failure.ignore>false</maven.test.failure.ignore> <maven.test.failure.ignore>false</maven.test.failure.ignore>
</properties> </properties>
</profile> </profile>
<profile> <profile>
<id>fast</id> <id>fast</id>
<properties> <properties>
<maven.test.skip>true</maven.test.skip> <maven.test.skip>true</maven.test.skip>
<maven.javadoc.skip>true</maven.javadoc.skip> <maven.javadoc.skip>true</maven.javadoc.skip>
</properties> </properties>
</profile> </profile>
<profile> <profile>
<id>staging</id> <id>staging</id>
<distributionManagement> <distributionManagement>
<site> <site>
<id>spring-site-staging</id> <id>spring-site-staging</id>
<url>file:///${java.io.tmpdir}/spring-data/data-document/docs</url> <url>file:///${java.io.tmpdir}/spring-data/data-document/docs</url>
</site> </site>
<repository> <repository>
<id>spring-milestone-staging</id> <id>spring-milestone-staging</id>
<url>file:///${java.io.tmpdir}/spring-data/data-document/milestone</url> <url>file:///${java.io.tmpdir}/spring-data/data-document/milestone</url>
</repository> </repository>
<snapshotRepository> <snapshotRepository>
<id>spring-snapshot-staging</id> <id>spring-snapshot-staging</id>
<url>file:///${java.io.tmpdir}/spring-data/data-document/snapshot</url> <url>file:///${java.io.tmpdir}/spring-data/data-document/snapshot</url>
</snapshotRepository> </snapshotRepository>
</distributionManagement> </distributionManagement>
</profile> </profile>
<profile> <profile>
<id>bootstrap</id> <id>bootstrap</id>
<!-- TODO: move the repositories in here before release --> <!-- TODO: move the repositories in here before release -->
</profile> </profile>
</profiles> </profiles>
<distributionManagement> <distributionManagement>
<!-- see 'staging' profile for dry-run deployment settings --> <!-- see 'staging' profile for dry-run deployment settings -->
<downloadUrl>http://www.springsource.com/download/community <downloadUrl>http://www.springsource.com/download/community
</downloadUrl> </downloadUrl>
<site> <site>
<id>static.springframework.org</id> <id>static.springframework.org</id>
<url>scp://static.springframework.org/var/www/domains/springframework.org/static/htdocs/spring-data/data-document/docs/${project.version} <url>
</url> scp://static.springframework.org/var/www/domains/springframework.org/static/htdocs/spring-data/data-document/docs/${project.version}
</site> </url>
<repository> </site>
<id>spring-milestone</id> <repository>
<name>Spring Milestone Repository</name> <id>spring-milestone</id>
<url>s3://maven.springframework.org/milestone</url> <name>Spring Milestone Repository</name>
</repository> <url>s3://maven.springframework.org/milestone</url>
<snapshotRepository> </repository>
<id>spring-snapshot</id> <snapshotRepository>
<name>Spring Snapshot Repository</name> <id>spring-snapshot</id>
<url>s3://maven.springframework.org/snapshot</url> <name>Spring Snapshot Repository</name>
</snapshotRepository> <url>s3://maven.springframework.org/snapshot</url>
</distributionManagement> </snapshotRepository>
<dependencyManagement> </distributionManagement>
<!-- <dependencyManagement>
inheritable <dependency> declarations for child poms. children still <!--
must explicitly declare the groupId/artifactId of these dependencies inheritable <dependency> declarations for child poms. children still
in order for them to show up on the classpath, but metadata like must explicitly declare the groupId/artifactId of these dependencies
<version> and <scope> are inherited, which cuts down on verbosity. in order for them to show up on the classpath, but metadata like
see <version> and <scope> are inherited, which cuts down on verbosity.
http://www.sonatype.com/books/mvnref-book/reference/pom-relationships-sect-dep-manage.html see
--> http://www.sonatype.com/books/mvnref-book/reference/pom-relationships-sect-dep-manage.html
<dependencies> -->
<dependencies>
<!-- Spring --> <!-- Spring -->
<dependency> <dependency>

View File

@@ -1,9 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry including="**/*.aj|**/*.java" kind="src" output="target/classes" path="src/main/java"/>
<classpathentry including="**/*.aj|**/*.java" kind="src" output="target/test-classes" path="src/test/java"/>
<classpathentry kind="src" output="target/test-classes" path="src/test/resources"/>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6"/>
<classpathentry kind="con" path="org.maven.ide.eclipse.MAVEN2_CLASSPATH_CONTAINER"/>
<classpathentry kind="output" path="target/classes"/>
</classpath>

View File

@@ -1,24 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>spring-data-mongodb-cross-store</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.ajdt.core.ajbuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.maven.ide.eclipse.maven2Builder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.ajdt.ui.ajnature</nature>
<nature>org.eclipse.jdt.core.javanature</nature>
<nature>org.maven.ide.eclipse.maven2Nature</nature>
</natures>
</projectDescription>

View File

@@ -1,9 +0,0 @@
#Tue Mar 01 09:48:37 EST 2011
eclipse.preferences.version=1
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
org.eclipse.jdt.core.compiler.compliance=1.6
org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
org.eclipse.jdt.core.compiler.source=1.6

View File

@@ -1,8 +0,0 @@
#Mon Feb 28 16:25:59 EST 2011
activeProfiles=
eclipse.preferences.version=1
fullBuildGoals=process-test-resources
resolveWorkspaceProjects=true
resourceFilterGoals=process-resources resources\:testResources
skipCompilerPlugin=true
version=1

View File

@@ -115,72 +115,72 @@
<version>1.0.0.Final</version> <version>1.0.0.Final</version>
</dependency> </dependency>
</dependencies> </dependencies>
<repositories> <repositories>
<repository> <repository>
<id>jboss-repository</id> <id>jboss-repository</id>
<name>JBoss Public Repository</name> <name>JBoss Public Repository</name>
<url>http://repository.jboss.org/nexus/content/groups/public-jboss</url> <url>http://repository.jboss.org/nexus/content/groups/public-jboss</url>
</repository> </repository>
<repository> <repository>
<id>spring-maven-snapshot</id> <id>spring-maven-snapshot</id>
<snapshots> <snapshots>
<enabled>true</enabled> <enabled>true</enabled>
</snapshots> </snapshots>
<name>Springframework Maven SNAPSHOT Repository</name> <name>Springframework Maven SNAPSHOT Repository</name>
<url>http://maven.springframework.org/snapshot</url> <url>http://maven.springframework.org/snapshot</url>
</repository> </repository>
</repositories> </repositories>
<pluginRepositories> <pluginRepositories>
<pluginRepository> <pluginRepository>
<id>spring-maven-milestones</id> <id>spring-maven-milestones</id>
<name>Springframework Maven Milestone Repository</name> <name>Springframework Maven Milestone Repository</name>
<url>http://maven.springframework.org/milestone</url> <url>http://maven.springframework.org/milestone</url>
</pluginRepository> </pluginRepository>
</pluginRepositories> </pluginRepositories>
<build> <build>
<plugins> <plugins>
<plugin> <plugin>
<groupId>org.codehaus.mojo</groupId> <groupId>org.codehaus.mojo</groupId>
<artifactId>aspectj-maven-plugin</artifactId> <artifactId>aspectj-maven-plugin</artifactId>
<version>1.2</version> <version>1.2</version>
<dependencies> <dependencies>
<dependency> <dependency>
<groupId>org.aspectj</groupId> <groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId> <artifactId>aspectjrt</artifactId>
<version>${aspectj.version}</version> <version>${aspectj.version}</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.aspectj</groupId> <groupId>org.aspectj</groupId>
<artifactId>aspectjtools</artifactId> <artifactId>aspectjtools</artifactId>
<version>${aspectj.version}</version> <version>${aspectj.version}</version>
</dependency> </dependency>
</dependencies> </dependencies>
<executions> <executions>
<execution> <execution>
<goals> <goals>
<goal>compile</goal> <goal>compile</goal>
<goal>test-compile</goal> <goal>test-compile</goal>
</goals> </goals>
</execution> </execution>
</executions> </executions>
<configuration> <configuration>
<outxml>true</outxml> <outxml>true</outxml>
<aspectLibraries> <aspectLibraries>
<aspectLibrary> <aspectLibrary>
<groupId>org.springframework</groupId> <groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId> <artifactId>spring-aspects</artifactId>
</aspectLibrary> </aspectLibrary>
<aspectLibrary> <aspectLibrary>
<groupId>org.springframework.data</groupId> <groupId>org.springframework.data</groupId>
<artifactId>spring-data-commons-aspects</artifactId> <artifactId>spring-data-commons-aspects</artifactId>
</aspectLibrary> </aspectLibrary>
</aspectLibraries> </aspectLibraries>
<source>1.6</source> <source>1.6</source>
<target>1.6</target> <target>1.6</target>
</configuration> </configuration>
</plugin> </plugin>
</plugins> </plugins>
</build> </build>
</project> </project>

View File

@@ -8,7 +8,7 @@ import java.lang.annotation.Target;
/** /**
* Annotation to denote an object that should be transparently persisted * Annotation to denote an object that should be transparently persisted
* using MongoDB * using MongoDB
* *
* @author Thomas Risberg * @author Thomas Risberg
*/ */

View File

@@ -1,7 +1,9 @@
package org.springframework.persistence.document; package org.springframework.persistence.document;
import java.util.Map; import com.mongodb.BasicDBObject;
import com.mongodb.DBCollection;
import com.mongodb.DBObject;
import com.mongodb.MongoException;
import org.apache.commons.logging.Log; import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory; import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
@@ -14,111 +16,104 @@ import org.springframework.persistence.support.ChangeSetBacked;
import org.springframework.persistence.support.ChangeSetPersister; import org.springframework.persistence.support.ChangeSetPersister;
import org.springframework.util.ClassUtils; import org.springframework.util.ClassUtils;
import com.mongodb.BasicDBObject;
import com.mongodb.DB;
import com.mongodb.DBCollection;
import com.mongodb.DBObject;
import com.mongodb.Mongo;
import com.mongodb.MongoException;
//import edu.emory.mathcs.backport.java.util.Arrays; //import edu.emory.mathcs.backport.java.util.Arrays;
public class MongoChangeSetPersister implements ChangeSetPersister<Object> { public class MongoChangeSetPersister implements ChangeSetPersister<Object> {
protected final Log log = LogFactory.getLog(getClass()); protected final Log log = LogFactory.getLog(getClass());
@Autowired @Autowired
private MongoTemplate mongoTemplate; private MongoTemplate mongoTemplate;
@Autowired
private ConversionService conversionService;
@Override
public void getPersistentState(Class<? extends ChangeSetBacked> entityClass, Object id, ChangeSet changeSet)
throws DataAccessException, NotFoundException {
String collection = ClassUtils.getShortName(entityClass).toLowerCase();
DBObject q = new BasicDBObject();
q.put("_id", id);
try {
DBObject dbo = mongoTemplate.getCollection(collection).findOne(q);
log.debug("Found DBObject: " + dbo);
if (dbo == null) {
throw new NotFoundException();
}
String classShortName = ClassUtils.getShortName(entityClass);
for (Object property : dbo.toMap().keySet()) {
String propertyKey = (String) property;
String propertyName = propertyKey.startsWith(classShortName) ? propertyKey.substring(propertyKey.indexOf(classShortName)
+ classShortName.length() + 1) : propertyKey;
// System.err.println("Mongo persisted property [" + propertyName + "] :: " + propertyKey + " = " + dbo.get(propertyKey));
if (propertyKey.startsWith("_")) {
// Id or class
changeSet.set(propertyKey, dbo.get(propertyKey));
} else {
//throw new IllegalStateException("Unknown property [" + propertyName + "] found in MongoDB store");
changeSet.set(propertyKey, dbo.get(propertyKey));
}
}
} catch (MongoException ex) {
throw new DataAccessResourceFailureException("Can't read from Mongo", ex);
}
}
@Override
public Object getPersistentId(Class<? extends ChangeSetBacked> entityClass,
ChangeSet cs) throws DataAccessException {
log.debug("getPersistentId called on " + entityClass);
if (cs == null) {
return null;
}
if (cs.getValues().get(ChangeSetPersister.ID_KEY) == null) {
// Not yet persistent
return null;
}
Object o = cs.getValues().get(ChangeSetPersister.ID_KEY);
return o;
}
@Override
public Object persistState(Class<? extends ChangeSetBacked> entityClass, ChangeSet cs) throws DataAccessException {
log.info("PERSIST::"+cs);
cs.set(CLASS_KEY, entityClass.getName());
String idstr = cs.get(ID_KEY, String.class, this.conversionService);
Object id = null;
if (idstr != null) {
id = idstr;
}
if (id == null) {
log.info("Flush: entity make persistent; data store will assign id");
cs.set("_class", entityClass.getName());
String collection = entityClass.getSimpleName().toLowerCase();
DBCollection dbc = mongoTemplate.getCollection(collection);
DBObject dbo = mapChangeSetToDbObject(cs);
if (dbc == null) {
dbc = mongoTemplate.createCollection(collection);
}
dbc.save(dbo);
id = dbo.get(ID_KEY);
log.info("Data store assigned id: " + id);
} else {
log.info("Flush: entity already persistent with id=" + id);
String collection = entityClass.getName();
DBCollection dbc = mongoTemplate.getCollection(collection);
DBObject dbo = mapChangeSetToDbObject(cs);
if (dbc == null) {
throw new DataAccessResourceFailureException("Expected to find a collection named '" + collection +"'. It was not found, so ChangeSet can't be persisted.");
}
dbc.save(dbo);
}
return 0L; @Autowired
} private ConversionService conversionService;
private DBObject mapChangeSetToDbObject(ChangeSet cs) { @Override
BasicDBObject dbo = new BasicDBObject(); public void getPersistentState(Class<? extends ChangeSetBacked> entityClass, Object id, ChangeSet changeSet)
for (String property : cs.getValues().keySet()) { throws DataAccessException, NotFoundException {
dbo.put(property, cs.getValues().get(property)); String collection = ClassUtils.getShortName(entityClass).toLowerCase();
} DBObject q = new BasicDBObject();
return dbo; q.put("_id", id);
} try {
DBObject dbo = mongoTemplate.getCollection(collection).findOne(q);
log.debug("Found DBObject: " + dbo);
if (dbo == null) {
throw new NotFoundException();
}
String classShortName = ClassUtils.getShortName(entityClass);
for (Object property : dbo.toMap().keySet()) {
String propertyKey = (String) property;
String propertyName = propertyKey.startsWith(classShortName) ? propertyKey.substring(propertyKey.indexOf(classShortName)
+ classShortName.length() + 1) : propertyKey;
// System.err.println("Mongo persisted property [" + propertyName + "] :: " + propertyKey + " = " + dbo.get(propertyKey));
if (propertyKey.startsWith("_")) {
// Id or class
changeSet.set(propertyKey, dbo.get(propertyKey));
} else {
//throw new IllegalStateException("Unknown property [" + propertyName + "] found in MongoDB store");
changeSet.set(propertyKey, dbo.get(propertyKey));
}
}
} catch (MongoException ex) {
throw new DataAccessResourceFailureException("Can't read from Mongo", ex);
}
}
@Override
public Object getPersistentId(Class<? extends ChangeSetBacked> entityClass,
ChangeSet cs) throws DataAccessException {
log.debug("getPersistentId called on " + entityClass);
if (cs == null) {
return null;
}
if (cs.getValues().get(ChangeSetPersister.ID_KEY) == null) {
// Not yet persistent
return null;
}
Object o = cs.getValues().get(ChangeSetPersister.ID_KEY);
return o;
}
@Override
public Object persistState(Class<? extends ChangeSetBacked> entityClass, ChangeSet cs) throws DataAccessException {
log.info("PERSIST::" + cs);
cs.set(CLASS_KEY, entityClass.getName());
String idstr = cs.get(ID_KEY, String.class, this.conversionService);
Object id = null;
if (idstr != null) {
id = idstr;
}
if (id == null) {
log.info("Flush: entity make persistent; data store will assign id");
cs.set("_class", entityClass.getName());
String collection = entityClass.getSimpleName().toLowerCase();
DBCollection dbc = mongoTemplate.getCollection(collection);
DBObject dbo = mapChangeSetToDbObject(cs);
if (dbc == null) {
dbc = mongoTemplate.createCollection(collection);
}
dbc.save(dbo);
id = dbo.get(ID_KEY);
log.info("Data store assigned id: " + id);
} else {
log.info("Flush: entity already persistent with id=" + id);
String collection = entityClass.getName();
DBCollection dbc = mongoTemplate.getCollection(collection);
DBObject dbo = mapChangeSetToDbObject(cs);
if (dbc == null) {
throw new DataAccessResourceFailureException("Expected to find a collection named '" + collection + "'. It was not found, so ChangeSet can't be persisted.");
}
dbc.save(dbo);
}
return 0L;
}
private DBObject mapChangeSetToDbObject(ChangeSet cs) {
BasicDBObject dbo = new BasicDBObject();
for (String property : cs.getValues().keySet()) {
dbo.put(property, cs.getValues().get(property));
}
return dbo;
}
} }

View File

@@ -4,7 +4,7 @@ import org.springframework.persistence.support.AbstractDeferredUpdateMixinFields
/** /**
* Aspect to turn an object annotated with DocumentEntity into a document entity using Mongo. * Aspect to turn an object annotated with DocumentEntity into a document entity using Mongo.
* *
* @author Thomas Risberg * @author Thomas Risberg
*/ */
public aspect MongoDocumentBacking extends AbstractDeferredUpdateMixinFields<DocumentEntity> { public aspect MongoDocumentBacking extends AbstractDeferredUpdateMixinFields<DocumentEntity> {

View File

@@ -13,69 +13,66 @@ import org.springframework.persistence.support.ChangeSetPersister.NotFoundExcept
import org.springframework.persistence.support.EntityInstantiator; import org.springframework.persistence.support.EntityInstantiator;
import org.springframework.persistence.support.HashMapChangeSet; import org.springframework.persistence.support.HashMapChangeSet;
import com.mongodb.DB;
public class MongoEntityOperations extends OrderedEntityOperations<Object, ChangeSetBacked> { public class MongoEntityOperations extends OrderedEntityOperations<Object, ChangeSetBacked> {
@Autowired
private MongoTemplate mongoTemplate;
private EntityInstantiator<ChangeSetBacked, ChangeSet> entityInstantiator;
private MongoChangeSetPersister changeSetPersister; @Autowired
private MongoTemplate mongoTemplate;
public void setEntityInstantiator(EntityInstantiator<ChangeSetBacked, ChangeSet> entityInstantiator) { private EntityInstantiator<ChangeSetBacked, ChangeSet> entityInstantiator;
this.entityInstantiator = entityInstantiator;
}
@Autowired private MongoChangeSetPersister changeSetPersister;
public void setChangeSetPersister(MongoChangeSetPersister changeSetPersister) {
this.changeSetPersister = changeSetPersister; public void setEntityInstantiator(EntityInstantiator<ChangeSetBacked, ChangeSet> entityInstantiator) {
} this.entityInstantiator = entityInstantiator;
}
@Autowired
public void setChangeSetPersister(MongoChangeSetPersister changeSetPersister) {
this.changeSetPersister = changeSetPersister;
}
@Override @Override
public boolean cacheInEntity() { public boolean cacheInEntity() {
return true; return true;
} }
@Override @Override
public ChangeSetBacked findEntity(Class<ChangeSetBacked> entityClass, Object key) throws DataAccessException { public ChangeSetBacked findEntity(Class<ChangeSetBacked> entityClass, Object key) throws DataAccessException {
try { try {
ChangeSet cs = new HashMapChangeSet(); ChangeSet cs = new HashMapChangeSet();
changeSetPersister.getPersistentState(entityClass, key, cs); changeSetPersister.getPersistentState(entityClass, key, cs);
return entityInstantiator.createEntityFromState(cs, entityClass); return entityInstantiator.createEntityFromState(cs, entityClass);
} } catch (NotFoundException ex) {
catch (NotFoundException ex) { return null;
return null; }
} }
}
@Override @Override
public Object findUniqueKey(ChangeSetBacked entity) throws DataAccessException { public Object findUniqueKey(ChangeSetBacked entity) throws DataAccessException {
return entity.getId(); return entity.getId();
} }
@Override @Override
public boolean isTransactional() { public boolean isTransactional() {
// TODO // TODO
return false; return false;
} }
@Override @Override
public boolean isTransient(ChangeSetBacked entity) throws DataAccessException { public boolean isTransient(ChangeSetBacked entity) throws DataAccessException {
return entity.getId() == null; return entity.getId() == null;
} }
@Override @Override
public Object makePersistent(Object owner, ChangeSetBacked entity, Field f, RelatedEntity fs) throws DataAccessException { public Object makePersistent(Object owner, ChangeSetBacked entity, Field f, RelatedEntity fs) throws DataAccessException {
changeSetPersister.persistState(entity.getClass(), entity.getChangeSet()); changeSetPersister.persistState(entity.getClass(), entity.getChangeSet());
return entity.getId(); return entity.getId();
} }
@Override @Override
public boolean supports(Class<?> entityClass, RelatedEntity fs) { public boolean supports(Class<?> entityClass, RelatedEntity fs) {
return entityClass.isAnnotationPresent(DocumentEntity.class); return entityClass.isAnnotationPresent(DocumentEntity.class);
} }
} }

View File

@@ -3,6 +3,7 @@ package org.springframework.data.document.persistence;
import javax.persistence.EntityManager; import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext; import javax.persistence.PersistenceContext;
import com.mongodb.*;
import org.junit.Assert; import org.junit.Assert;
import org.junit.Test; import org.junit.Test;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
@@ -17,122 +18,116 @@ import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
import com.mongodb.DBCollection;
import com.mongodb.DBCursor;
import com.mongodb.DBObject;
import com.mongodb.Mongo;
import com.mongodb.MongoException;
@RunWith(SpringJUnit4ClassRunner.class) @RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "classpath:/META-INF/spring/applicationContext.xml") @ContextConfiguration(locations = "classpath:/META-INF/spring/applicationContext.xml")
public class CrossStoreMongoTests { public class CrossStoreMongoTests {
@Autowired @Autowired
private Mongo mongo; private Mongo mongo;
@Autowired @Autowired
private MongoTemplate mongoTemplate; private MongoTemplate mongoTemplate;
private EntityManager entityManager;
private String colName = MongoPerson.class.getSimpleName().toLowerCase();
private EntityManager entityManager;
@PersistenceContext
public void setEntityManager(EntityManager entityManager) { private String colName = MongoPerson.class.getSimpleName().toLowerCase();
this.entityManager = entityManager;
@PersistenceContext
public void setEntityManager(EntityManager entityManager) {
this.entityManager = entityManager;
}
private void clearData(String collectionName) {
DBCollection col = this.mongoTemplate.getCollection(collectionName);
if (col != null) {
this.mongoTemplate.dropCollection(collectionName);
} }
}
private void clearData(String collectionName) { @Test
DBCollection col = this.mongoTemplate.getCollection(collectionName); @Transactional
if (col != null) { @Rollback(false)
this.mongoTemplate.dropCollection(collectionName); public void testUserConstructor() {
} clearData(colName);
} int age = 33;
MongoPerson p = new MongoPerson("Thomas", age);
@Test Assert.assertEquals(age, p.getAge());
@Transactional p.birthday();
@Rollback(false) Assert.assertEquals(1 + age, p.getAge());
public void testUserConstructor() { }
clearData(colName);
int age = 33;
MongoPerson p = new MongoPerson("Thomas", age);
Assert.assertEquals(age, p.getAge());
p.birthday();
Assert.assertEquals(1 + age, p.getAge());
}
@Test @Test
@Transactional @Transactional
public void testInstantiatedFinder() throws MongoException { public void testInstantiatedFinder() throws MongoException {
DBCollection col = this.mongoTemplate.getCollection(colName); DBCollection col = this.mongoTemplate.getCollection(colName);
DBObject dbo = col.findOne(); DBObject dbo = col.findOne();
Object _id = dbo.get("_id"); Object _id = dbo.get("_id");
MongoPerson found = MongoPerson.findPerson(_id); MongoPerson found = MongoPerson.findPerson(_id);
Assert.assertNotNull(found); Assert.assertNotNull(found);
Assert.assertEquals(_id, found.getId()); Assert.assertEquals(_id, found.getId());
System.out.println("Loaded MongoPerson data: " + found); System.out.println("Loaded MongoPerson data: " + found);
} }
@Test @Test
@Transactional @Transactional
@Rollback(false) @Rollback(false)
public void testCreateMongoToJpaEntityRelationship() { public void testCreateMongoToJpaEntityRelationship() {
clearData(colName); clearData(colName);
Account a = new Account(); Account a = new Account();
a.setName("My Account"); a.setName("My Account");
a.setFriendlyName("My Test Acct."); a.setFriendlyName("My Test Acct.");
a.setBalance(123.45F); a.setBalance(123.45F);
a.setId(2L); a.setId(2L);
MongoPerson p = new MongoPerson("Jack", 22); MongoPerson p = new MongoPerson("Jack", 22);
entityManager.persist(a); entityManager.persist(a);
p.setAccount(a); p.setAccount(a);
} }
@Test @Test
@Transactional @Transactional
public void testReadMongoToJpaEntityRelationship() { public void testReadMongoToJpaEntityRelationship() {
DBCollection col = this.mongoTemplate.getCollection(colName); DBCollection col = this.mongoTemplate.getCollection(colName);
DBCursor dbc = col.find(); DBCursor dbc = col.find();
Object _id = null; Object _id = null;
for (DBObject dbo : dbc) { for (DBObject dbo : dbc) {
System.out.println(dbo); System.out.println(dbo);
if ("Jack".equals(dbo.get("name"))) { if ("Jack".equals(dbo.get("name"))) {
_id = dbo.get("_id"); _id = dbo.get("_id");
break; break;
} }
} }
System.out.println(_id); System.out.println(_id);
MongoPerson found = MongoPerson.findPerson(_id); MongoPerson found = MongoPerson.findPerson(_id);
System.out.println(found); System.out.println(found);
if (found != null) if (found != null)
System.out.println(found.getAccount()); System.out.println(found.getAccount());
} }
@Test @Test
@Transactional @Transactional
@Rollback(false) @Rollback(false)
public void testCreateJpaToMongoEntityRelationship() { public void testCreateJpaToMongoEntityRelationship() {
clearData("resume"); clearData("resume");
Person p = new Person("Thomas", 20); Person p = new Person("Thomas", 20);
Resume r = new Resume(); Resume r = new Resume();
r.addEducation("Skanstulls High School, 1975"); r.addEducation("Skanstulls High School, 1975");
r.addEducation("Univ. of Stockholm, 1980"); r.addEducation("Univ. of Stockholm, 1980");
r.addJob("DiMark, DBA, 1990-2000"); r.addJob("DiMark, DBA, 1990-2000");
r.addJob("VMware, Developer, 2007-"); r.addJob("VMware, Developer, 2007-");
p.setResume(r); p.setResume(r);
p.setId(1L); p.setId(1L);
entityManager.persist(p); entityManager.persist(p);
} }
@Test @Test
@Transactional @Transactional
public void testReadJpaToMongoEntityRelationship() { public void testReadJpaToMongoEntityRelationship() {
Person found = entityManager.find(Person.class, 1L); Person found = entityManager.find(Person.class, 1L);
System.out.println(found); System.out.println(found);
// TODO: This part isn't working yet - there is no reference to the Momgo _id stored in the db // TODO: This part isn't working yet - there is no reference to the Momgo _id stored in the db
// if (found != null) // if (found != null)
// System.out.println(found.getResume()); // System.out.println(found.getResume());
} }
} }

View File

@@ -5,61 +5,62 @@ import javax.persistence.Id;
@Entity @Entity
public class Account { public class Account {
@Id private Long id;
private String name; @Id
private Long id;
private float balance; private String name;
private String friendlyName; private float balance;
private String whatever; private String friendlyName;
public Long getId() { private String whatever;
return id;
}
public void setId(Long id) { public Long getId() {
this.id = id; return id;
} }
public String getName() { public void setId(Long id) {
return name; this.id = id;
} }
public void setName(String name) { public String getName() {
this.name = name; return name;
} }
public float getBalance() { public void setName(String name) {
return balance; this.name = name;
} }
public void setBalance(float balance) { public float getBalance() {
this.balance = balance; return balance;
} }
public String getFriendlyName() { public void setBalance(float balance) {
return friendlyName; this.balance = balance;
} }
public void setFriendlyName(String friendlyName) { public String getFriendlyName() {
this.friendlyName = friendlyName; return friendlyName;
} }
public String getWhatever() { public void setFriendlyName(String friendlyName) {
return whatever; this.friendlyName = friendlyName;
} }
public void setWhatever(String whatever) { public String getWhatever() {
this.whatever = whatever; return whatever;
} }
@Override public void setWhatever(String whatever) {
public String toString() { this.whatever = whatever;
return "Account [id=" + id + ", name=" + name + ", balance=" + balance }
+ ", friendlyName=" + friendlyName + "]";
} @Override
public String toString() {
return "Account [id=" + id + ", name=" + name + ", balance=" + balance
+ ", friendlyName=" + friendlyName + "]";
}
} }

View File

@@ -2,62 +2,62 @@ package org.springframework.persistence.document.test;
import org.springframework.persistence.RelatedEntity; import org.springframework.persistence.RelatedEntity;
import org.springframework.persistence.document.DocumentEntity; import org.springframework.persistence.document.DocumentEntity;
@DocumentEntity @DocumentEntity
public class MongoPerson { public class MongoPerson {
// TODO only public because of AspectJ bug
public String name;
public int age;
public java.util.Date birthDate;
// TODO only public to check weaving bug-- // TODO only public because of AspectJ bug
// seems to work whereas private didn't public String name;
@RelatedEntity
public Account account;
public MongoPerson(String name, int age) { public int age;
this.name = name;
this.age = age;
this.birthDate = new java.util.Date();
}
public void birthday() { public java.util.Date birthDate;
++age;
}
public String getName() { // TODO only public to check weaving bug--
return name; // seems to work whereas private didn't
} @RelatedEntity
public Account account;
public void setName(String name) { public MongoPerson(String name, int age) {
this.name = name; this.name = name;
} this.age = age;
this.birthDate = new java.util.Date();
}
public int getAge() { public void birthday() {
return age; ++age;
} }
public void setAge(int age) { public String getName() {
this.age = age; return name;
} }
public java.util.Date getBirthDate() { public void setName(String name) {
return birthDate; this.name = name;
} }
public void setBirthDate(java.util.Date birthDate) { public int getAge() {
this.birthDate = birthDate; return age;
} }
public Account getAccount() { public void setAge(int age) {
return account; this.age = age;
} }
public void setAccount(Account account) { public java.util.Date getBirthDate() {
this.account = account; return birthDate;
} }
public void setBirthDate(java.util.Date birthDate) {
this.birthDate = birthDate;
}
public Account getAccount() {
return account;
}
public void setAccount(Account account) {
this.account = account;
}
} }

View File

@@ -3,58 +3,52 @@ package org.springframework.persistence.document.test;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Configurable; import org.springframework.beans.factory.annotation.Configurable;
import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.persistence.support.ChangeSet; import org.springframework.persistence.support.*;
import org.springframework.persistence.support.ChangeSetBacked;
import org.springframework.persistence.support.ChangeSetConfiguration;
import org.springframework.persistence.support.ChangeSetPersister;
import org.springframework.persistence.support.ChangeSetSynchronizer;
import org.springframework.persistence.support.HashMapChangeSet;
import org.springframework.persistence.support.ChangeSetPersister.NotFoundException; import org.springframework.persistence.support.ChangeSetPersister.NotFoundException;
/** /**
* EXAMPLE OF CODE THAT SHOULD BE GENERATED BY ROO BESIDES EACH MONGOENTITY CLASS * EXAMPLE OF CODE THAT SHOULD BE GENERATED BY ROO BESIDES EACH MONGOENTITY CLASS
* *
* Note: Combines X_Roo_Entity with X_Roo_Finder, as * Note: Combines X_Roo_Entity with X_Roo_Finder, as
* we need only a single aspect for entities. * we need only a single aspect for entities.
* *
* @author Thomas Risberg * @author Thomas Risberg
* *
*/ */
privileged aspect MongoPerson_Roo_Mongo_Entity { privileged aspect MongoPerson_Roo_Mongo_Entity {
private static ChangeSetPersister<Object> changeSetPersister() {
return new MongoConfigurationHolder().changeSetConfig.getChangeSetPersister();
}
private static ChangeSetSynchronizer<ChangeSetBacked> changeSetManager() {
return new MongoConfigurationHolder().changeSetConfig.getChangeSetManager();
}
@Configurable private static ChangeSetPersister<Object> changeSetPersister() {
public static class MongoConfigurationHolder { return new MongoConfigurationHolder().changeSetConfig.getChangeSetPersister();
@Autowired }
@Qualifier("mongoChangeSetConfiguration")
public ChangeSetConfiguration<Object> changeSetConfig;
}
/** private static ChangeSetSynchronizer<ChangeSetBacked> changeSetManager() {
* Add constructor that takes ChangeSet. return new MongoConfigurationHolder().changeSetConfig.getChangeSetManager();
* @param ChangeSet }
*/
public MongoPerson.new(ChangeSet cs) {
super();
setChangeSet(cs);
}
public static MongoPerson MongoPerson.findPerson(Object id) { @Configurable
ChangeSet rv = new HashMapChangeSet(); public static class MongoConfigurationHolder {
try { @Autowired
changeSetPersister().getPersistentState(MongoPerson.class, id, rv); @Qualifier("mongoChangeSetConfiguration")
return new MongoPerson(rv); public ChangeSetConfiguration<Object> changeSetConfig;
} }
catch (NotFoundException ex) {
return null; /**
} * Add constructor that takes ChangeSet.
} * @param ChangeSet
*/
public MongoPerson.new(ChangeSet cs) {
super();
setChangeSet(cs);
}
public static MongoPerson MongoPerson.findPerson(Object id) {
ChangeSet rv = new HashMapChangeSet();
try {
changeSetPersister().getPersistentState(MongoPerson.class, id, rv);
return new MongoPerson(rv);
} catch (NotFoundException ex) {
return null;
}
}
} }

View File

@@ -4,73 +4,74 @@ import javax.persistence.Entity;
import javax.persistence.Id; import javax.persistence.Id;
import org.springframework.persistence.RelatedEntity; import org.springframework.persistence.RelatedEntity;
@Entity @Entity
public class Person { public class Person {
@Id Long id;
private String name;
private int age;
private java.util.Date birthDate;
// @Document // need to decide what the annotation here should be @Id
@RelatedEntity Long id;
public Resume resume;
public Person() { private String name;
}
public Person(String name, int age) { private int age;
this.name = name;
this.age = age;
this.birthDate = new java.util.Date();
}
public void birthday() { private java.util.Date birthDate;
++age;
}
public Long getId() { // @Document // need to decide what the annotation here should be
return id; @RelatedEntity
} public Resume resume;
public void setId(Long id) { public Person() {
this.id = id; }
}
public String getName() { public Person(String name, int age) {
return name; this.name = name;
} this.age = age;
this.birthDate = new java.util.Date();
}
public void setName(String name) { public void birthday() {
this.name = name; ++age;
} }
public int getAge() { public Long getId() {
return age; return id;
} }
public void setAge(int age) { public void setId(Long id) {
this.age = age; this.id = id;
} }
public java.util.Date getBirthDate() { public String getName() {
return birthDate; return name;
} }
public void setBirthDate(java.util.Date birthDate) { public void setName(String name) {
this.birthDate = birthDate; this.name = name;
} }
public Resume getResume() { public int getAge() {
return resume; return age;
} }
public void setResume(Resume resume) { public void setAge(int age) {
this.resume = resume; this.age = age;
} }
public java.util.Date getBirthDate() {
return birthDate;
}
public void setBirthDate(java.util.Date birthDate) {
this.birthDate = birthDate;
}
public Resume getResume() {
return resume;
}
public void setResume(Resume resume) {
this.resume = resume;
}
} }

View File

@@ -5,29 +5,29 @@ import org.springframework.persistence.document.DocumentEntity;
@DocumentEntity @DocumentEntity
public class Resume { public class Resume {
private String education = ""; private String education = "";
private String jobs = "";
public String getEducation() { private String jobs = "";
return education;
}
public void addEducation(String education) { public String getEducation() {
this.education = this.education + (this.education.length() > 0 ? "; " : "") + education; return education;
} }
public String getJobs() { public void addEducation(String education) {
return jobs; this.education = this.education + (this.education.length() > 0 ? "; " : "") + education;
} }
public void addJob(String job) { public String getJobs() {
this.jobs = this.jobs + (this.jobs.length() > 0 ? "; " : "") + job; return jobs;
} }
public void addJob(String job) {
this.jobs = this.jobs + (this.jobs.length() > 0 ? "; " : "") + job;
}
@Override
public String toString() {
return "Resume [education=" + education + ", jobs=" + jobs + "]";
}
@Override
public String toString() {
return "Resume [education=" + education + ", jobs=" + jobs + "]";
}
} }

View File

@@ -1,13 +1,15 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?> <?xml version="1.0" encoding="UTF-8" standalone="no"?>
<persistence xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="2.0" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd"> <persistence xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
<persistence-unit name="test" transaction-type="RESOURCE_LOCAL"> version="2.0"
<provider>org.hibernate.ejb.HibernatePersistence</provider> xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd">
<class>org.springframework.persistence.document.test.Account</class> <persistence-unit name="test" transaction-type="RESOURCE_LOCAL">
<properties> <provider>org.hibernate.ejb.HibernatePersistence</provider>
<property name="hibernate.dialect" value="org.hibernate.dialect.HSQLDialect"/> <class>org.springframework.persistence.document.test.Account</class>
<!--value='create' to build a new database on each run; value='update' to modify an existing database; value='create-drop' means the same as 'create' but also drops tables when Hibernate closes; value='validate' makes no changes to the database--> <properties>
<property name="hibernate.hbm2ddl.auto" value="update"/> <property name="hibernate.dialect" value="org.hibernate.dialect.HSQLDialect"/>
<property name="hibernate.ejb.naming_strategy" value="org.hibernate.cfg.ImprovedNamingStrategy"/> <!--value='create' to build a new database on each run; value='update' to modify an existing database; value='create-drop' means the same as 'create' but also drops tables when Hibernate closes; value='validate' makes no changes to the database-->
</properties> <property name="hibernate.hbm2ddl.auto" value="update"/>
</persistence-unit> <property name="hibernate.ejb.naming_strategy" value="org.hibernate.cfg.ImprovedNamingStrategy"/>
</properties>
</persistence-unit>
</persistence> </persistence>

View File

@@ -1,98 +1,99 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" <beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:tx="http://www.springframework.org/schema/tx" xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:jdbc="http://www.springframework.org/schema/jdbc" xmlns:jdbc="http://www.springframework.org/schema/jdbc"
xmlns:context="http://www.springframework.org/schema/context" xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc-3.0.xsd xsi:schemaLocation="http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc-3.0.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd"> http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd">
<context:spring-configured/> <context:spring-configured/>
<context:component-scan base-package="org.springframework.persistence.test"> <context:component-scan base-package="org.springframework.persistence.test">
<context:exclude-filter expression=".*_Roo_.*" type="regex"/> <context:exclude-filter expression=".*_Roo_.*" type="regex"/>
<context:exclude-filter expression="org.springframework.stereotype.Controller" type="annotation"/> <context:exclude-filter expression="org.springframework.stereotype.Controller" type="annotation"/>
</context:component-scan> </context:component-scan>
<!-- Store spanning config --> <!-- Store spanning config -->
<bean class="org.springframework.persistence.StoreSpanning"
factory-method="aspectOf" >
<property name="mappingValidator">
<bean class="org.springframework.persistence.support.SimpleMappingValidator" />
</property>
</bean>
<bean id="entityOperationsLocator" class="org.springframework.persistence.ChainingEntityOperationsLocator" />
<bean class="org.springframework.persistence.ChainingForeignStoreKeyManagerLocator" />
<bean class="org.springframework.persistence.PresentKeyForeignStoreKeyManager" autowire="constructor" />
<bean class="org.springframework.persistence.GeneratedFieldForeignStoreKeyManager" />
<bean class="org.springframework.persistence.document.MongoEntityOperations" > <bean class="org.springframework.persistence.StoreSpanning"
<property name="order" value="5" /> factory-method="aspectOf">
<property name="entityInstantiator"> <property name="mappingValidator">
<bean class="org.springframework.persistence.support.ChangeSetConstructorEntityInstantiator" /> <bean class="org.springframework.persistence.support.SimpleMappingValidator"/>
</property> </property>
<property name="changeSetPersister" ref="mongoChangeSetPersister" /> </bean>
</bean>
<bean class="org.springframework.persistence.EntityManagerJpaEntityOperations" /> <bean id="entityOperationsLocator" class="org.springframework.persistence.ChainingEntityOperationsLocator"/>
<bean class="org.springframework.persistence.support.ChangeSetForeignStoreKeyManager"> <bean class="org.springframework.persistence.ChainingForeignStoreKeyManagerLocator"/>
<property name="fieldDelimiter" value="#"/>
</bean>
<!-- Mongo config --> <bean class="org.springframework.persistence.PresentKeyForeignStoreKeyManager" autowire="constructor"/>
<bean id="mongo" class="org.springframework.data.document.mongodb.MongoFactoryBean">
<property name="host" value="localhost" />
<property name="port" value="27017" />
</bean>
<bean id="mongoTemplate" class="org.springframework.data.document.mongodb.MongoTemplate"> <bean class="org.springframework.persistence.GeneratedFieldForeignStoreKeyManager"/>
<constructor-arg name="mongo" ref="mongo" />
<constructor-arg name="databaseName" value="test" />
</bean>
<bean class="org.springframework.data.document.mongodb.MongoExceptionTranslator" />
<!-- Mongo aspect config --> <bean class="org.springframework.persistence.document.MongoEntityOperations">
<bean class="org.springframework.persistence.document.MongoDocumentBacking" <property name="order" value="5"/>
factory-method="aspectOf"> <property name="entityInstantiator">
<property name="changeSetConfiguration" ref="mongoChangeSetConfiguration"/> <bean class="org.springframework.persistence.support.ChangeSetConstructorEntityInstantiator"/>
</bean> </property>
<bean id ="mongoChangeSetPersister" class="org.springframework.persistence.document.MongoChangeSetPersister" /> <property name="changeSetPersister" ref="mongoChangeSetPersister"/>
<bean id="mongoChangeSetSynchronizer" class="org.springframework.persistence.support.SimpleReflectiveChangeSetSynchronizer" /> </bean>
<bean id="mongoChangeSetConfiguration" class="org.springframework.persistence.support.ChangeSetConfiguration">
<property name="changeSetPersister" ref="mongoChangeSetPersister"/>
<property name="changeSetManager" ref="mongoChangeSetSynchronizer"/>
</bean>
<!-- Needed for ChangeSet persistence -->
<bean id="conversionService" class="org.springframework.context.support.ConversionServiceFactoryBean" />
<jdbc:embedded-database id="dataSource" type="HSQL"> <bean class="org.springframework.persistence.EntityManagerJpaEntityOperations"/>
</jdbc:embedded-database>
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager" >
<property name="entityManagerFactory" ref="entityManagerFactory"/>
</bean>
<tx:annotation-driven mode="aspectj" transaction-manager="transactionManager"/> <bean class="org.springframework.persistence.support.ChangeSetForeignStoreKeyManager">
<property name="fieldDelimiter" value="#"/>
<bean class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean" id="entityManagerFactory"> </bean>
<property name="persistenceUnitName" value="test"/>
<property name="dataSource" ref="dataSource"/> <!-- Mongo config -->
<property name="jpaVendorAdapter"> <bean id="mongo" class="org.springframework.data.document.mongodb.MongoFactoryBean">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter"> <property name="host" value="localhost"/>
<property name="showSql" value="true"/> <property name="port" value="27017"/>
<property name="generateDdl" value="true"/> </bean>
<property name="databasePlatform" value="org.hibernate.dialect.HSQLDialect"/>
</bean> <bean id="mongoTemplate" class="org.springframework.data.document.mongodb.MongoTemplate">
</property> <constructor-arg name="mongo" ref="mongo"/>
</bean> <constructor-arg name="databaseName" value="test"/>
</bean>
<bean class="org.springframework.data.document.mongodb.MongoExceptionTranslator"/>
<!-- Mongo aspect config -->
<bean class="org.springframework.persistence.document.MongoDocumentBacking"
factory-method="aspectOf">
<property name="changeSetConfiguration" ref="mongoChangeSetConfiguration"/>
</bean>
<bean id="mongoChangeSetPersister" class="org.springframework.persistence.document.MongoChangeSetPersister"/>
<bean id="mongoChangeSetSynchronizer"
class="org.springframework.persistence.support.SimpleReflectiveChangeSetSynchronizer"/>
<bean id="mongoChangeSetConfiguration" class="org.springframework.persistence.support.ChangeSetConfiguration">
<property name="changeSetPersister" ref="mongoChangeSetPersister"/>
<property name="changeSetManager" ref="mongoChangeSetSynchronizer"/>
</bean>
<!-- Needed for ChangeSet persistence -->
<bean id="conversionService" class="org.springframework.context.support.ConversionServiceFactoryBean"/>
<jdbc:embedded-database id="dataSource" type="HSQL">
</jdbc:embedded-database>
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory"/>
</bean>
<tx:annotation-driven mode="aspectj" transaction-manager="transactionManager"/>
<bean class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean" id="entityManagerFactory">
<property name="persistenceUnitName" value="test"/>
<property name="dataSource" ref="dataSource"/>
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
<property name="showSql" value="true"/>
<property name="generateDdl" value="true"/>
<property name="databasePlatform" value="org.hibernate.dialect.HSQLDialect"/>
</bean>
</property>
</bean>
</beans> </beans>

View File

@@ -1,19 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="src" output="target/classes" path="src/main/java"/>
<classpathentry kind="src" output="target/test-classes" path="src/test/java"/>
<classpathentry kind="src" output="target/test-classes" path="src/test/resources"/>
<classpathentry kind="src" path="src/main/resources"/>
<classpathentry kind="con" path="org.maven.ide.eclipse.MAVEN2_CLASSPATH_CONTAINER">
<attributes>
<attribute name="org.eclipse.jst.component.nondependency" value=""/>
</attributes>
</classpathentry>
<classpathentry kind="con" path="org.eclipse.jst.j2ee.internal.module.container"/>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6">
<attributes>
<attribute name="owner.project.facets" value="java"/>
</attributes>
</classpathentry>
<classpathentry kind="output" path="target/classes"/>
</classpath>

View File

@@ -1,36 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>spring-data-mongodb</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.wst.common.project.facet.core.builder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.maven.ide.eclipse.maven2Builder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.wst.validation.validationbuilder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.jem.workbench.JavaEMFNature</nature>
<nature>org.eclipse.wst.common.modulecore.ModuleCoreNature</nature>
<nature>org.eclipse.jdt.core.javanature</nature>
<nature>org.maven.ide.eclipse.maven2Nature</nature>
<nature>org.eclipse.wst.common.project.facet.core.nature</nature>
</natures>
</projectDescription>

View File

@@ -1,9 +0,0 @@
#Wed Mar 09 13:51:37 EST 2011
eclipse.preferences.version=1
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
org.eclipse.jdt.core.compiler.compliance=1.6
org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
org.eclipse.jdt.core.compiler.source=1.6

View File

@@ -1,7 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project-modules id="moduleCoreId" project-version="1.5.0">
<wb-module deploy-name="spring-data-mongodb">
<wb-resource deploy-path="/" source-path="/src/main/java"/>
<wb-resource deploy-path="/" source-path="/src/main/resources"/>
</wb-module>
</project-modules>

View File

@@ -1,5 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<faceted-project>
<installed facet="jst.utility" version="1.0"/>
<installed facet="java" version="1.6"/>
</faceted-project>

View File

@@ -1,9 +0,0 @@
#Wed Oct 06 14:49:46 EDT 2010
activeProfiles=
eclipse.preferences.version=1
fullBuildGoals=process-test-resources
includeModules=false
resolveWorkspaceProjects=true
resourceFilterGoals=process-resources resources\:testResources
skipCompilerPlugin=true
version=1

View File

@@ -19,13 +19,13 @@ import org.springframework.dao.DataAccessResourceFailureException;
public class CannotGetMongoDbConnectionException extends DataAccessResourceFailureException { public class CannotGetMongoDbConnectionException extends DataAccessResourceFailureException {
private static final long serialVersionUID = 1172099106475265589L; private static final long serialVersionUID = 1172099106475265589L;
public CannotGetMongoDbConnectionException(String msg, Throwable cause) { public CannotGetMongoDbConnectionException(String msg, Throwable cause) {
super(msg, cause); super(msg, cause);
} }
public CannotGetMongoDbConnectionException(String msg) { public CannotGetMongoDbConnectionException(String msg) {
super(msg); super(msg);
} }
} }

View File

@@ -15,13 +15,12 @@
*/ */
package org.springframework.data.document.mongodb; package org.springframework.data.document.mongodb;
import org.springframework.dao.DataAccessException;
import com.mongodb.DBCollection; import com.mongodb.DBCollection;
import com.mongodb.MongoException; import com.mongodb.MongoException;
import org.springframework.dao.DataAccessException;
public interface CollectionCallback<T> { public interface CollectionCallback<T> {
T doInCollection(DBCollection collection) throws MongoException, DataAccessException; T doInCollection(DBCollection collection) throws MongoException, DataAccessException;
} }

View File

@@ -16,56 +16,56 @@
package org.springframework.data.document.mongodb; package org.springframework.data.document.mongodb;
/** /**
* Provides a simple wrapper to encapsulate the variety of settings you can use when creating a collection. * Provides a simple wrapper to encapsulate the variety of settings you can use when creating a collection.
*
* @author Thomas Risberg
* *
* @author Thomas Risberg
*/ */
public class CollectionOptions { public class CollectionOptions {
private Integer maxDocuments;
private Integer size;
private Boolean capped;
/**
* Constructs a new <code>CollectionOptions</code> instance.
* @param size the collection size in bytes, this data space is preallocated
* @param maxDocuments the maximum number of documents in the collection.
* @param capped true to created a "capped" collection (fixed size with auto-FIFO behavior
* based on insertion order), false otherwise.
*/
public CollectionOptions(Integer size, Integer maxDocuments, Boolean capped) {
super();
this.maxDocuments = maxDocuments;
this.size = size;
this.capped = capped;
}
public Integer getMaxDocuments() { private Integer maxDocuments;
return maxDocuments;
}
public void setMaxDocuments(Integer maxDocuments) { private Integer size;
this.maxDocuments = maxDocuments;
}
public Integer getSize() { private Boolean capped;
return size;
}
public void setSize(Integer size) { /**
this.size = size; * Constructs a new <code>CollectionOptions</code> instance.
} *
* @param size the collection size in bytes, this data space is preallocated
* @param maxDocuments the maximum number of documents in the collection.
* @param capped true to created a "capped" collection (fixed size with auto-FIFO behavior
* based on insertion order), false otherwise.
*/
public CollectionOptions(Integer size, Integer maxDocuments, Boolean capped) {
super();
this.maxDocuments = maxDocuments;
this.size = size;
this.capped = capped;
}
public Integer getMaxDocuments() {
return maxDocuments;
}
public void setMaxDocuments(Integer maxDocuments) {
this.maxDocuments = maxDocuments;
}
public Integer getSize() {
return size;
}
public void setSize(Integer size) {
this.size = size;
}
public Boolean getCapped() {
return capped;
}
public void setCapped(Boolean capped) {
this.capped = capped;
}
public Boolean getCapped() {
return capped;
}
public void setCapped(Boolean capped) {
this.capped = capped;
}
} }

View File

@@ -20,15 +20,15 @@ import com.mongodb.DBCursor;
/** /**
* Simple callback interface to allow customization of a {@link DBCursor}. * Simple callback interface to allow customization of a {@link DBCursor}.
* *
* @author Oliver Gierke * @author Oliver Gierke
*/ */
public interface CursorPreparer { public interface CursorPreparer {
/** /**
* Prepare the given cursor (apply limits, skips and so on). Returns th eprepared cursor. * Prepare the given cursor (apply limits, skips and so on). Returns th eprepared cursor.
* *
* @param cursor * @param cursor
*/ */
DBCursor prepare(DBCursor cursor); DBCursor prepare(DBCursor cursor);
} }

View File

@@ -15,12 +15,11 @@
*/ */
package org.springframework.data.document.mongodb; package org.springframework.data.document.mongodb;
import org.springframework.dao.DataAccessException;
import com.mongodb.DB; import com.mongodb.DB;
import com.mongodb.MongoException; import com.mongodb.MongoException;
import org.springframework.dao.DataAccessException;
public interface DbCallback<T> { public interface DbCallback<T> {
T doInDB(DB db) throws MongoException, DataAccessException; T doInDB(DB db) throws MongoException, DataAccessException;
} }

View File

@@ -3,69 +3,68 @@ package org.springframework.data.document.mongodb;
import java.util.Map; import java.util.Map;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
import com.mongodb.DB;
import org.springframework.transaction.support.ResourceHolderSupport; import org.springframework.transaction.support.ResourceHolderSupport;
import org.springframework.util.Assert; import org.springframework.util.Assert;
import com.mongodb.DB;
class DbHolder extends ResourceHolderSupport { class DbHolder extends ResourceHolderSupport {
private static final Object DEFAULT_KEY = new Object(); private static final Object DEFAULT_KEY = new Object();
private final Map<Object, DB> dbMap = new ConcurrentHashMap<Object, DB>(); private final Map<Object, DB> dbMap = new ConcurrentHashMap<Object, DB>();
public DbHolder(DB db) { public DbHolder(DB db) {
addDB(db); addDB(db);
} }
public DbHolder(Object key, DB db) { public DbHolder(Object key, DB db) {
addDB(key, db); addDB(key, db);
} }
public DB getDB() { public DB getDB() {
return getDB(DEFAULT_KEY); return getDB(DEFAULT_KEY);
} }
public DB getDB(Object key) { public DB getDB(Object key) {
return this.dbMap.get(key); return this.dbMap.get(key);
} }
public DB getAnyDB() { public DB getAnyDB() {
if (!this.dbMap.isEmpty()) { if (!this.dbMap.isEmpty()) {
return this.dbMap.values().iterator().next(); return this.dbMap.values().iterator().next();
} }
return null; return null;
} }
public void addDB(DB session) { public void addDB(DB session) {
addDB(DEFAULT_KEY, session); addDB(DEFAULT_KEY, session);
} }
public void addDB(Object key, DB session) { public void addDB(Object key, DB session) {
Assert.notNull(key, "Key must not be null"); Assert.notNull(key, "Key must not be null");
Assert.notNull(session, "DB must not be null"); Assert.notNull(session, "DB must not be null");
this.dbMap.put(key, session); this.dbMap.put(key, session);
} }
public DB removeDB(Object key) { public DB removeDB(Object key) {
return this.dbMap.remove(key); return this.dbMap.remove(key);
} }
public boolean containsDB(DB session) { public boolean containsDB(DB session) {
return this.dbMap.containsValue(session); return this.dbMap.containsValue(session);
} }
public boolean isEmpty() { public boolean isEmpty() {
return this.dbMap.isEmpty(); return this.dbMap.isEmpty();
} }
public boolean doesNotHoldNonDefaultDB() { public boolean doesNotHoldNonDefaultDB() {
synchronized (this.dbMap) { synchronized (this.dbMap) {
return this.dbMap.isEmpty() || return this.dbMap.isEmpty() ||
(this.dbMap.size() == 1 && this.dbMap.containsKey(DEFAULT_KEY)); (this.dbMap.size() == 1 && this.dbMap.containsKey(DEFAULT_KEY));
} }
} }
} }

View File

@@ -15,80 +15,80 @@
*/ */
package org.springframework.data.document.mongodb; package org.springframework.data.document.mongodb;
import com.mongodb.DB;
import com.mongodb.Mongo;
import org.apache.commons.logging.Log; import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory; import org.apache.commons.logging.LogFactory;
import org.springframework.jmx.export.annotation.ManagedOperation; import org.springframework.jmx.export.annotation.ManagedOperation;
import org.springframework.jmx.export.annotation.ManagedResource; import org.springframework.jmx.export.annotation.ManagedResource;
import com.mongodb.DB;
import com.mongodb.Mongo;
/** /**
* Mongo server administration exposed via JMX annotations * Mongo server administration exposed via JMX annotations
*
* @author Mark Pollack
* *
* @author Mark Pollack
*/ */
@ManagedResource(description="Mongo Admin Operations") @ManagedResource(description = "Mongo Admin Operations")
public class MongoAdmin implements MongoAdminOperations { public class MongoAdmin implements MongoAdminOperations {
/** Logger available to subclasses */ /**
protected final Log logger = LogFactory.getLog(getClass()); * Logger available to subclasses
*/
private Mongo mongo; protected final Log logger = LogFactory.getLog(getClass());
private String username;
private String password;
public MongoAdmin(Mongo mongo) {
this.mongo = mongo;
}
/* (non-Javadoc)
* @see org.springframework.data.document.mongodb.MongoAdminOperations#dropDatabase(java.lang.String)
*/
@ManagedOperation
public void dropDatabase(String databaseName) {
mongo.getDB(databaseName).dropDatabase();
}
/* (non-Javadoc)
* @see org.springframework.data.document.mongodb.MongoAdminOperations#createDatabase(java.lang.String)
*/
@ManagedOperation
public void createDatabase(String databaseName) {
mongo.getDB(databaseName);
}
/* (non-Javadoc)
* @see org.springframework.data.document.mongodb.MongoAdminOperations#getDatabaseStats(java.lang.String)
*/
@ManagedOperation
public String getDatabaseStats(String databaseName) {
return mongo.getDB("testAdminDb").getStats().toString();
}
/**
* Sets the username to use to connect to the Mongo database
*
* @param username The username to use
*/
public void setUsername(String username) {
this.username = username;
}
/** private Mongo mongo;
* Sets the password to use to authenticate with the Mongo database. private String username;
* private String password;
* @param password The password to use
*/ public MongoAdmin(Mongo mongo) {
public void setPassword(String password) { this.mongo = mongo;
}
this.password = password;
} /* (non-Javadoc)
* @see org.springframework.data.document.mongodb.MongoAdminOperations#dropDatabase(java.lang.String)
*/
public DB getDb(String databaseName) { @ManagedOperation
return MongoDbUtils.getDB(mongo, databaseName, username, password == null ? null : password.toCharArray()); public void dropDatabase(String databaseName) {
} mongo.getDB(databaseName).dropDatabase();
}
/* (non-Javadoc)
* @see org.springframework.data.document.mongodb.MongoAdminOperations#createDatabase(java.lang.String)
*/
@ManagedOperation
public void createDatabase(String databaseName) {
mongo.getDB(databaseName);
}
/* (non-Javadoc)
* @see org.springframework.data.document.mongodb.MongoAdminOperations#getDatabaseStats(java.lang.String)
*/
@ManagedOperation
public String getDatabaseStats(String databaseName) {
return mongo.getDB("testAdminDb").getStats().toString();
}
/**
* Sets the username to use to connect to the Mongo database
*
* @param username The username to use
*/
public void setUsername(String username) {
this.username = username;
}
/**
* Sets the password to use to authenticate with the Mongo database.
*
* @param password The password to use
*/
public void setPassword(String password) {
this.password = password;
}
public DB getDb(String databaseName) {
return MongoDbUtils.getDB(mongo, databaseName, username, password == null ? null : password.toCharArray());
}
} }

View File

@@ -4,13 +4,13 @@ import org.springframework.jmx.export.annotation.ManagedOperation;
public interface MongoAdminOperations { public interface MongoAdminOperations {
@ManagedOperation @ManagedOperation
public abstract void dropDatabase(String databaseName); public abstract void dropDatabase(String databaseName);
@ManagedOperation @ManagedOperation
public abstract void createDatabase(String databaseName); public abstract void createDatabase(String databaseName);
@ManagedOperation @ManagedOperation
public abstract String getDatabaseStats(String databaseName); public abstract String getDatabaseStats(String databaseName);
} }

View File

@@ -16,151 +16,148 @@
package org.springframework.data.document.mongodb; package org.springframework.data.document.mongodb;
import com.mongodb.DB;
import com.mongodb.Mongo;
import org.apache.commons.logging.Log; import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory; import org.apache.commons.logging.LogFactory;
import org.springframework.transaction.support.TransactionSynchronizationManager; import org.springframework.transaction.support.TransactionSynchronizationManager;
import org.springframework.util.Assert; import org.springframework.util.Assert;
import com.mongodb.DB;
import com.mongodb.Mongo;
/** /**
* Helper class featuring helper methods for internal MongoDb classes. * Helper class featuring helper methods for internal MongoDb classes.
* * <p/>
* <p>Mainly intended for internal use within the framework. * <p>Mainly intended for internal use within the framework.
* *
* @author Thomas Risberg * @author Thomas Risberg
* @author Graeme Rocher * @author Graeme Rocher
* @author Oliver Gierke * @author Oliver Gierke
*
* @since 1.0 * @since 1.0
*/ */
public abstract class MongoDbUtils { public abstract class MongoDbUtils {
private static final Log LOGGER = LogFactory.getLog(MongoDbUtils.class); private static final Log LOGGER = LogFactory.getLog(MongoDbUtils.class);
/**
* Private constructor to prevent instantiation.
*/
private MongoDbUtils() {
}
/** /**
* Obtains a {@link DB} connection for the given {@link Mongo} instance and database name * Private constructor to prevent instantiation.
* */
* @param mongo The {@link Mongo} instance private MongoDbUtils() {
* @param databaseName The database name
* @return The {@link DB} connection
*/
public static DB getDB(Mongo mongo, String databaseName) {
return doGetDB(mongo, databaseName,null,null, true);
}
/** }
*
* Obtains a {@link DB} connection for the given {@link Mongo} instance and database name
*
* @param mongo The {@link Mongo} instance
* @param databaseName The database name
* @param username The username to authenticate with
* @param password The password to authenticate with
* @return The {@link DB} connection
*/
public static DB getDB(Mongo mongo, String databaseName, String username, char[] password) {
return doGetDB(mongo, databaseName,username,password, true);
}
public static DB doGetDB(Mongo mongo, String databaseName, String username, char[] password, boolean allowCreate) { /**
Assert.notNull(mongo, "No Mongo instance specified"); * Obtains a {@link DB} connection for the given {@link Mongo} instance and database name
*
* @param mongo The {@link Mongo} instance
* @param databaseName The database name
* @return The {@link DB} connection
*/
public static DB getDB(Mongo mongo, String databaseName) {
return doGetDB(mongo, databaseName, null, null, true);
}
DbHolder dbHolder = (DbHolder) TransactionSynchronizationManager.getResource(mongo); /**
if (dbHolder != null && !dbHolder.isEmpty()) { * Obtains a {@link DB} connection for the given {@link Mongo} instance and database name
// pre-bound Mongo DB *
DB db = null; * @param mongo The {@link Mongo} instance
if (TransactionSynchronizationManager.isSynchronizationActive() && * @param databaseName The database name
dbHolder.doesNotHoldNonDefaultDB()) { * @param username The username to authenticate with
// Spring transaction management is active -> * @param password The password to authenticate with
db = dbHolder.getDB(); * @return The {@link DB} connection
if (db != null && !dbHolder.isSynchronizedWithTransaction()) { */
LOGGER.debug("Registering Spring transaction synchronization for existing Mongo DB"); public static DB getDB(Mongo mongo, String databaseName, String username, char[] password) {
TransactionSynchronizationManager.registerSynchronization(new MongoSynchronization(dbHolder, mongo)); return doGetDB(mongo, databaseName, username, password, true);
dbHolder.setSynchronizedWithTransaction(true); }
}
}
if (db != null) {
return db;
}
}
LOGGER.debug("Opening Mongo DB"); public static DB doGetDB(Mongo mongo, String databaseName, String username, char[] password, boolean allowCreate) {
DB db = mongo.getDB(databaseName); Assert.notNull(mongo, "No Mongo instance specified");
boolean creadentialsGiven = username != null && password != null;
if(creadentialsGiven && !db.authenticate(username, password)) {
throw new CannotGetMongoDbConnectionException("Failed to authenticate with Mongo using the given credentials");
}
// Use same Session for further Mongo actions within the transaction.
// Thread object will get removed by synchronization at transaction completion.
if (TransactionSynchronizationManager.isSynchronizationActive()) {
// We're within a Spring-managed transaction, possibly from JtaTransactionManager.
LOGGER.debug("Registering Spring transaction synchronization for new Hibernate Session");
DbHolder holderToUse = dbHolder;
if (holderToUse == null) {
holderToUse = new DbHolder(db);
}
else {
holderToUse.addDB(db);
}
TransactionSynchronizationManager.registerSynchronization(new MongoSynchronization(holderToUse, mongo));
holderToUse.setSynchronizedWithTransaction(true);
if (holderToUse != dbHolder) {
TransactionSynchronizationManager.bindResource(mongo, holderToUse);
}
}
// Check whether we are allowed to return the DB. DbHolder dbHolder = (DbHolder) TransactionSynchronizationManager.getResource(mongo);
if (!allowCreate && !isDBTransactional(db, mongo)) { if (dbHolder != null && !dbHolder.isEmpty()) {
throw new IllegalStateException("No Mongo DB bound to thread, " + // pre-bound Mongo DB
"and configuration does not allow creation of non-transactional one here"); DB db = null;
} if (TransactionSynchronizationManager.isSynchronizationActive() &&
dbHolder.doesNotHoldNonDefaultDB()) {
// Spring transaction management is active ->
db = dbHolder.getDB();
if (db != null && !dbHolder.isSynchronizedWithTransaction()) {
LOGGER.debug("Registering Spring transaction synchronization for existing Mongo DB");
TransactionSynchronizationManager.registerSynchronization(new MongoSynchronization(dbHolder, mongo));
dbHolder.setSynchronizedWithTransaction(true);
}
}
if (db != null) {
return db;
}
}
return db; LOGGER.debug("Opening Mongo DB");
} DB db = mongo.getDB(databaseName);
boolean creadentialsGiven = username != null && password != null;
/** if (creadentialsGiven && !db.authenticate(username, password)) {
* Return whether the given DB instance is transactional, that is, throw new CannotGetMongoDbConnectionException("Failed to authenticate with Mongo using the given credentials");
* bound to the current thread by Spring's transaction facilities. }
* @param db the DB to check
* @param mongo the Mongo instance that the DB was created with // Use same Session for further Mongo actions within the transaction.
* (may be <code>null</code>) // Thread object will get removed by synchronization at transaction completion.
* @return whether the DB is transactional if (TransactionSynchronizationManager.isSynchronizationActive()) {
*/ // We're within a Spring-managed transaction, possibly from JtaTransactionManager.
public static boolean isDBTransactional(DB db, Mongo mongo) { LOGGER.debug("Registering Spring transaction synchronization for new Hibernate Session");
if (mongo == null) { DbHolder holderToUse = dbHolder;
return false; if (holderToUse == null) {
} holderToUse = new DbHolder(db);
DbHolder dbHolder = } else {
(DbHolder) TransactionSynchronizationManager.getResource(mongo); holderToUse.addDB(db);
return (dbHolder != null && dbHolder.containsDB(db)); }
} TransactionSynchronizationManager.registerSynchronization(new MongoSynchronization(holderToUse, mongo));
holderToUse.setSynchronizedWithTransaction(true);
/** if (holderToUse != dbHolder) {
* Perform actual closing of the Mongo DB object, TransactionSynchronizationManager.bindResource(mongo, holderToUse);
* catching and logging any cleanup exceptions thrown. }
* @param db the DB to close (may be <code>null</code>) }
*/
public static void closeDB(DB db) { // Check whether we are allowed to return the DB.
if (db != null) { if (!allowCreate && !isDBTransactional(db, mongo)) {
LOGGER.debug("Closing Mongo DB object"); throw new IllegalStateException("No Mongo DB bound to thread, " +
try { "and configuration does not allow creation of non-transactional one here");
db.requestDone(); }
}
catch (Throwable ex) { return db;
LOGGER.debug("Unexpected exception on closing Mongo DB object", ex); }
}
}
} /**
* Return whether the given DB instance is transactional, that is,
* bound to the current thread by Spring's transaction facilities.
*
* @param db the DB to check
* @param mongo the Mongo instance that the DB was created with
* (may be <code>null</code>)
* @return whether the DB is transactional
*/
public static boolean isDBTransactional(DB db, Mongo mongo) {
if (mongo == null) {
return false;
}
DbHolder dbHolder =
(DbHolder) TransactionSynchronizationManager.getResource(mongo);
return (dbHolder != null && dbHolder.containsDB(db));
}
/**
* Perform actual closing of the Mongo DB object,
* catching and logging any cleanup exceptions thrown.
*
* @param db the DB to close (may be <code>null</code>)
*/
public static void closeDB(DB db) {
if (db != null) {
LOGGER.debug("Closing Mongo DB object");
try {
db.requestDone();
} catch (Throwable ex) {
LOGGER.debug("Unexpected exception on closing Mongo DB object", ex);
}
}
}
} }

View File

@@ -15,52 +15,50 @@
*/ */
package org.springframework.data.document.mongodb; package org.springframework.data.document.mongodb;
import com.mongodb.MongoException;
import com.mongodb.MongoException.DuplicateKey;
import com.mongodb.MongoException.Network;
import org.springframework.dao.DataAccessException; import org.springframework.dao.DataAccessException;
import org.springframework.dao.DataAccessResourceFailureException; import org.springframework.dao.DataAccessResourceFailureException;
import org.springframework.dao.DataIntegrityViolationException; import org.springframework.dao.DataIntegrityViolationException;
import org.springframework.dao.support.PersistenceExceptionTranslator; import org.springframework.dao.support.PersistenceExceptionTranslator;
import org.springframework.data.document.UncategorizedDocumentStoreException; import org.springframework.data.document.UncategorizedDocumentStoreException;
import com.mongodb.MongoException;
import com.mongodb.MongoException.DuplicateKey;
import com.mongodb.MongoException.Network;
/** /**
* Simple {@link PersistenceExceptionTranslator} for Mongo. Convert the given runtime exception to an appropriate * Simple {@link PersistenceExceptionTranslator} for Mongo. Convert the given runtime exception to an appropriate
* exception from the {@code org.springframework.dao} hierarchy. Return {@literal null} if no translation is * exception from the {@code org.springframework.dao} hierarchy. Return {@literal null} if no translation is
* appropriate: any other exception may have resulted from user code, and should not be translated. * appropriate: any other exception may have resulted from user code, and should not be translated.
*
* @param ex runtime exception that occurred * @param ex runtime exception that occurred
* @return the corresponding DataAccessException instance, or {@literal null} if the exception should not be translated
*
*
* @author Oliver Gierke * @author Oliver Gierke
* @return the corresponding DataAccessException instance, or {@literal null} if the exception should not be translated
*/ */
public class MongoExceptionTranslator implements PersistenceExceptionTranslator { public class MongoExceptionTranslator implements PersistenceExceptionTranslator {
/* /*
* (non-Javadoc) * (non-Javadoc)
* *
* @see org.springframework.dao.support.PersistenceExceptionTranslator# * @see org.springframework.dao.support.PersistenceExceptionTranslator#
* translateExceptionIfPossible(java.lang.RuntimeException) * translateExceptionIfPossible(java.lang.RuntimeException)
*/ */
public DataAccessException translateExceptionIfPossible(RuntimeException ex) { public DataAccessException translateExceptionIfPossible(RuntimeException ex) {
// Check for well-known MongoException subclasses. // Check for well-known MongoException subclasses.
// All other MongoExceptions // All other MongoExceptions
if (ex instanceof DuplicateKey) { if (ex instanceof DuplicateKey) {
return new DataIntegrityViolationException(ex.getMessage(), ex); return new DataIntegrityViolationException(ex.getMessage(), ex);
} }
if (ex instanceof Network) { if (ex instanceof Network) {
return new DataAccessResourceFailureException(ex.getMessage(), ex); return new DataAccessResourceFailureException(ex.getMessage(), ex);
} }
if (ex instanceof MongoException) { if (ex instanceof MongoException) {
return new UncategorizedDocumentStoreException(ex.getMessage(), ex); return new UncategorizedDocumentStoreException(ex.getMessage(), ex);
} }
// If we get here, we have an exception that resulted from user code, // If we get here, we have an exception that resulted from user code,
// rather than the persistence provider, so we return null to indicate // rather than the persistence provider, so we return null to indicate
// that translation should not occur. // that translation should not occur.
return null; return null;
} }
} }

View File

@@ -18,6 +18,9 @@ package org.springframework.data.document.mongodb;
import java.util.List; import java.util.List;
import com.mongodb.Mongo;
import com.mongodb.MongoOptions;
import com.mongodb.ServerAddress;
import org.apache.commons.logging.Log; import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory; import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.FactoryBean; import org.springframework.beans.factory.FactoryBean;
@@ -26,112 +29,103 @@ import org.springframework.dao.DataAccessException;
import org.springframework.dao.support.PersistenceExceptionTranslator; import org.springframework.dao.support.PersistenceExceptionTranslator;
import org.springframework.util.Assert; import org.springframework.util.Assert;
import com.mongodb.Mongo;
import com.mongodb.MongoOptions;
import com.mongodb.ServerAddress;
/** /**
* Convenient factory for configuring MongoDB. * Convenient factory for configuring MongoDB.
* *
* @author Thomas Risberg * @author Thomas Risberg
* @author Graeme Rocher * @author Graeme Rocher
*
* @since 1.0 * @since 1.0
*/ */
public class MongoFactoryBean implements FactoryBean<Mongo>, InitializingBean, PersistenceExceptionTranslator { public class MongoFactoryBean implements FactoryBean<Mongo>, InitializingBean, PersistenceExceptionTranslator {
/**
* Logger, available to subclasses.
*/
protected final Log logger = LogFactory.getLog(getClass());
private Mongo mongo; /**
private MongoOptions mongoOptions; * Logger, available to subclasses.
private String host; */
private Integer port; protected final Log logger = LogFactory.getLog(getClass());
private List<ServerAddress> replicaSetSeeds;
private List<ServerAddress> replicaPair;
private PersistenceExceptionTranslator exceptionTranslator = new MongoExceptionTranslator(); private Mongo mongo;
private MongoOptions mongoOptions;
public void setMongoOptions(MongoOptions mongoOptions) { private String host;
this.mongoOptions = mongoOptions; private Integer port;
} private List<ServerAddress> replicaSetSeeds;
private List<ServerAddress> replicaPair;
public void setReplicaSetSeeds(List<ServerAddress> replicaSetSeeds) { private PersistenceExceptionTranslator exceptionTranslator = new MongoExceptionTranslator();
this.replicaSetSeeds = replicaSetSeeds;
}
public void setReplicaPair(List<ServerAddress> replicaPair) {
this.replicaPair = replicaPair;
}
public void setHost(String host) { public void setMongoOptions(MongoOptions mongoOptions) {
this.host = host; this.mongoOptions = mongoOptions;
} }
public void setPort(int port) { public void setReplicaSetSeeds(List<ServerAddress> replicaSetSeeds) {
this.port = port; this.replicaSetSeeds = replicaSetSeeds;
} }
public PersistenceExceptionTranslator getExceptionTranslator() { public void setReplicaPair(List<ServerAddress> replicaPair) {
return exceptionTranslator; this.replicaPair = replicaPair;
} }
public void setExceptionTranslator( public void setHost(String host) {
PersistenceExceptionTranslator exceptionTranslator) { this.host = host;
this.exceptionTranslator = exceptionTranslator; }
}
public Mongo getObject() throws Exception { public void setPort(int port) {
Assert.notNull(mongo, "Mongo must not be null"); this.port = port;
return mongo; }
}
public Class<? extends Mongo> getObjectType() { public PersistenceExceptionTranslator getExceptionTranslator() {
return Mongo.class; return exceptionTranslator;
} }
public boolean isSingleton() { public void setExceptionTranslator(
return false; PersistenceExceptionTranslator exceptionTranslator) {
} this.exceptionTranslator = exceptionTranslator;
}
public void afterPropertiesSet() throws Exception { public Mongo getObject() throws Exception {
// apply defaults - convenient when used to configure for tests Assert.notNull(mongo, "Mongo must not be null");
// in an application context return mongo;
if (mongo == null) { }
if (host == null) {
logger.warn("Property host not specified. Using default configuration");
mongo = new Mongo();
}
else {
ServerAddress defaultOptions = new ServerAddress();
if(mongoOptions == null) mongoOptions = new MongoOptions();
if(replicaPair != null) {
if(replicaPair.size() < 2) {
throw new CannotGetMongoDbConnectionException("A replica pair must have two server entries");
}
mongo = new Mongo(replicaPair.get(0), replicaPair.get(1), mongoOptions);
}
else if(replicaSetSeeds != null) {
mongo = new Mongo(replicaSetSeeds, mongoOptions);
}
else {
String mongoHost = host != null ? host : defaultOptions.getHost();
if(port != null) {
mongo = new Mongo(new ServerAddress(mongoHost, port), mongoOptions);
}
else {
mongo = new Mongo(mongoHost, mongoOptions);
}
}
}
}
}
public DataAccessException translateExceptionIfPossible(RuntimeException ex) { public Class<? extends Mongo> getObjectType() {
return exceptionTranslator.translateExceptionIfPossible(ex); return Mongo.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 (mongo == null) {
if (host == null) {
logger.warn("Property host not specified. Using default configuration");
mongo = new Mongo();
} else {
ServerAddress defaultOptions = new ServerAddress();
if (mongoOptions == null) mongoOptions = new MongoOptions();
if (replicaPair != null) {
if (replicaPair.size() < 2) {
throw new CannotGetMongoDbConnectionException("A replica pair must have two server entries");
}
mongo = new Mongo(replicaPair.get(0), replicaPair.get(1), mongoOptions);
} else if (replicaSetSeeds != null) {
mongo = new Mongo(replicaSetSeeds, mongoOptions);
} else {
String mongoHost = host != null ? host : defaultOptions.getHost();
if (port != null) {
mongo = new Mongo(new ServerAddress(mongoHost, port), mongoOptions);
} else {
mongo = new Mongo(mongoHost, mongoOptions);
}
}
}
}
}
public DataAccessException translateExceptionIfPossible(RuntimeException ex) {
return exceptionTranslator.translateExceptionIfPossible(ex);
}
} }

View File

@@ -15,123 +15,120 @@
*/ */
package org.springframework.data.document.mongodb; package org.springframework.data.document.mongodb;
import com.mongodb.MongoOptions;
import org.springframework.beans.factory.FactoryBean; import org.springframework.beans.factory.FactoryBean;
import org.springframework.beans.factory.InitializingBean; import org.springframework.beans.factory.InitializingBean;
import com.mongodb.MongoOptions;
/** /**
* A factory bean for consruction a MongoOptions instance * A factory bean for consruction a MongoOptions instance
*
* @author Graeme Rocher
* *
* @author Graeme Rocher
*/ */
public class MongoOptionsFactoryBean implements FactoryBean<MongoOptions>, InitializingBean{ public class MongoOptionsFactoryBean implements FactoryBean<MongoOptions>, InitializingBean {
private static final MongoOptions MONGO_OPTIONS = new MongoOptions(); private static final MongoOptions MONGO_OPTIONS = new MongoOptions();
/** /**
number of connections allowed per host * number of connections allowed per host
will block if run out * will block if run out
*/ */
private int connectionsPerHost = MONGO_OPTIONS.connectionsPerHost; private int connectionsPerHost = MONGO_OPTIONS.connectionsPerHost;
/** /**
multiplier for connectionsPerHost for # of threads that can block * multiplier for connectionsPerHost for # of threads that can block
if connectionsPerHost is 10, and threadsAllowedToBlockForConnectionMultiplier is 5, * if connectionsPerHost is 10, and threadsAllowedToBlockForConnectionMultiplier is 5,
then 50 threads can block * then 50 threads can block
more than that and an exception will be throw * more than that and an exception will be throw
*/ */
private int threadsAllowedToBlockForConnectionMultiplier = MONGO_OPTIONS.threadsAllowedToBlockForConnectionMultiplier; private int threadsAllowedToBlockForConnectionMultiplier = MONGO_OPTIONS.threadsAllowedToBlockForConnectionMultiplier;
/**
* max wait time of a blocking thread for a connection
*/
private int maxWaitTime = MONGO_OPTIONS.maxWaitTime;
/** /**
connect timeout in milliseconds. 0 is default and infinite * max wait time of a blocking thread for a connection
*/ */
private int connectTimeout = MONGO_OPTIONS.connectTimeout; private int maxWaitTime = MONGO_OPTIONS.maxWaitTime;
/** /**
socket timeout. 0 is default and infinite * connect timeout in milliseconds. 0 is default and infinite
*/ */
private int socketTimeout = MONGO_OPTIONS.socketTimeout; private int connectTimeout = MONGO_OPTIONS.connectTimeout;
/**
this controls whether or not on a connect, the system retries automatically
*/
private boolean autoConnectRetry = MONGO_OPTIONS.autoConnectRetry;
/**
number of connections allowed per host
will block if run out
*/
public void setConnectionsPerHost(int connectionsPerHost) {
this.connectionsPerHost = connectionsPerHost;
}
/** /**
multiplier for connectionsPerHost for # of threads that can block * socket timeout. 0 is default and infinite
if connectionsPerHost is 10, and threadsAllowedToBlockForConnectionMultiplier is 5, */
then 50 threads can block private int socketTimeout = MONGO_OPTIONS.socketTimeout;
more than that and an exception will be throw
*/
public void setThreadsAllowedToBlockForConnectionMultiplier(
int threadsAllowedToBlockForConnectionMultiplier) {
this.threadsAllowedToBlockForConnectionMultiplier = threadsAllowedToBlockForConnectionMultiplier;
}
/** /**
* max wait time of a blocking thread for a connection * this controls whether or not on a connect, the system retries automatically
*/ */
public void setMaxWaitTime(int maxWaitTime) { private boolean autoConnectRetry = MONGO_OPTIONS.autoConnectRetry;
this.maxWaitTime = maxWaitTime;
}
/**
connect timeout in milliseconds. 0 is default and infinite
*/
public void setConnectTimeout(int connectTimeout) {
this.connectTimeout = connectTimeout;
}
/** /**
socket timeout. 0 is default and infinite * number of connections allowed per host
*/ * will block if run out
public void setSocketTimeout(int socketTimeout) { */
this.socketTimeout = socketTimeout; public void setConnectionsPerHost(int connectionsPerHost) {
} this.connectionsPerHost = connectionsPerHost;
}
/** /**
this controls whether or not on a connect, the system retries automatically * multiplier for connectionsPerHost for # of threads that can block
*/ * if connectionsPerHost is 10, and threadsAllowedToBlockForConnectionMultiplier is 5,
public void setAutoConnectRetry(boolean autoConnectRetry) { * then 50 threads can block
this.autoConnectRetry = autoConnectRetry; * more than that and an exception will be throw
} */
public void setThreadsAllowedToBlockForConnectionMultiplier(
int threadsAllowedToBlockForConnectionMultiplier) {
this.threadsAllowedToBlockForConnectionMultiplier = threadsAllowedToBlockForConnectionMultiplier;
}
public void afterPropertiesSet() { /**
MONGO_OPTIONS.connectionsPerHost = connectionsPerHost; * max wait time of a blocking thread for a connection
MONGO_OPTIONS.threadsAllowedToBlockForConnectionMultiplier = threadsAllowedToBlockForConnectionMultiplier; */
MONGO_OPTIONS.maxWaitTime = maxWaitTime; public void setMaxWaitTime(int maxWaitTime) {
MONGO_OPTIONS.connectTimeout = connectTimeout; this.maxWaitTime = maxWaitTime;
MONGO_OPTIONS.socketTimeout = socketTimeout; }
MONGO_OPTIONS.autoConnectRetry = autoConnectRetry;
}
public MongoOptions getObject() { /**
return MONGO_OPTIONS; * connect timeout in milliseconds. 0 is default and infinite
} */
public void setConnectTimeout(int connectTimeout) {
this.connectTimeout = connectTimeout;
}
public Class<?> getObjectType() { /**
return MongoOptions.class; * socket timeout. 0 is default and infinite
} */
public void setSocketTimeout(int socketTimeout) {
this.socketTimeout = socketTimeout;
}
public boolean isSingleton() { /**
return true; * this controls whether or not on a connect, the system retries automatically
} */
public void setAutoConnectRetry(boolean autoConnectRetry) {
this.autoConnectRetry = autoConnectRetry;
}
public void afterPropertiesSet() {
MONGO_OPTIONS.connectionsPerHost = connectionsPerHost;
MONGO_OPTIONS.threadsAllowedToBlockForConnectionMultiplier = threadsAllowedToBlockForConnectionMultiplier;
MONGO_OPTIONS.maxWaitTime = maxWaitTime;
MONGO_OPTIONS.connectTimeout = connectTimeout;
MONGO_OPTIONS.socketTimeout = socketTimeout;
MONGO_OPTIONS.autoConnectRetry = autoConnectRetry;
}
public MongoOptions getObject() {
return MONGO_OPTIONS;
}
public Class<?> getObjectType() {
return MongoOptions.class;
}
public boolean isSingleton() {
return true;
}
} }

View File

@@ -15,16 +15,16 @@
*/ */
package org.springframework.data.document.mongodb; package org.springframework.data.document.mongodb;
import org.bson.types.ObjectId;
import org.springframework.beans.BeanUtils;
import org.springframework.util.Assert;
import java.beans.PropertyDescriptor; import java.beans.PropertyDescriptor;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.lang.reflect.Type; import java.lang.reflect.Type;
import java.math.BigInteger; import java.math.BigInteger;
import java.util.*; import java.util.*;
import org.bson.types.ObjectId;
import org.springframework.beans.BeanUtils;
import org.springframework.util.Assert;
/** /**
* An iterable of {@link MongoPropertyDescriptor}s that allows dedicated access to the {@link MongoPropertyDescriptor} * An iterable of {@link MongoPropertyDescriptor}s that allows dedicated access to the {@link MongoPropertyDescriptor}
* that captures the id-property. * that captures the id-property.

View File

@@ -5,8 +5,8 @@ import org.springframework.transaction.support.ResourceHolderSynchronization;
class MongoSynchronization extends ResourceHolderSynchronization<ResourceHolder, Object> { class MongoSynchronization extends ResourceHolderSynchronization<ResourceHolder, Object> {
public MongoSynchronization(ResourceHolder resourceHolder, public MongoSynchronization(ResourceHolder resourceHolder,
Object resourceKey) { Object resourceKey) {
super(resourceHolder, resourceKey); super(resourceHolder, resourceKey);
} }
} }

View File

@@ -19,19 +19,19 @@ import com.mongodb.DBObject;
/** /**
* A MongoWriter is responsible for converting an object of type T to the native MongoDB representation DBObject. * A MongoWriter is responsible for converting an object of type T to the native MongoDB representation DBObject.
*
* @author Mark Pollack
* @author Thomas Risberg
* *
* @param <T> the type of the object to convert to a DBObject * @param <T> the type of the object to convert to a DBObject
* @author Mark Pollack
* @author Thomas Risberg
*/ */
public interface MongoWriter<T> { public interface MongoWriter<T> {
/** /**
* Write the given object of type T to the native MongoDB object representation DBObject. * Write the given object of type T to the native MongoDB object representation DBObject.
* @param t The object to convert to a DBObject *
* @param dbo The DBObject to use for writing. * @param t The object to convert to a DBObject
*/ * @param dbo The DBObject to use for writing.
void write(T t, DBObject dbo); */
void write(T t, DBObject dbo);
} }

View File

@@ -1,5 +1,5 @@
package org.springframework.data.document.mongodb; package org.springframework.data.document.mongodb;
public enum WriteResultChecking { public enum WriteResultChecking {
NONE, LOG, EXCEPTION NONE, LOG, EXCEPTION
} }

View File

@@ -22,55 +22,48 @@ import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.xml.BeanDefinitionParser; import org.springframework.beans.factory.xml.BeanDefinitionParser;
import org.springframework.beans.factory.xml.ParserContext; import org.springframework.beans.factory.xml.ParserContext;
import org.springframework.data.document.mongodb.MongoAdmin; import org.springframework.data.document.mongodb.MongoAdmin;
import org.springframework.data.document.mongodb.monitor.AssertMetrics; import org.springframework.data.document.mongodb.monitor.*;
import org.springframework.data.document.mongodb.monitor.BackgroundFlushingMetrics;
import org.springframework.data.document.mongodb.monitor.BtreeIndexCounters;
import org.springframework.data.document.mongodb.monitor.ConnectionMetrics;
import org.springframework.data.document.mongodb.monitor.GlobalLockMetrics;
import org.springframework.data.document.mongodb.monitor.MemoryMetrics;
import org.springframework.data.document.mongodb.monitor.OperationCounters;
import org.springframework.data.document.mongodb.monitor.ServerInfo;
import org.springframework.util.StringUtils; import org.springframework.util.StringUtils;
import org.w3c.dom.Element; import org.w3c.dom.Element;
public class MongoJmxParser implements BeanDefinitionParser { public class MongoJmxParser implements BeanDefinitionParser {
public BeanDefinition parse(Element element, ParserContext parserContext) { public BeanDefinition parse(Element element, ParserContext parserContext) {
String name = element.getAttribute("mongo-ref"); String name = element.getAttribute("mongo-ref");
if (!StringUtils.hasText(name)) { if (!StringUtils.hasText(name)) {
name = "mongo"; name = "mongo";
} }
registerJmxComponents(name, element, parserContext); registerJmxComponents(name, element, parserContext);
return null; return null;
} }
protected void registerJmxComponents(String mongoRefName, Element element, ParserContext parserContext) { protected void registerJmxComponents(String mongoRefName, Element element, ParserContext parserContext) {
Object eleSource = parserContext.extractSource(element); Object eleSource = parserContext.extractSource(element);
CompositeComponentDefinition compositeDef = new CompositeComponentDefinition(element.getTagName(), eleSource); CompositeComponentDefinition compositeDef = new CompositeComponentDefinition(element.getTagName(), eleSource);
createBeanDefEntry(AssertMetrics.class, compositeDef, mongoRefName, eleSource, parserContext); createBeanDefEntry(AssertMetrics.class, compositeDef, mongoRefName, eleSource, parserContext);
createBeanDefEntry(BackgroundFlushingMetrics.class, compositeDef, mongoRefName, eleSource, parserContext); createBeanDefEntry(BackgroundFlushingMetrics.class, compositeDef, mongoRefName, eleSource, parserContext);
createBeanDefEntry(BtreeIndexCounters.class, compositeDef, mongoRefName, eleSource, parserContext); createBeanDefEntry(BtreeIndexCounters.class, compositeDef, mongoRefName, eleSource, parserContext);
createBeanDefEntry(ConnectionMetrics.class, compositeDef, mongoRefName, eleSource, parserContext); createBeanDefEntry(ConnectionMetrics.class, compositeDef, mongoRefName, eleSource, parserContext);
createBeanDefEntry(GlobalLockMetrics.class, compositeDef, mongoRefName, eleSource, parserContext); createBeanDefEntry(GlobalLockMetrics.class, compositeDef, mongoRefName, eleSource, parserContext);
createBeanDefEntry(MemoryMetrics.class, compositeDef, mongoRefName, eleSource, parserContext); createBeanDefEntry(MemoryMetrics.class, compositeDef, mongoRefName, eleSource, parserContext);
createBeanDefEntry(OperationCounters.class, compositeDef, mongoRefName, eleSource, parserContext); createBeanDefEntry(OperationCounters.class, compositeDef, mongoRefName, eleSource, parserContext);
createBeanDefEntry(ServerInfo.class, compositeDef, mongoRefName, eleSource, parserContext); createBeanDefEntry(ServerInfo.class, compositeDef, mongoRefName, eleSource, parserContext);
createBeanDefEntry(MongoAdmin.class, compositeDef, mongoRefName, eleSource, parserContext); createBeanDefEntry(MongoAdmin.class, compositeDef, mongoRefName, eleSource, parserContext);
parserContext.registerComponent(compositeDef); parserContext.registerComponent(compositeDef);
} }
protected void createBeanDefEntry(Class clazz, CompositeComponentDefinition compositeDef, String mongoRefName, Object eleSource, ParserContext parserContext) {
BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(clazz);
builder.getRawBeanDefinition().setSource(eleSource);
builder.addConstructorArgReference(mongoRefName);
BeanDefinition assertDef = builder.getBeanDefinition();
String assertName = parserContext.getReaderContext().registerWithGeneratedName(assertDef);
compositeDef.addNestedComponent(new BeanComponentDefinition(assertDef, assertName));
}
protected void createBeanDefEntry(Class clazz, CompositeComponentDefinition compositeDef, String mongoRefName, Object eleSource, ParserContext parserContext) {
BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(clazz);
builder.getRawBeanDefinition().setSource(eleSource);
builder.addConstructorArgReference(mongoRefName);
BeanDefinition assertDef = builder.getBeanDefinition();
String assertName = parserContext.getReaderContext().registerWithGeneratedName(assertDef);
compositeDef.addNestedComponent(new BeanComponentDefinition(assertDef, assertName));
}
} }

Some files were not shown because too many files have changed in this diff Show More