From 4d944d94891687d33e21a283bcf499730e8778fd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20Basl=C3=A9?= Date: Mon, 22 Jun 2015 10:33:36 +0200 Subject: [PATCH] parser for the cluster definition --- .../data/couchbase/config/BeanNames.java | 2 +- .../config/CouchbaseClusterParser.java | 45 +++--- .../config/CouchbaseNamespaceHandler.java | 2 +- .../config/CouchbaseClusterParserTest.java | 136 ++++++++++++++++++ .../configurations/couchbaseCluster-bean.xml | 26 ++++ 5 files changed, 191 insertions(+), 20 deletions(-) create mode 100644 src/test/java/org/springframework/data/couchbase/config/CouchbaseClusterParserTest.java create mode 100644 src/test/resources/configurations/couchbaseCluster-bean.xml diff --git a/src/main/java/org/springframework/data/couchbase/config/BeanNames.java b/src/main/java/org/springframework/data/couchbase/config/BeanNames.java index ceb620cc..47100c83 100644 --- a/src/main/java/org/springframework/data/couchbase/config/BeanNames.java +++ b/src/main/java/org/springframework/data/couchbase/config/BeanNames.java @@ -22,7 +22,7 @@ package org.springframework.data.couchbase.config; * @author Michael Nitschinger * @author Simon Baslé */ -public class BeanNames { +class BeanNames { /** * Refers to the "<couchbase:env />" bean. diff --git a/src/main/java/org/springframework/data/couchbase/config/CouchbaseClusterParser.java b/src/main/java/org/springframework/data/couchbase/config/CouchbaseClusterParser.java index f921387f..3897b87e 100644 --- a/src/main/java/org/springframework/data/couchbase/config/CouchbaseClusterParser.java +++ b/src/main/java/org/springframework/data/couchbase/config/CouchbaseClusterParser.java @@ -19,9 +19,8 @@ package org.springframework.data.couchbase.config; import java.util.ArrayList; import java.util.List; -import com.couchbase.client.java.Cluster; +import com.couchbase.client.java.CouchbaseCluster; import org.w3c.dom.Element; -import org.w3c.dom.NodeList; import org.springframework.beans.factory.support.AbstractBeanDefinition; import org.springframework.beans.factory.support.BeanDefinitionBuilder; @@ -70,7 +69,7 @@ public class CouchbaseClusterParser extends AbstractSingleBeanDefinitionParser { */ @Override protected Class getBeanClass(final Element element) { - return Cluster.class; + return CouchbaseCluster.class; } /** @@ -81,37 +80,47 @@ public class CouchbaseClusterParser extends AbstractSingleBeanDefinitionParser { */ @Override protected void doParse(final Element element, final BeanDefinitionBuilder bean) { + bean.setFactoryMethod("create"); + bean.setDestroyMethodName("disconnect"); + parseEnvironment(bean, element); - NodeList nodes = element.getElementsByTagName(CLUSTER_NODE_TAG); - if (nodes != null && nodes.getLength() > 0) { - List bootstrapUrls = new ArrayList(nodes.getLength()); - for (int i = 0; i < bootstrapUrls.size(); i++) { - bootstrapUrls.add(nodes.item(i).getNodeValue()); + List nodes = DomUtils.getChildElementsByTagName(element, CLUSTER_NODE_TAG); + if (nodes != null && nodes.size() > 0) { + List bootstrapUrls = new ArrayList(nodes.size()); + for (int i = 0; i < nodes.size(); i++) { + bootstrapUrls.add(nodes.get(i).getTextContent()); } bean.addConstructorArgValue(bootstrapUrls); } } - public static boolean parseEnvironment(BeanDefinitionBuilder clusterBuilder, Element clusterElement) { - //first try a reference - String envRef = clusterElement.getAttribute(CLUSTER_ENVIRONMENT_REF); - if (StringUtils.hasText(envRef)) { - clusterBuilder.addConstructorArgReference(envRef); + protected boolean parseEnvironment(BeanDefinitionBuilder clusterBuilder, Element clusterElement) { + //any inline environment description would take precedence over a reference + Element envElement = DomUtils.getChildElementByTagName(clusterElement, CLUSTER_ENVIRONMENT_TAG); + if (envElement != null && envElement.hasAttributes()) { + injectEnvElement(clusterBuilder, envElement); return true; } - //secondly try to see if an env has been described inline - Element envElement = DomUtils.getChildElementByTagName(clusterElement, CLUSTER_ENVIRONMENT_TAG); - if (envElement == null || !envElement.hasAttributes()) { - return false; + //secondly try to see if an env has been referenced + String envRef = clusterElement.getAttribute(CLUSTER_ENVIRONMENT_REF); + if (StringUtils.hasText(envRef)) { + injectEnvReference(clusterBuilder, envRef); + return true; } + return false; + } + protected void injectEnvElement(BeanDefinitionBuilder clusterBuilder, Element envElement) { BeanDefinitionBuilder envDefinitionBuilder = BeanDefinitionBuilder .genericBeanDefinition(CouchbaseEnvironmentFactoryBean.class); new CouchbaseEnvironmentParser().doParse(envElement, envDefinitionBuilder); clusterBuilder.addConstructorArgValue(envDefinitionBuilder.getBeanDefinition()); - return true; + } + + protected void injectEnvReference(BeanDefinitionBuilder clusterBuilder, String envRef) { + clusterBuilder.addConstructorArgReference(envRef); } } diff --git a/src/main/java/org/springframework/data/couchbase/config/CouchbaseNamespaceHandler.java b/src/main/java/org/springframework/data/couchbase/config/CouchbaseNamespaceHandler.java index 5402d5bb..88a2ba33 100644 --- a/src/main/java/org/springframework/data/couchbase/config/CouchbaseNamespaceHandler.java +++ b/src/main/java/org/springframework/data/couchbase/config/CouchbaseNamespaceHandler.java @@ -35,7 +35,7 @@ public class CouchbaseNamespaceHandler extends NamespaceHandlerSupport { public final void init() { //TODO repositories (CouchbaseRepositoryConfigurationExtension and RepositoryBeanDefinitionParser) //TODO bucket - //TODO cluster + registerBeanDefinitionParser("cluster", new CouchbaseClusterParser()); registerBeanDefinitionParser("env", new CouchbaseEnvironmentParser()); registerBeanDefinitionParser("jmx", new CouchbaseJmxParser()); registerBeanDefinitionParser("template", new CouchbaseTemplateParser()); diff --git a/src/test/java/org/springframework/data/couchbase/config/CouchbaseClusterParserTest.java b/src/test/java/org/springframework/data/couchbase/config/CouchbaseClusterParserTest.java new file mode 100644 index 00000000..8283b93c --- /dev/null +++ b/src/test/java/org/springframework/data/couchbase/config/CouchbaseClusterParserTest.java @@ -0,0 +1,136 @@ +/* + * Copyright 2012-2015 the original author or authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.data.couchbase.config; + +import static org.hamcrest.CoreMatchers.*; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.core.Is.is; + +import java.util.List; + +import com.couchbase.client.java.env.CouchbaseEnvironment; +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Test; + +import org.springframework.beans.factory.config.BeanDefinition; +import org.springframework.beans.factory.config.ConstructorArgumentValues; +import org.springframework.beans.factory.config.RuntimeBeanReference; +import org.springframework.beans.factory.support.BeanDefinitionReader; +import org.springframework.beans.factory.support.DefaultListableBeanFactory; +import org.springframework.beans.factory.support.GenericBeanDefinition; +import org.springframework.beans.factory.xml.XmlBeanDefinitionReader; +import org.springframework.core.io.ClassPathResource; + +public class CouchbaseClusterParserTest { + + + private static DefaultListableBeanFactory factory; + + @BeforeClass + public static void setUp() { + factory = new DefaultListableBeanFactory(); + BeanDefinitionReader reader = new XmlBeanDefinitionReader(factory); + int n = reader.loadBeanDefinitions(new ClassPathResource("configurations/couchbaseCluster-bean.xml")); + System.out.println(n); + } + + @AfterClass + public static void tearDown() { + } + + @Test + public void testClusterWithNodes() { + BeanDefinition def = factory.getBeanDefinition("clusterWithNodes"); + + assertThat(def, is(notNullValue())); + assertThat(def.getConstructorArgumentValues().getArgumentCount(), is(equalTo(1))); + assertThat(def.getPropertyValues().size(), is(equalTo(0))); + assertThat(def.getFactoryMethodName(), is(equalTo("create"))); + + ConstructorArgumentValues.ValueHolder holder = def.getConstructorArgumentValues() + .getArgumentValue(0, List.class); + assertThat(holder.getValue(), is(instanceOf(List.class))); + List nodes = (List) holder.getValue(); + + assertThat(nodes.size(), is(equalTo(2))); + assertThat((String) nodes.get(0), is(equalTo("192.1.2.3"))); + assertThat((String) nodes.get(1), is(equalTo("192.4.5.6"))); + } + + @Test + public void testClusterWithEnvInline() { + BeanDefinition def = factory.getBeanDefinition("clusterWithEnvInline"); + + assertThat(def, is(notNullValue())); + assertThat(def.getConstructorArgumentValues().getArgumentCount(), is(equalTo(1))); + assertThat(def.getPropertyValues().size(), is(equalTo(0))); + + ConstructorArgumentValues.ValueHolder holder = def.getConstructorArgumentValues() + .getArgumentValue(0, CouchbaseEnvironment.class); + GenericBeanDefinition envDef = (GenericBeanDefinition) holder.getValue(); + + assertThat(envDef.getBeanClassName(), is(equalTo(CouchbaseEnvironmentFactoryBean.class.getName()))); + assertThat("unexpected attribute", envDef.getPropertyValues().contains("managementTimeout")); + } + + @Test + public void testClusterWithEnvRef() { + BeanDefinition def = factory.getBeanDefinition("clusterWithEnvRef"); + + assertThat(def, is(notNullValue())); + assertThat(def.getConstructorArgumentValues().getArgumentCount(), is(equalTo(1))); + assertThat(def.getPropertyValues().size(), is(equalTo(0))); + + ConstructorArgumentValues.ValueHolder holder = def.getConstructorArgumentValues() + .getArgumentValue(0, CouchbaseEnvironment.class); + + assertThat(holder.getValue(), instanceOf(RuntimeBeanReference.class)); + RuntimeBeanReference envRef = (RuntimeBeanReference) holder.getValue(); + + assertThat(envRef.getBeanName(), is(equalTo("someEnv"))); + } + @Test + public void testClusterConfigurationPrecedence() { + BeanDefinition def = factory.getBeanDefinition("clusterWithAll"); + + assertThat(def, is(notNullValue())); + assertThat(def.getConstructorArgumentValues().getArgumentCount(), is(equalTo(2))); + assertThat(def.getPropertyValues().size(), is(equalTo(0))); + assertThat(def.getFactoryMethodName(), is(equalTo("create"))); + + assertThat(def.getConstructorArgumentValues().getIndexedArgumentValues().get(0).getValue(), + instanceOf(GenericBeanDefinition.class)); + assertThat(def.getConstructorArgumentValues().getIndexedArgumentValues().get(1).getValue(), + instanceOf(List.class)); + + ConstructorArgumentValues.ValueHolder holderEnv = def.getConstructorArgumentValues() + .getArgumentValue(0, CouchbaseEnvironment.class); + GenericBeanDefinition envDef = (GenericBeanDefinition) holderEnv.getValue(); + + assertThat(envDef.getBeanClassName(), is(equalTo(CouchbaseEnvironmentFactoryBean.class.getName()))); + assertThat("unexpected attribute", envDef.getPropertyValues().contains("autoreleaseAfter")); + + ConstructorArgumentValues.ValueHolder holderNodes = def.getConstructorArgumentValues() + .getArgumentValue(1, List.class); + List nodes = (List) holderNodes.getValue(); + + assertThat(nodes.size(), is(equalTo(2))); + assertThat((String) nodes.get(0), is(equalTo("2.2.2.2"))); + assertThat((String) nodes.get(1), is(equalTo("4.4.4.4"))); + } +} \ No newline at end of file diff --git a/src/test/resources/configurations/couchbaseCluster-bean.xml b/src/test/resources/configurations/couchbaseCluster-bean.xml new file mode 100644 index 00000000..2ad55028 --- /dev/null +++ b/src/test/resources/configurations/couchbaseCluster-bean.xml @@ -0,0 +1,26 @@ + + + + + + + + + + + + 192.1.2.3 + 192.4.5.6 + + + + 2.2.2.2 + 4.4.4.4 + + + \ No newline at end of file