diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/MongoParsingUtils.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/MongoParsingUtils.java index 6613f7066..4ab0b2fc4 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/MongoParsingUtils.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/config/MongoParsingUtils.java @@ -1,5 +1,5 @@ /* - * Copyright 2011-2012 the original author or authors. + * Copyright 2011-2013 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. @@ -33,6 +33,7 @@ import org.w3c.dom.Element; * * @author Mark Pollack * @author Oliver Gierke + * @author Thomas Darimont */ abstract class MongoParsingUtils { @@ -79,6 +80,8 @@ abstract class MongoParsingUtils { setPropertyValue(optionsDefBuilder, optionsElement, "write-timeout", "writeTimeout"); setPropertyValue(optionsDefBuilder, optionsElement, "write-fsync", "writeFsync"); setPropertyValue(optionsDefBuilder, optionsElement, "slave-ok", "slaveOk"); + setPropertyValue(optionsDefBuilder, optionsElement, "ssl", "ssl"); + setPropertyReference(optionsDefBuilder, optionsElement, "ssl-socket-factory-ref", "sslSocketFactory"); mongoBuilder.addPropertyValue("mongoOptions", optionsDefBuilder.getBeanDefinition()); return true; diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoOptionsFactoryBean.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoOptionsFactoryBean.java index 2271de441..5948a4191 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoOptionsFactoryBean.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/MongoOptionsFactoryBean.java @@ -1,5 +1,5 @@ /* - * Copyright 2010-2011 the original author or authors. + * Copyright 2010-2013 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. @@ -15,129 +15,146 @@ */ package org.springframework.data.mongodb.core; -import com.mongodb.MongoOptions; +import javax.net.ssl.SSLSocketFactory; import org.springframework.beans.factory.FactoryBean; import org.springframework.beans.factory.InitializingBean; +import com.mongodb.MongoOptions; + /** - * A factory bean for construction of a MongoOptions instance + * A factory bean for construction of a {@link MongoOptions} instance. * * @author Graeme Rocher - * @Author Mark Pollack + * @author Mark Pollack + * @author Mike Saavedra + * @author Thomas Darimont */ public class MongoOptionsFactoryBean implements FactoryBean, InitializingBean { - private static final MongoOptions MONGO_OPTIONS = new MongoOptions(); + private final MongoOptions MONGO_OPTIONS = new MongoOptions(); + /** - * number of connections allowed per host will block if run out + * The number of connections allowed per host will block if run out. */ private int connectionsPerHost = MONGO_OPTIONS.connectionsPerHost; /** - * multiplier for connectionsPerHost for # of threads that can block if connectionsPerHost is 10, and - * threadsAllowedToBlockForConnectionMultiplier is 5, then 50 threads can block more than that and an exception will - * be throw + * A multiplier for connectionsPerHost for # of threads that can block a connection. + *

+ * If connectionsPerHost is {@literal 10}, and threadsAllowedToBlockForConnectionMultiplier is {@literal 5}, then + * {@literal 50} threads can block. If more threads try to block an exception will be thrown. */ private int threadsAllowedToBlockForConnectionMultiplier = MONGO_OPTIONS.threadsAllowedToBlockForConnectionMultiplier; /** - * max wait time of a blocking thread for a connection + * 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 + * Connect timeout in milliseconds. {@literal 0} is default and means infinite time. */ private int connectTimeout = MONGO_OPTIONS.connectTimeout; /** - * socket timeout. 0 is default and infinite + * The socket timeout. {@literal 0} is default and means infinite time. */ private int socketTimeout = MONGO_OPTIONS.socketTimeout; /** - * This controls whether or not to have socket keep alive turned on (SO_KEEPALIVE). - * - * defaults to false + * This controls whether or not to have socket keep alive turned on (SO_KEEPALIVE). This defaults to {@literal false}. */ public boolean socketKeepAlive = MONGO_OPTIONS.socketKeepAlive; /** - * this controls whether or not on a connect, the system retries automatically + * This controls whether or not the system retries automatically on a failed connect. This defaults to + * {@literal false}. */ private boolean autoConnectRetry = MONGO_OPTIONS.autoConnectRetry; private long maxAutoConnectRetryTime = MONGO_OPTIONS.maxAutoConnectRetryTime; /** - * This specifies the number of servers to wait for on the write operation, and exception raising behavior. - * - * Defaults to 0. + * This specifies the number of servers to wait for on the write operation, and exception raising behavior. This + * defaults to {@literal 0}. */ private int writeNumber; /** - * This controls timeout for write operations in milliseconds. - * - * Defaults to 0 (indefinite). Greater than zero is number of milliseconds to wait. + * This controls timeout for write operations in milliseconds. This defaults to {@literal 0} (indefinite). Greater + * than zero is number of milliseconds to wait. */ private int writeTimeout; /** - * This controls whether or not to fsync. - * - * Defaults to false. + * This controls whether or not to fsync. This defaults to {@literal false}. */ private boolean writeFsync; /** - * Specifies if the driver is allowed to read from secondaries or slaves. - * - * Defaults to false + * Specifies if the driver is allowed to read from secondaries or slaves. This defaults to {@literal false}. */ - @SuppressWarnings("deprecation") - private boolean slaveOk = MONGO_OPTIONS.slaveOk; + @SuppressWarnings("deprecation") private boolean slaveOk = MONGO_OPTIONS.slaveOk; /** - * number of connections allowed per host will block if run out + * This controls SSL support via SSLSocketFactory. This defaults to {@literal false}. + */ + private boolean ssl; + + /** + * Specifies the {@link SSLSocketFactory} to use. This defaults to {@link SSLSocketFactory#getDefault()} + */ + private SSLSocketFactory sslSocketFactory; + + /** + * The maximum number of connections allowed per host until we will block. + * + * @param connectionsPerHost */ public void setConnectionsPerHost(int connectionsPerHost) { this.connectionsPerHost = connectionsPerHost; } /** - * multiplier for connectionsPerHost for # of threads that can block if connectionsPerHost is 10, and - * threadsAllowedToBlockForConnectionMultiplier is 5, then 50 threads can block more than that and an exception will - * be throw + * A multiplier for connectionsPerHost for # of threads that can block a connection. + * + * @see #threadsAllowedToBlockForConnectionMultiplier + * @param threadsAllowedToBlockForConnectionMultiplier */ public void setThreadsAllowedToBlockForConnectionMultiplier(int threadsAllowedToBlockForConnectionMultiplier) { this.threadsAllowedToBlockForConnectionMultiplier = threadsAllowedToBlockForConnectionMultiplier; } /** - * max wait time of a blocking thread for a connection + * Max wait time of a blocking thread for a connection. + * + * @param maxWaitTime */ public void setMaxWaitTime(int maxWaitTime) { this.maxWaitTime = maxWaitTime; } /** - * connect timeout in milliseconds. 0 is default and infinite + * The connect timeout in milliseconds. {@literal 0} is default and infinite + * + * @param connectTimeout */ public void setConnectTimeout(int connectTimeout) { this.connectTimeout = connectTimeout; } /** - * socket timeout. 0 is default and infinite + * The socket timeout. {@literal 0} is default and infinite. + * + * @param socketTimeout */ public void setSocketTimeout(int socketTimeout) { this.socketTimeout = socketTimeout; } /** - * This controls whether or not to have socket keep alive + * This controls whether or not to have socket keep alive. * * @param socketKeepAlive */ @@ -147,12 +164,12 @@ public class MongoOptionsFactoryBean implements FactoryBean, Initi /** * This specifies the number of servers to wait for on the write operation, and exception raising behavior. The 'w' - * option to the getlasterror command. Defaults to 0. + * option to the getlasterror command. Defaults to {@literal 0}. *

* * @param writeNumber the number of servers to wait for on the write operation, and exception raising behavior. @@ -164,31 +181,33 @@ public class MongoOptionsFactoryBean implements FactoryBean, Initi /** * This controls timeout for write operations in milliseconds. The 'wtimeout' option to the getlasterror command. * - * @param writeTimeout Defaults to 0 (indefinite). Greater than zero is number of milliseconds to wait. + * @param writeTimeout Defaults to {@literal 0} (indefinite). Greater than zero is number of milliseconds to wait. */ public void setWriteTimeout(int writeTimeout) { this.writeTimeout = writeTimeout; } /** - * This controls whether or not to fsync. The 'fsync' option to the getlasterror command. Defaults to false. + * This controls whether or not to fsync. The 'fsync' option to the getlasterror command. Defaults to {@literal false} * - * @param writeFsync to fsync on write (true), otherwise false. + * @param writeFsync to fsync on write (true), otherwise {@literal false}. */ public void setWriteFsync(boolean writeFsync) { this.writeFsync = writeFsync; } /** - * this controls whether or not on a connect, the system retries automatically + * Controls whether or not the system retries automatically, on a failed connect. + * + * @param autoConnectRetry */ public void setAutoConnectRetry(boolean autoConnectRetry) { this.autoConnectRetry = autoConnectRetry; } /** - * The maximum amount of time in millisecons to spend retrying to open connection to the same server. Default is 0, - * which means to use the default 15s if autoConnectRetry is on. + * The maximum amount of time in millisecons to spend retrying to open connection to the same server. This defaults to + * {@literal 0}, which means to use the default {@literal 15s} if {@link #autoConnectRetry} is on. * * @param maxAutoConnectRetryTime the maxAutoConnectRetryTime to set */ @@ -197,7 +216,7 @@ public class MongoOptionsFactoryBean implements FactoryBean, Initi } /** - * Specifies if the driver is allowed to read from secondaries or slaves. Defaults to false. + * Specifies if the driver is allowed to read from secondaries or slaves. This defaults to {@literal false}. * * @param slaveOk true if the driver should read from secondaries or slaves. */ @@ -205,8 +224,29 @@ public class MongoOptionsFactoryBean implements FactoryBean, Initi this.slaveOk = slaveOk; } + /** + * Specifies if the driver should use an SSL connection to Mongo. This defaults to {@literal false}. + * + * @param ssl true if the driver should use an SSL connection. + */ + public void setSsl(boolean ssl) { + this.ssl = ssl; + } + + /** + * Specifies the SSLSocketFactory to use for creating SSL connections to Mongo. + * + * @param sslSocketFactory the sslSocketFactory to use. + */ + public void setSslSocketFactory(SSLSocketFactory sslSocketFactory) { + + setSsl(sslSocketFactory != null); + this.sslSocketFactory = sslSocketFactory; + } + @SuppressWarnings("deprecation") public void afterPropertiesSet() { + MONGO_OPTIONS.connectionsPerHost = connectionsPerHost; MONGO_OPTIONS.threadsAllowedToBlockForConnectionMultiplier = threadsAllowedToBlockForConnectionMultiplier; MONGO_OPTIONS.maxWaitTime = maxWaitTime; @@ -219,6 +259,9 @@ public class MongoOptionsFactoryBean implements FactoryBean, Initi MONGO_OPTIONS.w = writeNumber; MONGO_OPTIONS.wtimeout = writeTimeout; MONGO_OPTIONS.fsync = writeFsync; + if (ssl) { + MONGO_OPTIONS.setSocketFactory(sslSocketFactory != null ? sslSocketFactory : SSLSocketFactory.getDefault()); + } } public MongoOptions getObject() { @@ -232,5 +275,4 @@ public class MongoOptionsFactoryBean implements FactoryBean, Initi public boolean isSingleton() { return true; } - } diff --git a/spring-data-mongodb/src/main/resources/META-INF/spring.schemas b/spring-data-mongodb/src/main/resources/META-INF/spring.schemas index ebad3c5ac..c5555508e 100644 --- a/spring-data-mongodb/src/main/resources/META-INF/spring.schemas +++ b/spring-data-mongodb/src/main/resources/META-INF/spring.schemas @@ -2,4 +2,5 @@ http\://www.springframework.org/schema/data/mongo/spring-mongo-1.0.xsd=org/sprin http\://www.springframework.org/schema/data/mongo/spring-mongo-1.1.xsd=org/springframework/data/mongodb/config/spring-mongo-1.1.xsd http\://www.springframework.org/schema/data/mongo/spring-mongo-1.2.xsd=org/springframework/data/mongodb/config/spring-mongo-1.2.xsd http\://www.springframework.org/schema/data/mongo/spring-mongo-1.3.xsd=org/springframework/data/mongodb/config/spring-mongo-1.3.xsd -http\://www.springframework.org/schema/data/mongo/spring-mongo.xsd=org/springframework/data/mongodb/config/spring-mongo-1.3.xsd +http\://www.springframework.org/schema/data/mongo/spring-mongo-1.4.xsd=org/springframework/data/mongodb/config/spring-mongo-1.4.xsd +http\://www.springframework.org/schema/data/mongo/spring-mongo.xsd=org/springframework/data/mongodb/config/spring-mongo-1.4.xsd diff --git a/spring-data-mongodb/src/main/resources/org/springframework/data/mongodb/config/spring-mongo-1.4.xsd b/spring-data-mongodb/src/main/resources/org/springframework/data/mongodb/config/spring-mongo-1.4.xsd new file mode 100644 index 000000000..27d9c86ad --- /dev/null +++ b/spring-data-mongodb/src/main/resources/org/springframework/data/mongodb/config/spring-mongo-1.4.xsd @@ -0,0 +1,626 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + The WriteConcern that will be the default value used when asking the MongoDbFactory for a DB object + + + + + + + + + + + + + + The reference to a MongoTemplate. Will default to 'mongoTemplate'. + + + + + + + Enables creation of indexes for queries that get derived from the method name + and thus reference domain class properties. Defaults to false. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + The reference to a DbFactory. + + + + + + + + + + + + The reference to a MongoTypeMapper to be used by this MappingMongoConverter. + + + + + + + The reference to a MappingContext. Will default to 'mappingContext'. + + + + + + + Disables JSR-303 validation on MongoDB documents before they are saved. By default it is set to false. + + + + + + + + + + Enables abbreviating the field names for domain class properties to the + first character of their camel case names, e.g. fooBar -> fb. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + The WriteConcern that will be the default value used when asking the MongoDbFactory for a DB object + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + A reference to a custom converter. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + The reference to a DbFactory. + + + + + + + + + + + + The WriteConcern that will be the default value used when asking the MongoDbFactory for a DB object + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + The reference to a DbFactory. + + + + + + + + + + + \ No newline at end of file diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/MongoNamespaceTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/MongoNamespaceTests.java index a11b641e8..96a52bb95 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/MongoNamespaceTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/MongoNamespaceTests.java @@ -18,6 +18,8 @@ package org.springframework.data.mongodb.config; import static org.junit.Assert.*; import static org.springframework.test.util.ReflectionTestUtils.*; +import javax.net.ssl.SSLSocketFactory; + import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; @@ -41,13 +43,13 @@ import com.mongodb.WriteConcern; * @author Mark Pollack * @author Oliver Gierke * @author Martin Baumgartner + * @author Thomas Darimont */ @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration public class MongoNamespaceTests { - @Autowired - private ApplicationContext ctx; + @Autowired private ApplicationContext ctx; @Test public void testMongoSingleton() throws Exception { @@ -59,12 +61,46 @@ public class MongoNamespaceTests { @Test public void testMongoSingletonWithAttributes() throws Exception { + assertTrue(ctx.containsBean("defaultMongo")); MongoFactoryBean mfb = (MongoFactoryBean) ctx.getBean("&defaultMongo"); String host = (String) getField(mfb, "host"); Integer port = (Integer) getField(mfb, "port"); assertEquals("localhost", host); assertEquals(new Integer(27017), port); + + MongoOptions options = (MongoOptions) getField(mfb, "mongoOptions"); + assertFalse("By default socketFactory should not be a SSLSocketFactory", + options.getSocketFactory() instanceof SSLSocketFactory); + } + + /** + * @see DATAMONGO-764 + */ + @Test + public void testMongoSingletonWithSslEnabled() throws Exception { + + assertTrue(ctx.containsBean("mongoSsl")); + MongoFactoryBean mfb = (MongoFactoryBean) ctx.getBean("&mongoSsl"); + + MongoOptions options = (MongoOptions) getField(mfb, "mongoOptions"); + assertTrue("socketFactory should be a SSLSocketFactory", options.getSocketFactory() instanceof SSLSocketFactory); + } + + /** + * @see DATAMONGO-764 + */ + @Test + public void testMongoSingletonWithSslEnabledAndCustomSslSocketFactory() throws Exception { + + assertTrue(ctx.containsBean("mongoSslWithCustomSslFactory")); + MongoFactoryBean mfb = (MongoFactoryBean) ctx.getBean("&mongoSslWithCustomSslFactory"); + + SSLSocketFactory customSslSocketFactory = ctx.getBean("customSslSocketFactory", SSLSocketFactory.class); + MongoOptions options = (MongoOptions) getField(mfb, "mongoOptions"); + + assertTrue("socketFactory should be a SSLSocketFactory", options.getSocketFactory() instanceof SSLSocketFactory); + assertSame(customSslSocketFactory, options.getSocketFactory()); } @Test diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoOptionsFactoryBeanUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoOptionsFactoryBeanUnitTests.java index bb81f3f84..a73845b0d 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoOptionsFactoryBeanUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoOptionsFactoryBeanUnitTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2011 the original author or authors. + * Copyright 2011-2013 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. @@ -15,16 +15,20 @@ */ package org.springframework.data.mongodb.core; +import static org.hamcrest.CoreMatchers.*; +import static org.junit.Assert.*; + +import javax.net.ssl.SSLSocketFactory; + import org.junit.Test; import com.mongodb.MongoOptions; -import static org.hamcrest.CoreMatchers.*; -import static org.junit.Assert.*; /** * Unit tests for {@link MongoOptionsFactoryBean}. * * @author Oliver Gierke + * @author Mike Saavedra */ public class MongoOptionsFactoryBeanUnitTests { @@ -41,4 +45,19 @@ public class MongoOptionsFactoryBeanUnitTests { MongoOptions options = bean.getObject(); assertThat(options.maxAutoConnectRetryTime, is(27L)); } + + /** + * @see DATAMONGO-764 + */ + @Test + public void testSslConnection() { + + MongoOptionsFactoryBean bean = new MongoOptionsFactoryBean(); + bean.setSsl(true); + bean.afterPropertiesSet(); + + MongoOptions options = bean.getObject(); + assertNotNull(options.getSocketFactory()); + assertTrue(options.getSocketFactory() instanceof SSLSocketFactory); + } } diff --git a/spring-data-mongodb/src/test/resources/org/springframework/data/mongodb/config/MongoNamespaceTests-context.xml b/spring-data-mongodb/src/test/resources/org/springframework/data/mongodb/config/MongoNamespaceTests-context.xml index 9467bff01..4718bdc05 100644 --- a/spring-data-mongodb/src/test/resources/org/springframework/data/mongodb/config/MongoNamespaceTests-context.xml +++ b/spring-data-mongodb/src/test/resources/org/springframework/data/mongodb/config/MongoNamespaceTests-context.xml @@ -1,11 +1,13 @@ + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns:mongo="http://www.springframework.org/schema/data/mongo" + xmlns:context="http://www.springframework.org/schema/context" + xmlns:util="http://www.springframework.org/schema/util" + xsi:schemaLocation="http://www.springframework.org/schema/data/mongo http://www.springframework.org/schema/data/mongo/spring-mongo.xsd + http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd + http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd + http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> @@ -38,6 +40,17 @@ + + + + + + + + + + + diff --git a/spring-data-mongodb/template.mf b/spring-data-mongodb/template.mf index e46a19ac9..e8fe82a46 100644 --- a/spring-data-mongodb/template.mf +++ b/spring-data-mongodb/template.mf @@ -13,6 +13,7 @@ Import-Template: javax.annotation.processing.*;version="0", javax.enterprise.*;version="${cdi:[=.=.=,+1.0.0)}";resolution:=optional, javax.tools.*;version="0", + javax.net.*;version="0", javax.validation.*;version="${validation:[=.=.=.=,+1.0.0)}";resolution:=optional, org.aopalliance.*;version="[1.0.0, 2.0.0)";resolution:=optional, org.bson.*;version="0",