From 4e4c4f69ffcf5975e5e86069e55263675442a40b Mon Sep 17 00:00:00 2001 From: Mark Fisher Date: Mon, 1 Nov 2010 14:17:39 -0400 Subject: [PATCH 01/82] polishing --- ...gregatedXmlMessageValidationException.java | 34 +++-- .../xml/DefaultXmlPayloadConverter.java | 140 +++++++++--------- .../integration/xml/XmlPayloadConverter.java | 5 +- 3 files changed, 101 insertions(+), 78 deletions(-) diff --git a/spring-integration-xml/src/main/java/org/springframework/integration/xml/AggregatedXmlMessageValidationException.java b/spring-integration-xml/src/main/java/org/springframework/integration/xml/AggregatedXmlMessageValidationException.java index 011369040c..9649dc8f8b 100644 --- a/spring-integration-xml/src/main/java/org/springframework/integration/xml/AggregatedXmlMessageValidationException.java +++ b/spring-integration-xml/src/main/java/org/springframework/integration/xml/AggregatedXmlMessageValidationException.java @@ -1,8 +1,22 @@ -/** - * +/* + * Copyright 2002-2010 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ + package org.springframework.integration.xml; +import java.util.Collections; import java.util.Iterator; import java.util.List; @@ -12,18 +26,20 @@ import java.util.List; */ @SuppressWarnings("serial") public class AggregatedXmlMessageValidationException extends RuntimeException { - + private final List exceptions; - public AggregatedXmlMessageValidationException(List exceptions){ - this.exceptions = exceptions; + + public AggregatedXmlMessageValidationException(List exceptions) { + this.exceptions = (exceptions != null) ? exceptions : Collections.emptyList(); } + + /** - * Will return iterator of exceptions aggregated by this Class. - * - * @return + * Returns an Iterator for the aggregated Exceptions. */ - public Iterator exceptionIterator(){ + public Iterator exceptionIterator() { return exceptions.iterator(); } + } diff --git a/spring-integration-xml/src/main/java/org/springframework/integration/xml/DefaultXmlPayloadConverter.java b/spring-integration-xml/src/main/java/org/springframework/integration/xml/DefaultXmlPayloadConverter.java index 7a85368523..890b9795da 100644 --- a/spring-integration-xml/src/main/java/org/springframework/integration/xml/DefaultXmlPayloadConverter.java +++ b/spring-integration-xml/src/main/java/org/springframework/integration/xml/DefaultXmlPayloadConverter.java @@ -25,89 +25,95 @@ import javax.xml.parsers.ParserConfigurationException; import javax.xml.transform.Source; import javax.xml.transform.dom.DOMSource; -import org.springframework.integration.MessagingException; -import org.springframework.xml.transform.StringSource; import org.w3c.dom.Document; import org.w3c.dom.Node; import org.xml.sax.InputSource; +import org.springframework.integration.MessagingException; +import org.springframework.xml.transform.StringSource; + /** - * Default implementation of {@link XmlPayloadConverter}. - * Supports {@link Document} and {@link String}. - * + * Default implementation of {@link XmlPayloadConverter}. Supports + * {@link Document}, {@link File} and {@link String} payloads. + * * @author Jonas Partner */ public class DefaultXmlPayloadConverter implements XmlPayloadConverter { - private DocumentBuilderFactory documentBuilderFactory; + private DocumentBuilderFactory documentBuilderFactory; - public DefaultXmlPayloadConverter() { - this.documentBuilderFactory = DocumentBuilderFactory.newInstance(); - this.documentBuilderFactory.setNamespaceAware(true); - } + public DefaultXmlPayloadConverter() { + this.documentBuilderFactory = DocumentBuilderFactory.newInstance(); + this.documentBuilderFactory.setNamespaceAware(true); + } - public DefaultXmlPayloadConverter(DocumentBuilderFactory documentBuilderFactory) { - this.documentBuilderFactory = documentBuilderFactory; - } + public DefaultXmlPayloadConverter(DocumentBuilderFactory documentBuilderFactory) { + this.documentBuilderFactory = documentBuilderFactory; + } - public Document convertToDocument(Object object) { - if (object instanceof Document) { - return (Document) object; - } - if (object instanceof File) { - try { - return getDocumentBuilder().parse((File) object); - } - catch (Exception e) { - throw new MessagingException("failed to parse File payload '" + object + "'", e); - } - } - if (object instanceof String) { - try { - return getDocumentBuilder().parse(new InputSource(new StringReader((String) object))); - } - catch (Exception e) { - throw new MessagingException("failed to parse String payload '" + object + "'", e); - } - } - throw new MessagingException("unsupported payload type [" + object.getClass().getName() + "]"); - } + public Document convertToDocument(Object object) { + if (object instanceof Document) { + return (Document) object; + } + if (object instanceof File) { + try { + return getDocumentBuilder().parse((File) object); + } + catch (Exception e) { + throw new MessagingException("failed to parse File payload '" + object + "'", e); + } + } + if (object instanceof String) { + try { + return getDocumentBuilder().parse(new InputSource(new StringReader((String) object))); + } + catch (Exception e) { + throw new MessagingException("failed to parse String payload '" + object + "'", e); + } + } + throw new MessagingException("unsupported payload type [" + object.getClass().getName() + "]"); + } - public Node convertToNode(Object object) { - Node n = null; - if (object instanceof Node) { - n = (Node) object; - } else if (object instanceof DOMSource) { - n = ((DOMSource) object).getNode(); - } else { - n = convertToDocument(object); - } - return n; - } + public Node convertToNode(Object object) { + Node node = null; + if (object instanceof Node) { + node = (Node) object; + } + else if (object instanceof DOMSource) { + node = ((DOMSource) object).getNode(); + } + else { + node = convertToDocument(object); + } + return node; + } - public Source convertToSource(Object object) { - Source source; - if (object instanceof Source) { - source = (Source) object; - } else if (object instanceof Document) { - source = new DOMSource((Document) object); - } else if (object instanceof String) { - source = new StringSource((String) object); - } else { - throw new MessagingException("unsupported payload type [" + object.getClass().getName() + "]"); - } - return source; - } + public Source convertToSource(Object object) { + Source source = null; + if (object instanceof Source) { + source = (Source) object; + } + else if (object instanceof Document) { + source = new DOMSource((Document) object); + } + else if (object instanceof String) { + source = new StringSource((String) object); + } + else { + throw new MessagingException("unsupported payload type [" + object.getClass().getName() + "]"); + } + return source; + } - protected synchronized DocumentBuilder getDocumentBuilder() { - try { - return this.documentBuilderFactory.newDocumentBuilder(); - } - catch (ParserConfigurationException e) { - throw new MessagingException("failed to create a new DocumentBuilder", e); - } - } + protected synchronized DocumentBuilder getDocumentBuilder() { + try { + return this.documentBuilderFactory.newDocumentBuilder(); + } + catch (ParserConfigurationException e) { + throw new MessagingException("failed to create a new DocumentBuilder", e); + } + } } diff --git a/spring-integration-xml/src/main/java/org/springframework/integration/xml/XmlPayloadConverter.java b/spring-integration-xml/src/main/java/org/springframework/integration/xml/XmlPayloadConverter.java index 0a92c04b0e..aae58e2382 100644 --- a/spring-integration-xml/src/main/java/org/springframework/integration/xml/XmlPayloadConverter.java +++ b/spring-integration-xml/src/main/java/org/springframework/integration/xml/XmlPayloadConverter.java @@ -22,7 +22,8 @@ import org.w3c.dom.Document; import org.w3c.dom.Node; /** - * Converter for creating XML {@link Document} instances + * Converter for creating XML {@link Document}, {@link Node} or {@link Source} + * instances from other types (e.g. String). * * @author Jonas Partner */ @@ -31,7 +32,7 @@ public interface XmlPayloadConverter { public Document convertToDocument(Object object); public Node convertToNode(Object object); - + public Source convertToSource(Object object); } From 36dad9371c2df1bff0823f4bb2a0579f473c5f7f Mon Sep 17 00:00:00 2001 From: Mark Fisher Date: Mon, 1 Nov 2010 14:36:07 -0400 Subject: [PATCH 02/82] formatting --- .../config/MarshallingTransformerParser.java | 2 +- .../UnmarshallingTransformerParser.java | 2 +- .../xml/config/XPathExpressionParser.java | 10 +-- .../config/XPathMessageSplitterParser.java | 19 ++--- .../xml/config/XPathRouterParser.java | 11 +-- .../xml/config/XPathSelectorParser.java | 12 +-- .../xml/config/XmlNamespaceUtils.java | 2 +- .../XmlPayloadValidatingFilterParser.java | 80 ++++++++++--------- .../config/XsltPayloadTransformerParser.java | 13 ++- 9 files changed, 69 insertions(+), 82 deletions(-) diff --git a/spring-integration-xml/src/main/java/org/springframework/integration/xml/config/MarshallingTransformerParser.java b/spring-integration-xml/src/main/java/org/springframework/integration/xml/config/MarshallingTransformerParser.java index edfa517191..fa796df527 100644 --- a/spring-integration-xml/src/main/java/org/springframework/integration/xml/config/MarshallingTransformerParser.java +++ b/spring-integration-xml/src/main/java/org/springframework/integration/xml/config/MarshallingTransformerParser.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2009 the original author or authors. + * Copyright 2002-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. diff --git a/spring-integration-xml/src/main/java/org/springframework/integration/xml/config/UnmarshallingTransformerParser.java b/spring-integration-xml/src/main/java/org/springframework/integration/xml/config/UnmarshallingTransformerParser.java index 2a6436ae5e..fc7d31e381 100644 --- a/spring-integration-xml/src/main/java/org/springframework/integration/xml/config/UnmarshallingTransformerParser.java +++ b/spring-integration-xml/src/main/java/org/springframework/integration/xml/config/UnmarshallingTransformerParser.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2009 the original author or authors. + * Copyright 2002-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. diff --git a/spring-integration-xml/src/main/java/org/springframework/integration/xml/config/XPathExpressionParser.java b/spring-integration-xml/src/main/java/org/springframework/integration/xml/config/XPathExpressionParser.java index 69bf51bbe5..24bf68e4a9 100644 --- a/spring-integration-xml/src/main/java/org/springframework/integration/xml/config/XPathExpressionParser.java +++ b/spring-integration-xml/src/main/java/org/springframework/integration/xml/config/XPathExpressionParser.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2008 the original author or authors. + * Copyright 2002-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. @@ -58,24 +58,19 @@ public class XPathExpressionParser extends AbstractSingleBeanDefinitionParser { protected void doParse(Element element, ParserContext parserContext, BeanDefinitionBuilder builder) { String expression = element.getAttribute("expression"); Assert.hasText(expression, "The 'expression' attribute is required."); - String nsPrefix = element.getAttribute("ns-prefix"); String nsUri = element.getAttribute("ns-uri"); String namespaceMapRef = element.getAttribute("namespace-map"); - boolean prefixProvided = StringUtils.hasText(nsPrefix); boolean namespaceProvided = StringUtils.hasText(nsUri); boolean namespaceMapProvided = StringUtils.hasText(namespaceMapRef); - if (prefixProvided || namespaceProvided) { Assert.isTrue(prefixProvided && namespaceProvided, "Both 'ns-prefix' and 'ns-uri' must be specified if one is specified."); Assert.isTrue(!namespaceMapProvided, "It is not valid to specify both namespace and namespace-map."); } - builder.setFactoryMethod("createXPathExpression"); builder.addConstructorArgValue(expression); - if (prefixProvided) { Map namespaceMap = new HashMap(); namespaceMap.put(nsPrefix, nsUri); @@ -103,8 +98,7 @@ public class XPathExpressionParser extends AbstractSingleBeanDefinitionParser { } } - @SuppressWarnings("unchecked") - protected Map parseNamespaceMapElement(Element element, ParserContext parserContext, BeanDefinition parentDefinition) { + protected Map parseNamespaceMapElement(Element element, ParserContext parserContext, BeanDefinition parentDefinition) { BeanDefinitionParserDelegate beanParser = new BeanDefinitionParserDelegate(parserContext.getReaderContext()); beanParser.initDefaults(element.getOwnerDocument().getDocumentElement()); return beanParser.parseMapElement(element, parentDefinition); diff --git a/spring-integration-xml/src/main/java/org/springframework/integration/xml/config/XPathMessageSplitterParser.java b/spring-integration-xml/src/main/java/org/springframework/integration/xml/config/XPathMessageSplitterParser.java index 7e798632be..8b714b1303 100644 --- a/spring-integration-xml/src/main/java/org/springframework/integration/xml/config/XPathMessageSplitterParser.java +++ b/spring-integration-xml/src/main/java/org/springframework/integration/xml/config/XPathMessageSplitterParser.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2008 the original author or authors. + * Copyright 2002-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. @@ -23,6 +23,7 @@ import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.beans.factory.support.BeanDefinitionBuilder; import org.springframework.beans.factory.xml.ParserContext; import org.springframework.integration.config.xml.AbstractConsumerEndpointParser; +import org.springframework.integration.config.xml.IntegrationNamespaceUtils; import org.springframework.integration.xml.splitter.XPathMessageSplitter; import org.springframework.util.Assert; import org.springframework.util.StringUtils; @@ -49,14 +50,10 @@ public class XPathMessageSplitterParser extends AbstractConsumerEndpointParser { protected BeanDefinitionBuilder parseHandler(Element element, ParserContext parserContext) { BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(XPathMessageSplitter.class); String xPathExpressionRef = element.getAttribute("xpath-expression-ref"); - String documentBuilderFactoryRef = element.getAttribute("doc-builder-factory"); - String createDocuments = element.getAttribute("create-documents"); - NodeList xPathExpressionNodes = element.getElementsByTagNameNS(element.getNamespaceURI(), "xpath-expression"); - Assert.isTrue(xPathExpressionNodes.getLength() <= 1, "only one xpath-expression child can be specified"); + Assert.isTrue(xPathExpressionNodes.getLength() <= 1, "At most one xpath-expression child may be specified."); boolean hasChild = xPathExpressionNodes.getLength() == 1; boolean hasReference = StringUtils.hasText(xPathExpressionRef); - Assert.isTrue(hasChild ^ hasReference, "Exactly one of 'xpath-expression' or 'xpath-expression-ref' is required."); if (hasChild) { BeanDefinition beanDefinition = this.xpathParser.parse((Element) xPathExpressionNodes.item(0), parserContext); @@ -65,14 +62,8 @@ public class XPathMessageSplitterParser extends AbstractConsumerEndpointParser { else { builder.addConstructorArgReference(xPathExpressionRef); } - - if(StringUtils.hasText(documentBuilderFactoryRef)){ - builder.addPropertyReference("documentBuilder", documentBuilderFactoryRef); - } - if(StringUtils.hasText("create-documents")){ - builder.addPropertyValue("createDocuments", Boolean.valueOf(createDocuments)); - } - + IntegrationNamespaceUtils.setReferenceIfAttributeDefined(builder, element, "doc-builder-factory", "documentBuilder"); + IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, "create-documents"); return builder; } diff --git a/spring-integration-xml/src/main/java/org/springframework/integration/xml/config/XPathRouterParser.java b/spring-integration-xml/src/main/java/org/springframework/integration/xml/config/XPathRouterParser.java index 22da832772..e36f3daebe 100644 --- a/spring-integration-xml/src/main/java/org/springframework/integration/xml/config/XPathRouterParser.java +++ b/spring-integration-xml/src/main/java/org/springframework/integration/xml/config/XPathRouterParser.java @@ -16,14 +16,15 @@ package org.springframework.integration.xml.config; +import org.w3c.dom.Element; +import org.w3c.dom.NodeList; + import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.beans.factory.support.BeanDefinitionBuilder; import org.springframework.beans.factory.xml.ParserContext; import org.springframework.integration.config.xml.AbstractRouterParser; import org.springframework.util.Assert; import org.springframework.util.StringUtils; -import org.w3c.dom.Element; -import org.w3c.dom.NodeList; /** * Parser for the <xpath-router/> element. @@ -36,14 +37,14 @@ public class XPathRouterParser extends AbstractRouterParser { private XPathExpressionParser xpathParser = new XPathExpressionParser(); + @Override - protected BeanDefinition doParseRouter(Element element, - ParserContext parserContext) { + protected BeanDefinition doParseRouter(Element element, ParserContext parserContext) { BeanDefinitionBuilder xpathRouterBuilder = BeanDefinitionBuilder.genericBeanDefinition( "org.springframework.integration.xml.router.XPathRouter"); NodeList xPathExpressionNodes = element.getElementsByTagNameNS( element.getNamespaceURI(), "xpath-expression"); - Assert.isTrue(xPathExpressionNodes.getLength() < 2, "Only one xpath-expression child can be specified."); + Assert.isTrue(xPathExpressionNodes.getLength() <= 1, "At most one xpath-expression child may be specified."); String xPathExpressionRef = element.getAttribute("xpath-expression-ref"); boolean xPathExpressionChildPresent = (xPathExpressionNodes.getLength() == 1); boolean xPathReferencePresent = StringUtils.hasText(xPathExpressionRef); diff --git a/spring-integration-xml/src/main/java/org/springframework/integration/xml/config/XPathSelectorParser.java b/spring-integration-xml/src/main/java/org/springframework/integration/xml/config/XPathSelectorParser.java index 241f795518..c63b3dd6c2 100644 --- a/spring-integration-xml/src/main/java/org/springframework/integration/xml/config/XPathSelectorParser.java +++ b/spring-integration-xml/src/main/java/org/springframework/integration/xml/config/XPathSelectorParser.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2008 the original author or authors. + * Copyright 2002-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. @@ -16,18 +16,18 @@ package org.springframework.integration.xml.config; +import org.w3c.dom.Element; +import org.w3c.dom.NodeList; + +import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.beans.factory.support.BeanDefinitionBuilder; import org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser; import org.springframework.beans.factory.xml.ParserContext; -import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.integration.xml.selector.BooleanTestXPathMessageSelector; import org.springframework.integration.xml.selector.StringValueTestXPathMessageSelector; import org.springframework.util.Assert; import org.springframework.util.StringUtils; -import org.w3c.dom.Element; -import org.w3c.dom.NodeList; - /** * @author Jonas Partner */ @@ -52,7 +52,7 @@ public class XPathSelectorParser extends AbstractSingleBeanDefinitionParser { String xPathExpressionRef = element.getAttribute("xpath-expression-ref"); String stringTestValue = element.getAttribute("string-test-value"); NodeList xPathExpressionNodes = element.getElementsByTagNameNS(element.getNamespaceURI(), "xpath-expression"); - Assert.isTrue(xPathExpressionNodes.getLength() < 2, "Only one xpath-expression child can be specified"); + Assert.isTrue(xPathExpressionNodes.getLength() <= 1, "At most one xpath-expression child may be specified."); boolean xPathExpressionChildPresent = xPathExpressionNodes.getLength() == 1; boolean xPathReferencePresent = StringUtils.hasText(xPathExpressionRef); Assert.isTrue(xPathExpressionChildPresent ^ xPathReferencePresent, diff --git a/spring-integration-xml/src/main/java/org/springframework/integration/xml/config/XmlNamespaceUtils.java b/spring-integration-xml/src/main/java/org/springframework/integration/xml/config/XmlNamespaceUtils.java index a3d7a4b574..439e79cc46 100644 --- a/spring-integration-xml/src/main/java/org/springframework/integration/xml/config/XmlNamespaceUtils.java +++ b/spring-integration-xml/src/main/java/org/springframework/integration/xml/config/XmlNamespaceUtils.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2008 the original author or authors. + * Copyright 2002-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. diff --git a/spring-integration-xml/src/main/java/org/springframework/integration/xml/config/XmlPayloadValidatingFilterParser.java b/spring-integration-xml/src/main/java/org/springframework/integration/xml/config/XmlPayloadValidatingFilterParser.java index d98e1dcdb0..ddbc97bdac 100644 --- a/spring-integration-xml/src/main/java/org/springframework/integration/xml/config/XmlPayloadValidatingFilterParser.java +++ b/spring-integration-xml/src/main/java/org/springframework/integration/xml/config/XmlPayloadValidatingFilterParser.java @@ -16,61 +16,32 @@ package org.springframework.integration.xml.config; +import org.w3c.dom.Element; + import org.springframework.beans.factory.BeanDefinitionStoreException; import org.springframework.beans.factory.support.BeanDefinitionBuilder; import org.springframework.beans.factory.xml.ParserContext; import org.springframework.integration.config.xml.AbstractConsumerEndpointParser; import org.springframework.integration.config.xml.IntegrationNamespaceUtils; import org.springframework.util.StringUtils; -import org.w3c.dom.Element; /** * @author Jonas Partner * @author Oleg Zhurakousky */ public class XmlPayloadValidatingFilterParser extends AbstractConsumerEndpointParser { - private static String SELECTOR = - "org.springframework.integration.xml.selector.XmlValidatingMessageSelector"; - private static String FILTER = - "org.springframework.integration.config.FilterFactoryBean"; - + + private static String SELECTOR_CLASSNAME = "org.springframework.integration.xml.selector.XmlValidatingMessageSelector"; + + private static String FILTER_CLASSNAME = "org.springframework.integration.config.FilterFactoryBean"; + /** Constant that defines a W3C XML Schema. */ - public static final String SCHEMA_W3C_XML = "http://www.w3.org/2001/XMLSchema"; + public static final String SCHEMA_W3C_XML = "http://www.w3.org/2001/XMLSchema"; - /** Constant that defines a RELAX NG Schema. */ - public static final String SCHEMA_RELAX_NG = "http://relaxng.org/ns/structure/1.0"; + /** Constant that defines a RELAX NG Schema. */ + public static final String SCHEMA_RELAX_NG = "http://relaxng.org/ns/structure/1.0"; - @Override - protected BeanDefinitionBuilder parseHandler(Element element, ParserContext parserContext) { - BeanDefinitionBuilder filterBuilder = BeanDefinitionBuilder.genericBeanDefinition(FILTER); - IntegrationNamespaceUtils.setReferenceIfAttributeDefined(filterBuilder, element, "discard-channel"); - IntegrationNamespaceUtils.setValueIfAttributeDefined(filterBuilder, element, "throw-exception-on-rejection"); - - BeanDefinitionBuilder selectorBuilder = BeanDefinitionBuilder.genericBeanDefinition(SELECTOR); - String validator = element.getAttribute("xml-validator"); - String schemaLocation = element.getAttribute("schema-location"); - boolean validatorDefined = StringUtils.hasText(validator); - boolean schemaLocationDefined = StringUtils.hasText(schemaLocation); - selectorBuilder.addPropertyValue("throwExceptionOnRejection", element.getAttribute("throw-exception-on-rejection")); - - if (!(validatorDefined ^ schemaLocationDefined)) { - throw new BeanDefinitionStoreException("Exactly one of 'xml-validator' or 'schema-location' is allowed on the 'validating-filter' element"); - } - if (schemaLocationDefined){ - selectorBuilder.addConstructorArgValue(schemaLocation); - // it is a restriction with the default value of 'xml-schema' which corresponds to 'http://www.w3.org/2001/XMLSchema' - String schemaType = "xml-schema".equals(element.getAttribute("schema-type")) ? SCHEMA_W3C_XML : SCHEMA_RELAX_NG;; - selectorBuilder.addConstructorArgValue(schemaType); - } - else { - selectorBuilder.addConstructorArgReference(validator); - } - - filterBuilder.addPropertyValue("targetObject", selectorBuilder.getBeanDefinition()); - return filterBuilder; - } - @Override protected boolean shouldGenerateId() { return false; @@ -80,4 +51,35 @@ public class XmlPayloadValidatingFilterParser extends AbstractConsumerEndpointPa protected boolean shouldGenerateIdAsFallback() { return true; } + + @Override + protected BeanDefinitionBuilder parseHandler(Element element, ParserContext parserContext) { + BeanDefinitionBuilder filterBuilder = BeanDefinitionBuilder.genericBeanDefinition(FILTER_CLASSNAME); + IntegrationNamespaceUtils.setReferenceIfAttributeDefined(filterBuilder, element, "discard-channel"); + IntegrationNamespaceUtils.setValueIfAttributeDefined(filterBuilder, element, "throw-exception-on-rejection"); + BeanDefinitionBuilder selectorBuilder = BeanDefinitionBuilder.genericBeanDefinition(SELECTOR_CLASSNAME); + String validator = element.getAttribute("xml-validator"); + String schemaLocation = element.getAttribute("schema-location"); + boolean validatorDefined = StringUtils.hasText(validator); + boolean schemaLocationDefined = StringUtils.hasText(schemaLocation); + if (!(validatorDefined ^ schemaLocationDefined)) { + throw new BeanDefinitionStoreException( + "Exactly one of 'xml-validator' or 'schema-location' is allowed on the 'validating-filter' element"); + } + if (schemaLocationDefined) { + selectorBuilder.addConstructorArgValue(schemaLocation); + // it is a restriction with the default value of 'xml-schema' which + // corresponds to 'http://www.w3.org/2001/XMLSchema' + String schemaType = "xml-schema".equals(element.getAttribute("schema-type")) + ? SCHEMA_W3C_XML : SCHEMA_RELAX_NG; + selectorBuilder.addConstructorArgValue(schemaType); + } + else { + selectorBuilder.addConstructorArgReference(validator); + } + selectorBuilder.addPropertyValue("throwExceptionOnRejection", element.getAttribute("throw-exception-on-rejection")); + filterBuilder.addPropertyValue("targetObject", selectorBuilder.getBeanDefinition()); + return filterBuilder; + } + } diff --git a/spring-integration-xml/src/main/java/org/springframework/integration/xml/config/XsltPayloadTransformerParser.java b/spring-integration-xml/src/main/java/org/springframework/integration/xml/config/XsltPayloadTransformerParser.java index 96c2380bc2..2661711074 100644 --- a/spring-integration-xml/src/main/java/org/springframework/integration/xml/config/XsltPayloadTransformerParser.java +++ b/spring-integration-xml/src/main/java/org/springframework/integration/xml/config/XsltPayloadTransformerParser.java @@ -19,6 +19,8 @@ package org.springframework.integration.xml.config; import java.util.List; import java.util.Map; +import org.w3c.dom.Element; + import org.springframework.beans.factory.support.BeanDefinitionBuilder; import org.springframework.beans.factory.support.ManagedMap; import org.springframework.beans.factory.support.RootBeanDefinition; @@ -29,7 +31,6 @@ import org.springframework.util.Assert; import org.springframework.util.CollectionUtils; import org.springframework.util.StringUtils; import org.springframework.util.xml.DomUtils; -import org.w3c.dom.Element; /** * @author Jonas Partner @@ -63,23 +64,21 @@ public class XsltPayloadTransformerParser extends AbstractTransformerParser { if (StringUtils.hasText(resultTransformer)) { builder.addConstructorArgReference(resultTransformer); } - List xslParameterElements = DomUtils.getChildElementsByTagName(element, "xslt-param"); if (!CollectionUtils.isEmpty(xslParameterElements)) { Map xslParameterMappings = new ManagedMap(); for (Element xslParameterElement : xslParameterElements) { String name = xslParameterElement.getAttribute("name"); - String expression = xslParameterElement.getAttribute("expression"); String value = xslParameterElement.getAttribute("value"); Assert.isTrue(StringUtils.hasText(expression) ^ StringUtils.hasText(value), "Exactly one of 'expression' or 'value' is required."); - RootBeanDefinition expressionDef = null; - if (StringUtils.hasText(value)){ + if (StringUtils.hasText(value)) { expressionDef = new RootBeanDefinition("org.springframework.expression.common.LiteralExpression"); expressionDef.getConstructorArgumentValues().addGenericArgumentValue(value); - } else if (StringUtils.hasText(expression)){ + } + else if (StringUtils.hasText(expression)) { expressionDef = new RootBeanDefinition("org.springframework.integration.config.ExpressionFactoryBean"); expressionDef.getConstructorArgumentValues().addGenericArgumentValue(expression); } @@ -89,7 +88,7 @@ public class XsltPayloadTransformerParser extends AbstractTransformerParser { } builder.addPropertyValue("xslParameterMappings", xslParameterMappings); } - IntegrationNamespaceUtils.setReferenceIfAttributeDefined(builder, element, "source-factory"); } + } From b37f8f8ac9eb71adf3933123905b210cd120678a Mon Sep 17 00:00:00 2001 From: Mark Fisher Date: Mon, 1 Nov 2010 14:44:43 -0400 Subject: [PATCH 03/82] INT-1575 updated root level readme.txt file --- readme.txt | 30 +++++++++++++++++++++++++----- 1 file changed, 25 insertions(+), 5 deletions(-) diff --git a/readme.txt b/readme.txt index a74109abc6..3f82fd0ce7 100644 --- a/readme.txt +++ b/readme.txt @@ -1,11 +1,31 @@ -TODO: complete +============================== Spring Integration ============================= +To check out the project and build from source, do the following: -project distribution zip file can be built by executing + git clone git://git.springsource.org/spring-integration/spring-integration.git + cd spring-integration + ./gradlew build - src/main/scripts/build-distribution.sh +------------------------------------------------------------------------------- +To generate Eclipse metadata (.classpath and .project files), do the following: + ./gradlew eclipse -licensing, changelog and other project information can be found under +Once complete, you may then import the projects into Eclipse as usual: - src/main/resources + File -> Import -> Existing projects into workspace +Browse to the 'spring-integration' root directory. All projects should import +free of errors. + +------------------------------------------------------------------------------- +To generate IDEA metadata (.iml and .ipr files), do the following: + + ./gradlew idea + +------------------------------------------------------------------------------- +To build the JavaDoc, do the following from within the root directory: + + ./gradlew :docs:api + +The result will be available in 'docs/build/api'. +=============================================================================== \ No newline at end of file From ed6b8c0159769f6b344002984e277a537d0d1882 Mon Sep 17 00:00:00 2001 From: Oleg Zhurakousky Date: Mon, 1 Nov 2010 17:13:50 -0400 Subject: [PATCH 04/82] INT-1574 added javadoc explaining immutability of Message and MessageHeaders --- .../integration/MessageHeaders.java | 31 ++++++++++++++++--- .../integration/message/ErrorMessage.java | 1 + .../integration/message/GenericMessage.java | 1 + 3 files changed, 28 insertions(+), 5 deletions(-) diff --git a/spring-integration-core/src/main/java/org/springframework/integration/MessageHeaders.java b/spring-integration-core/src/main/java/org/springframework/integration/MessageHeaders.java index 046969c043..dc9991d813 100644 --- a/spring-integration-core/src/main/java/org/springframework/integration/MessageHeaders.java +++ b/spring-integration-core/src/main/java/org/springframework/integration/MessageHeaders.java @@ -33,7 +33,20 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; /** - * The headers for a {@link Message}. + * The headers for a {@link Message}.
+ * IMPORTANT: MessageHeaders are immutable. Any mutating operation (e.g., put(..), putAll(..) etc.) + * will result in {@link UnsupportedOperationException} + * To create MessageHeaders instance use fluent MessageBuilder API + *
+ * MessageBuilder.withPayload("foo").setHeader("key1", "value1").setHeader("key2", "value2");
+ * 
+ * or create an instance of GenericMessage passing payload as {@link Object} and headers as a regular {@link Map} + *
+ * Map headers = new HashMap();
+ * headers.put("key1", "value1");
+ * headers.put("key2", "value2");
+ * new GenericMessage("foo", headers);
+ * 
* * @author Arjen Poutsma * @author Mark Fisher @@ -192,19 +205,27 @@ public final class MessageHeaders implements Map, Serializable { /* * Unsupported operations */ - + /** + * Since MessageHeaders are immutable the call to this method will result in {@link UnsupportedOperationException} + */ public Object put(String key, Object value) { throw new UnsupportedOperationException("MessageHeaders is immutable."); } - + /** + * Since MessageHeaders are immutable the call to this method will result in {@link UnsupportedOperationException} + */ public void putAll(Map t) { throw new UnsupportedOperationException("MessageHeaders is immutable."); } - + /** + * Since MessageHeaders are immutable the call to this method will result in {@link UnsupportedOperationException} + */ public Object remove(Object key) { throw new UnsupportedOperationException("MessageHeaders is immutable."); } - + /** + * Since MessageHeaders are immutable the call to this method will result in {@link UnsupportedOperationException} + */ public void clear() { throw new UnsupportedOperationException("MessageHeaders is immutable."); } diff --git a/spring-integration-core/src/main/java/org/springframework/integration/message/ErrorMessage.java b/spring-integration-core/src/main/java/org/springframework/integration/message/ErrorMessage.java index ca8e84f350..9a96d11718 100644 --- a/spring-integration-core/src/main/java/org/springframework/integration/message/ErrorMessage.java +++ b/spring-integration-core/src/main/java/org/springframework/integration/message/ErrorMessage.java @@ -20,6 +20,7 @@ import java.util.Map; /** * A message implementation that accepts a {@link Throwable} payload. + * Once created this object is immutable. * * @author Mark Fisher * @author Oleg Zhurakousky diff --git a/spring-integration-core/src/main/java/org/springframework/integration/message/GenericMessage.java b/spring-integration-core/src/main/java/org/springframework/integration/message/GenericMessage.java index 0d2a9e9638..4874feabd2 100644 --- a/spring-integration-core/src/main/java/org/springframework/integration/message/GenericMessage.java +++ b/spring-integration-core/src/main/java/org/springframework/integration/message/GenericMessage.java @@ -27,6 +27,7 @@ import org.springframework.util.ObjectUtils; /** * Base Message class defining common properties such as id, payload, and headers. + * Once created this object is immutable. * * @author Mark Fisher */ From 3061aaa08dccbdb66b1cdbaa2cad3a7859250a54 Mon Sep 17 00:00:00 2001 From: Oleg Zhurakousky Date: Tue, 2 Nov 2010 10:28:54 -0400 Subject: [PATCH 05/82] INT-1552 general restructuring of the docs to introduce parts that are consistent with eip definitions --- docs/src/reference/docbook/index.xml | 141 ++++++++++++++++++------- docs/src/reference/docbook/message.xml | 2 +- 2 files changed, 102 insertions(+), 41 deletions(-) diff --git a/docs/src/reference/docbook/index.xml b/docs/src/reference/docbook/index.xml index 5b6086cc61..12876a4bb0 100644 --- a/docs/src/reference/docbook/index.xml +++ b/docs/src/reference/docbook/index.xml @@ -55,44 +55,105 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + Overview of Spring Integration Framework + + The Spring Integration Framework is a lightweight solution TODO + + + + + Core Messaging + + Core Messaging TODO + + + + Messaging Channels + + Message Channels TODO + + + + + + + Messaging Construction + + Message Construction TODO + + + + + + Messaging Routing + + Message Routing TODO + + + + + + + + + + Messaging Transformation + + Message Transformation TODO + + + + + Messaging Endpoints + + Message Endpoints TODO + + + + + + + + + System Management + + Message Endpoints TODO + + + + + + + Integration Adapters + + Adapters TODO + + + + + + + + + + + + + + + + + Appendices + + Appendices TODO + + + + + + + + diff --git a/docs/src/reference/docbook/message.xml b/docs/src/reference/docbook/message.xml index 7656b0b030..def77ba699 100644 --- a/docs/src/reference/docbook/message.xml +++ b/docs/src/reference/docbook/message.xml @@ -1,7 +1,7 @@ - Message Construction + Message The Spring Integration Message is a generic container for data. Any object can be provided as the payload, and each Message also includes headers containing From 01dbe1916e2dfdd2dfdd709a8561fd1719aa186e Mon Sep 17 00:00:00 2001 From: Oleg Zhurakousky Date: Tue, 2 Nov 2010 12:07:56 -0400 Subject: [PATCH 06/82] INT-1577 restructured documentation to be consistent with Spring-core and EIP documentation --- docs/src/reference/docbook/aggregator.xml | 4 +- docs/src/reference/docbook/bridge.xml | 4 +- docs/src/reference/docbook/chain.xml | 4 +- .../src/reference/docbook/channel-adapter.xml | 4 +- docs/src/reference/docbook/channel.xml | 4 +- docs/src/reference/docbook/delayer.xml | 4 +- docs/src/reference/docbook/endpoint.xml | 4 +- docs/src/reference/docbook/filter.xml | 4 +- docs/src/reference/docbook/gateway.xml | 4 +- docs/src/reference/docbook/groovy.xml | 4 +- docs/src/reference/docbook/index.xml | 62 +++---------------- docs/src/reference/docbook/jmx.xml | 4 +- .../docbook/message-construction.xml | 9 +++ .../src/reference/docbook/message-history.xml | 4 +- .../src/reference/docbook/message-routing.xml | 14 +++++ .../docbook/message-transformation.xml | 9 +++ docs/src/reference/docbook/message.xml | 4 +- .../reference/docbook/messaging-channels.xml | 11 ++++ .../reference/docbook/messaging-endpoints.xml | 13 ++++ docs/src/reference/docbook/resequencer.xml | 4 +- docs/src/reference/docbook/router.xml | 4 +- .../reference/docbook/service-activator.xml | 4 +- docs/src/reference/docbook/splitter.xml | 4 +- .../reference/docbook/system-management.xml | 10 +++ docs/src/reference/docbook/transformer.xml | 4 +- 25 files changed, 109 insertions(+), 91 deletions(-) create mode 100644 docs/src/reference/docbook/message-construction.xml create mode 100644 docs/src/reference/docbook/message-routing.xml create mode 100644 docs/src/reference/docbook/message-transformation.xml create mode 100644 docs/src/reference/docbook/messaging-channels.xml create mode 100644 docs/src/reference/docbook/messaging-endpoints.xml create mode 100644 docs/src/reference/docbook/system-management.xml diff --git a/docs/src/reference/docbook/aggregator.xml b/docs/src/reference/docbook/aggregator.xml index 4503c52671..585d3f30d8 100644 --- a/docs/src/reference/docbook/aggregator.xml +++ b/docs/src/reference/docbook/aggregator.xml @@ -1,5 +1,5 @@ - Aggregator @@ -622,4 +622,4 @@ the @MessageEndpoint is defined on the class, detected automatically through classpath scanning. - + diff --git a/docs/src/reference/docbook/bridge.xml b/docs/src/reference/docbook/bridge.xml index 105cfc76e6..6bfc6742cb 100644 --- a/docs/src/reference/docbook/bridge.xml +++ b/docs/src/reference/docbook/bridge.xml @@ -1,5 +1,5 @@ - Messaging Bridge @@ -56,4 +56,4 @@ - + diff --git a/docs/src/reference/docbook/chain.xml b/docs/src/reference/docbook/chain.xml index c82a01577a..1ae62b1d53 100644 --- a/docs/src/reference/docbook/chain.xml +++ b/docs/src/reference/docbook/chain.xml @@ -1,5 +1,5 @@ - Message Handler Chain @@ -111,4 +111,4 @@ When light version of <gateway> element is defined in the chain SI will co - + diff --git a/docs/src/reference/docbook/channel-adapter.xml b/docs/src/reference/docbook/channel-adapter.xml index c14d6db69f..fc18b04db8 100644 --- a/docs/src/reference/docbook/channel-adapter.xml +++ b/docs/src/reference/docbook/channel-adapter.xml @@ -1,7 +1,7 @@ - +
Channel Adapter A Channel Adapter is a Message Endpoint that enables connecting a single sender or receiver to a Message Channel. @@ -75,4 +75,4 @@
-
\ No newline at end of file + \ No newline at end of file diff --git a/docs/src/reference/docbook/channel.xml b/docs/src/reference/docbook/channel.xml index c4babca116..00a5ece6c2 100644 --- a/docs/src/reference/docbook/channel.xml +++ b/docs/src/reference/docbook/channel.xml @@ -1,5 +1,5 @@ - Message Channels @@ -599,4 +599,4 @@ public Message receive(final PollableChannel channel) { ... }]]> - + diff --git a/docs/src/reference/docbook/delayer.xml b/docs/src/reference/docbook/delayer.xml index 3a41f4d63a..dd4c42c2e0 100644 --- a/docs/src/reference/docbook/delayer.xml +++ b/docs/src/reference/docbook/delayer.xml @@ -1,5 +1,5 @@ - Delayer @@ -58,4 +58,4 @@ - + diff --git a/docs/src/reference/docbook/endpoint.xml b/docs/src/reference/docbook/endpoint.xml index de74cbc352..4d77f11768 100644 --- a/docs/src/reference/docbook/endpoint.xml +++ b/docs/src/reference/docbook/endpoint.xml @@ -1,5 +1,5 @@ - Message Endpoints @@ -346,4 +346,4 @@ any transaction configuration essentially allowing you to enhance the behavior o to - Section 25 - Task Execution and Scheduling of Spring reference manual. - + diff --git a/docs/src/reference/docbook/filter.xml b/docs/src/reference/docbook/filter.xml index c9bd8aeb1d..b31c71189d 100644 --- a/docs/src/reference/docbook/filter.xml +++ b/docs/src/reference/docbook/filter.xml @@ -1,5 +1,5 @@ - Filter @@ -128,4 +128,4 @@ to be treated as Message Channel names by a router component. - + diff --git a/docs/src/reference/docbook/gateway.xml b/docs/src/reference/docbook/gateway.xml index 12a88b2f27..a09aebe08a 100644 --- a/docs/src/reference/docbook/gateway.xml +++ b/docs/src/reference/docbook/gateway.xml @@ -1,5 +1,5 @@ - Inbound Messaging Gateways @@ -251,4 +251,4 @@ For a more detailed example, please refer to the async-gateway - + diff --git a/docs/src/reference/docbook/groovy.xml b/docs/src/reference/docbook/groovy.xml index d23bd712ba..979985e0d2 100644 --- a/docs/src/reference/docbook/groovy.xml +++ b/docs/src/reference/docbook/groovy.xml @@ -1,5 +1,5 @@ - Groovy support @@ -69,4 +69,4 @@ You see that script could be included inline or via location attrib - + diff --git a/docs/src/reference/docbook/index.xml b/docs/src/reference/docbook/index.xml index 12876a4bb0..f679ed3626 100644 --- a/docs/src/reference/docbook/index.xml +++ b/docs/src/reference/docbook/index.xml @@ -63,67 +63,19 @@ + Core Messaging Core Messaging TODO - - Messaging Channels - - Message Channels TODO - - - - - - - Messaging Construction - - Message Construction TODO - - - - - - Messaging Routing - - Message Routing TODO - - - - - - - - - - Messaging Transformation - - Message Transformation TODO - - - - - Messaging Endpoints - - Message Endpoints TODO - - - - - - - - - System Management - - Message Endpoints TODO - - - - + + + + + + Integration Adapters diff --git a/docs/src/reference/docbook/jmx.xml b/docs/src/reference/docbook/jmx.xml index d9802cd296..b3c27ead27 100644 --- a/docs/src/reference/docbook/jmx.xml +++ b/docs/src/reference/docbook/jmx.xml @@ -1,5 +1,5 @@ - JMX Support @@ -187,4 +187,4 @@ foundation is available, however, we will be able to extend the attributes and operations that are being exposed. - + diff --git a/docs/src/reference/docbook/message-construction.xml b/docs/src/reference/docbook/message-construction.xml new file mode 100644 index 0000000000..321021a299 --- /dev/null +++ b/docs/src/reference/docbook/message-construction.xml @@ -0,0 +1,9 @@ + + + Message Construction + + + + diff --git a/docs/src/reference/docbook/message-history.xml b/docs/src/reference/docbook/message-history.xml index 63857a403f..d6345c578d 100644 --- a/docs/src/reference/docbook/message-history.xml +++ b/docs/src/reference/docbook/message-history.xml @@ -1,5 +1,5 @@ - Message History @@ -61,4 +61,4 @@ assertEquals("sampleChain", chainHistory.get("name"));]]> be changed once written. Every attempt will end in exception. - + diff --git a/docs/src/reference/docbook/message-routing.xml b/docs/src/reference/docbook/message-routing.xml new file mode 100644 index 0000000000..b71b571da3 --- /dev/null +++ b/docs/src/reference/docbook/message-routing.xml @@ -0,0 +1,14 @@ + + + Message Routing + + + + + + + + + diff --git a/docs/src/reference/docbook/message-transformation.xml b/docs/src/reference/docbook/message-transformation.xml new file mode 100644 index 0000000000..c8644b35f4 --- /dev/null +++ b/docs/src/reference/docbook/message-transformation.xml @@ -0,0 +1,9 @@ + + + Message Transformation + + + + diff --git a/docs/src/reference/docbook/message.xml b/docs/src/reference/docbook/message.xml index def77ba699..2129313f02 100644 --- a/docs/src/reference/docbook/message.xml +++ b/docs/src/reference/docbook/message.xml @@ -1,5 +1,5 @@ - Message @@ -219,4 +219,4 @@ assertEquals(MessagePriority.HIGHEST, anotherMessage.getHeaders().getPriority()) - + diff --git a/docs/src/reference/docbook/messaging-channels.xml b/docs/src/reference/docbook/messaging-channels.xml new file mode 100644 index 0000000000..089245c31f --- /dev/null +++ b/docs/src/reference/docbook/messaging-channels.xml @@ -0,0 +1,11 @@ + + + Messaging Channels + + + + + + diff --git a/docs/src/reference/docbook/messaging-endpoints.xml b/docs/src/reference/docbook/messaging-endpoints.xml new file mode 100644 index 0000000000..faf9233bf9 --- /dev/null +++ b/docs/src/reference/docbook/messaging-endpoints.xml @@ -0,0 +1,13 @@ + + + Messaging Endpoints + + + + + + + + diff --git a/docs/src/reference/docbook/resequencer.xml b/docs/src/reference/docbook/resequencer.xml index 7c58816c8c..cd3a6572a0 100644 --- a/docs/src/reference/docbook/resequencer.xml +++ b/docs/src/reference/docbook/resequencer.xml @@ -1,5 +1,5 @@ - Resequencer @@ -123,4 +123,4 @@ Since there is no custom behavior to be implemented in Java classes for resequencers, there is no annotation support for it. - + diff --git a/docs/src/reference/docbook/router.xml b/docs/src/reference/docbook/router.xml index 1fcc281e77..4092462023 100644 --- a/docs/src/reference/docbook/router.xml +++ b/docs/src/reference/docbook/router.xml @@ -1,5 +1,5 @@ - Router @@ -402,4 +402,4 @@ public List<String> route(@Header("orderStatus") OrderStatus status) - + diff --git a/docs/src/reference/docbook/service-activator.xml b/docs/src/reference/docbook/service-activator.xml index 2325d17e54..4ccadc3f80 100644 --- a/docs/src/reference/docbook/service-activator.xml +++ b/docs/src/reference/docbook/service-activator.xml @@ -1,5 +1,5 @@ - Service Activator @@ -68,4 +68,4 @@ - + diff --git a/docs/src/reference/docbook/splitter.xml b/docs/src/reference/docbook/splitter.xml index b22ffe64b8..9f60a54202 100644 --- a/docs/src/reference/docbook/splitter.xml +++ b/docs/src/reference/docbook/splitter.xml @@ -1,5 +1,5 @@ - Splitter @@ -154,4 +154,4 @@ List<LineItem> extractItems(Order order) { } - + diff --git a/docs/src/reference/docbook/system-management.xml b/docs/src/reference/docbook/system-management.xml new file mode 100644 index 0000000000..a8f7342c0b --- /dev/null +++ b/docs/src/reference/docbook/system-management.xml @@ -0,0 +1,10 @@ + + + System Management + + + + + diff --git a/docs/src/reference/docbook/transformer.xml b/docs/src/reference/docbook/transformer.xml index 42014c7e67..f0a6341e90 100644 --- a/docs/src/reference/docbook/transformer.xml +++ b/docs/src/reference/docbook/transformer.xml @@ -1,5 +1,5 @@ - Transformer @@ -180,4 +180,4 @@ Order generateOrder(String productId, @Header("customerName") String customer) { - + From 7c6a53d7ffed60c98e900faea4fd962bef32a1bd Mon Sep 17 00:00:00 2001 From: Mark Fisher Date: Tue, 2 Nov 2010 14:45:40 -0400 Subject: [PATCH 07/82] formatting --- .../xml/result/DomResultFactory.java | 24 +++++++------ .../integration/xml/result/ResultFactory.java | 2 +- .../xml/result/StringResultFactory.java | 2 +- .../integration/xml/router/XPathRouter.java | 36 +++++++++---------- 4 files changed, 32 insertions(+), 32 deletions(-) diff --git a/spring-integration-xml/src/main/java/org/springframework/integration/xml/result/DomResultFactory.java b/spring-integration-xml/src/main/java/org/springframework/integration/xml/result/DomResultFactory.java index cf11733726..36efa6b620 100644 --- a/spring-integration-xml/src/main/java/org/springframework/integration/xml/result/DomResultFactory.java +++ b/spring-integration-xml/src/main/java/org/springframework/integration/xml/result/DomResultFactory.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2008 the original author or authors. + * Copyright 2002-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. @@ -29,32 +29,34 @@ import org.springframework.integration.MessagingException; */ public class DomResultFactory implements ResultFactory { - private final DocumentBuilderFactory docBuilderFactory; + private final DocumentBuilderFactory documentBuilderFactory; - public DomResultFactory(DocumentBuilderFactory docBuilderFactory) { - this.docBuilderFactory = docBuilderFactory; + + public DomResultFactory(DocumentBuilderFactory documentBuilderFactory) { + this.documentBuilderFactory = documentBuilderFactory; } public DomResultFactory() { - this.docBuilderFactory = DocumentBuilderFactory.newInstance(); - docBuilderFactory.setNamespaceAware(true); + DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); + factory.setNamespaceAware(true); + this.documentBuilderFactory = factory; } + public synchronized Result createResult(Object payload) { try { return new DOMResult(getNewDocumentBuilder().newDocument()); } catch (ParserConfigurationException e) { - throw new MessagingException("Failed to create Result for payload type [" + payload.getClass().getName() - + "]"); + throw new MessagingException("failed to create Result for payload type [" + + payload.getClass().getName() + "]"); } } protected DocumentBuilder getNewDocumentBuilder() throws ParserConfigurationException { - synchronized (docBuilderFactory) { - return docBuilderFactory.newDocumentBuilder(); + synchronized (this.documentBuilderFactory) { + return this.documentBuilderFactory.newDocumentBuilder(); } - } } diff --git a/spring-integration-xml/src/main/java/org/springframework/integration/xml/result/ResultFactory.java b/spring-integration-xml/src/main/java/org/springframework/integration/xml/result/ResultFactory.java index 287aa90f7e..e25122f0b3 100644 --- a/spring-integration-xml/src/main/java/org/springframework/integration/xml/result/ResultFactory.java +++ b/spring-integration-xml/src/main/java/org/springframework/integration/xml/result/ResultFactory.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2008 the original author or authors. + * Copyright 2002-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. diff --git a/spring-integration-xml/src/main/java/org/springframework/integration/xml/result/StringResultFactory.java b/spring-integration-xml/src/main/java/org/springframework/integration/xml/result/StringResultFactory.java index 0b28954a98..c955e3ec8d 100644 --- a/spring-integration-xml/src/main/java/org/springframework/integration/xml/result/StringResultFactory.java +++ b/spring-integration-xml/src/main/java/org/springframework/integration/xml/result/StringResultFactory.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2008 the original author or authors. + * Copyright 2002-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. diff --git a/spring-integration-xml/src/main/java/org/springframework/integration/xml/router/XPathRouter.java b/spring-integration-xml/src/main/java/org/springframework/integration/xml/router/XPathRouter.java index 23bc2720bc..5833613cc1 100644 --- a/spring-integration-xml/src/main/java/org/springframework/integration/xml/router/XPathRouter.java +++ b/spring-integration-xml/src/main/java/org/springframework/integration/xml/router/XPathRouter.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2008 the original author or authors. + * Copyright 2002-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. @@ -20,6 +20,9 @@ import java.util.HashMap; import java.util.List; import java.util.Map; +import org.w3c.dom.DOMException; +import org.w3c.dom.Node; + import org.springframework.integration.Message; import org.springframework.integration.router.AbstractMessageRouter; import org.springframework.integration.xml.DefaultXmlPayloadConverter; @@ -27,18 +30,15 @@ import org.springframework.integration.xml.XmlPayloadConverter; import org.springframework.xml.xpath.NodeMapper; import org.springframework.xml.xpath.XPathExpression; import org.springframework.xml.xpath.XPathExpressionFactory; -import org.w3c.dom.DOMException; -import org.w3c.dom.Node; /** - * Abstract base class for Message Routers that use - * {@link XPathExpression} evaluation to determine channel names. + * Message Router that uses {@link XPathExpression} evaluation to determine channel names. * * @author Jonas Partner * @author Oleg Zhurakousky */ public class XPathRouter extends AbstractMessageRouter { - + private volatile NodeMapper nodeMapper = new TextContentNodeMapper(); private final XPathExpression xPathExpression; @@ -50,8 +50,8 @@ public class XPathRouter extends AbstractMessageRouter { * Create a router that uses an XPath expression. The expression may * contain zero or more namespace prefixes. * - * @param expression - * @param namespaces + * @param expression the XPath expression as a String + * @param namespaces map of namespaces with prefixes as the map keys */ public XPathRouter(String expression, Map namespaces) { this.xPathExpression = XPathExpressionFactory.createXPathExpression(expression, namespaces); @@ -61,9 +61,9 @@ public class XPathRouter extends AbstractMessageRouter { * Create a router uses an XPath expression with one namespace. For example, * expression='/ns1:one/@type' prefix='ns1' namespace='www.example.org' * - * @param expression - * @param prefix - * @param namespace + * @param expression the XPath expression as a String + * @param prefix namespace prefix + * @param namespace namespace uri */ public XPathRouter(String expression, String prefix, String namespace) { Map namespaces = new HashMap(); @@ -75,7 +75,7 @@ public class XPathRouter extends AbstractMessageRouter { * Create a router that uses an XPath expression with no namespaces. * For example '/one/@type' * - * @param expression + * @param expression the XPath expression as a String */ public XPathRouter(String expression) { this.xPathExpression = XPathExpressionFactory.createXPathExpression(expression); @@ -84,7 +84,7 @@ public class XPathRouter extends AbstractMessageRouter { /** * Create a router that uses the provided XPath expression. * - * @param expression + * @param expression the XPath expression */ public XPathRouter(XPathExpression expression) { this.xPathExpression = expression; @@ -96,9 +96,7 @@ public class XPathRouter extends AbstractMessageRouter { } /** - * Converter used to convert payloads prior to XPath testing. - * - * @param converter + * Specify the Converter to use when converting payloads prior to XPath evaluation. */ public void setConverter(XmlPayloadConverter converter) { this.converter = converter; @@ -107,8 +105,8 @@ public class XPathRouter extends AbstractMessageRouter { protected XPathExpression getXPathExpression() { return this.xPathExpression; } - - public String getComponentType(){ + + public String getComponentType() { return "xml:xpath-router"; } @@ -125,6 +123,6 @@ public class XPathRouter extends AbstractMessageRouter { public Object mapNode(Node node, int nodeNum) throws DOMException { return node.getTextContent(); } - } + } From 117f3206cacb4f4ca02422da4eb3c332a5596707 Mon Sep 17 00:00:00 2001 From: Mark Fisher Date: Tue, 2 Nov 2010 15:18:32 -0400 Subject: [PATCH 08/82] INT-1578 added source/target compatibility setting, but it's not clear yet that it has an impact --- build.gradle | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/build.gradle b/build.gradle index f6e91faebc..327f7c663c 100644 --- a/build.gradle +++ b/build.gradle @@ -85,6 +85,10 @@ configure(javaprojects) { apply plugin: 'eclipse' // `gradle eclipse` to generate .classpath/.project apply plugin: 'idea' // `gradle idea` to generate .ipr/.iml + // ensure JDK 5 compatibility + sourceCompatibility=1.5 + targetCompatibility=1.5 + // set up dedicated directories for jars and source jars. // this makes it easier when putting together the distribution libsBinDir = new File(libsDir, 'bin') From acbfe9434ccd870fd02b3b00a382558b44d9eefd Mon Sep 17 00:00:00 2001 From: Oleg Zhurakousky Date: Tue, 2 Nov 2010 15:58:57 -0400 Subject: [PATCH 09/82] INT-1557 added initial documentation (OAuth, Connection INbound Adapters) for Twitter adapter --- docs/src/reference/docbook/index.xml | 19 +-- docs/src/reference/docbook/twitter.xml | 178 +++++++++++++++++++++++++ 2 files changed, 188 insertions(+), 9 deletions(-) create mode 100644 docs/src/reference/docbook/twitter.xml diff --git a/docs/src/reference/docbook/index.xml b/docs/src/reference/docbook/index.xml index f679ed3626..47cb8618a3 100644 --- a/docs/src/reference/docbook/index.xml +++ b/docs/src/reference/docbook/index.xml @@ -82,19 +82,20 @@ Adapters TODO + + + + + - - + - - - - - - - + + + + Appendices diff --git a/docs/src/reference/docbook/twitter.xml b/docs/src/reference/docbook/twitter.xml new file mode 100644 index 0000000000..1443d7007a --- /dev/null +++ b/docs/src/reference/docbook/twitter.xml @@ -0,0 +1,178 @@ + + + Twitter Adapter + + Spring Integration provides support for interacting with Twitter via Twitter adapters. With Twitter adapters you can both + receive and send Twitter messages. + +
+ Introduction + + Twitter is a social networking and microblogging service that enables its users to send and read messages known as tweets. + Tweets are text-based posts of up to 140 characters displayed on the author's profile page and delivered to the author's + subscribers who are known as followers. + + + + Current Twitter support is based on Twitter4J API, + however future version will be changed to use Spring Social + project as it is nearing its first release at the time of writing. + + + + Spring Integration provides a convenient namespace configuration to define Twitter artifacts. + + +
+ +
+ Twitter Connection and OAuth Configuration + + + Before using inbound or outbound Twitter adapters you must establish secured Twitter connection. This connection object + could be shared by all twitter adapters connected to a particular account. + + + Twitter uses OAuth - an authentication protocol that allows users to approve application to act on their behalf without + sharing their password. More information can be found at http://oauth.net/ or + in this article http://hueniverse.com/oauth/ from Hueniverse. + Please also see OAuth FAQ for more information about OAuth and Twitter. + + + In order to use OAuth authentication/authorization with Twitter you must create new Application on Twitter Developers site. + Follow the directions below to create a new application and obtain consumer keys and access token: + + + + + Go to http://dev.twitter.com/ + + + Click on Register an app link and fill out all required fields on the form provided; + set Application Type to Client and depending on the nature of your application select + Default Access Type as Read & Write or Read-only + and Submit the form. If everything is successful you'll be presented with the Consumer Key + and Consumer Secret. Copy both values in the safe place. + + + On the same page you should see My Access Token button on the side bar (right). + Click on it and you'll be presented with two more values: Access Token and Access Token Secret. + Copy these values in a safe place as well. + + + + + Twitter Connection + + + + Spring Integration provides a convenient namespace configuration to define Twitter Connection. As you can see form the + configuration below you configure Twitter connection via twitter-connection element while providing + OAuth attributes filling them with values you have obtained in the previous step. + + ]]> + The values above are not real + + + + However a more practical way to manage OAuth connection attributes would be via Spring's placeholder support by simply + creating a property file (e.g., oauth.properties): + + + +and configuring a property-placeholder pointing to he above property file: + + + +]]> + +
+ +
+ Twitter Inbound Adapters + + Twitter inbound adapters allow you to receive Twitter Messages. There are several types of twitter messages: + Types of Tweets + + + Current release of Spring Integration provides support for Public Messages, Direct Messages as well as Mention Messages + + + Every Inbound Twitter Channel Adapter is a Polling consumer which means you have to provide a poller + configuration. However, one important thing you must understand with regard to Twitter since its inner-workings are slightly + different then any other poling consumer. Twitter defines a concept of Rate Limiting. You can read more about + it here: Rate Limiting . In the nutshell Rate Limiting + is the way Twitter manages how often an application can poll for updates. Luckily for you you don't have to worry about it + since the special Rate limit aware polling thread is created when any Twitter adapter is started. This thread will + poll Messages (Tweets) from the Twitter account at the rate allowed by Twitter at the time (it may change after every poll). The Tweets + will be stored in the instance of the org.springframework.integration.store.MetadataStore which is a + strategy interface designed for storing various types of metadata (e.g., last retrieved tweet) to help components such as Twitter + to deal with duplicates. By default, Spring Integration will look for a bean of type org.springframework.integration.store.MetadataStore + in the ApplicationContext. If one found then it will be used, otherwise it will create a new instance of SimpleMetadataStore + which is a simple in-memory implementation that will only persist meta-data within the life-cycle of the application context + which means upon restart you may end up with duplicate entries. If you need to persist meta-data between Application Context + restarts, you may use PropertiesPersistingMetadataStore (property file based persister) or provide your + own implementation of the MetedataStore interface (e.g., JdbcMetadatStore) and configure it + as bean in the Application Context. + +]]> +The Poller that is configured as part of the any Inbound Twitter Adapter (see below) will simply poll from this MetadataStore + +
+ Inbound Update Channel Adapter + + This adapter allows you to receive updates from everyone you follow. + + +]]> + +
+ +
+ Inbound Direct Message Channel Adapter + + This adapter allows you to receive Twitter Messages that were sent directly to you + + +]]> + +
+ +
+ Inbound Mention Message Channel Adapter + + This adapter allows you to receive Twitter Messages that Mention you via @user + + +]]> + +
+ + As you can see the configuration of all of these adapters is very similar to other inbound adapters with one exception. + Each one needs to be injected with the twitter-connection. Once configured the Twitter Messages would be + encapsulated into a Spring Integration Message and sent to a channel specified via channel attribute. + Currently the Payload of the Message is twitter4j.DirectMessage for Inbound Direct Message Channel Adapter + or twitter4j.Status for Inbound Update Channel Adapter and + Inbound Mention Message Channel Adapter. + + + For example; to get the text from the twitter4j.DirectMessage or twitter4j.Status + simply invoke getText() method. For more information please refer to Twitter4J API + +
+
From 012d9df8f485375a1f1eec64a4dd344e6270d457 Mon Sep 17 00:00:00 2001 From: Oleg Zhurakousky Date: Tue, 2 Nov 2010 16:15:07 -0400 Subject: [PATCH 10/82] INT-1560, INT-1559 added placeholders for the docs for FTP, SFTP and FEED --- docs/src/reference/docbook/feed.xml | 14 ++++++++++++++ docs/src/reference/docbook/ftp.xml | 14 ++++++++++++++ docs/src/reference/docbook/index.xml | 3 +++ docs/src/reference/docbook/sftp.xml | 14 ++++++++++++++ 4 files changed, 45 insertions(+) create mode 100644 docs/src/reference/docbook/feed.xml create mode 100644 docs/src/reference/docbook/ftp.xml create mode 100644 docs/src/reference/docbook/sftp.xml diff --git a/docs/src/reference/docbook/feed.xml b/docs/src/reference/docbook/feed.xml new file mode 100644 index 0000000000..f897e0d2e7 --- /dev/null +++ b/docs/src/reference/docbook/feed.xml @@ -0,0 +1,14 @@ + + + Feed Adapter + + Spring Integration provides support for Feed (RSS, Atom) + +
+ Introduction + + TODO + +
+
diff --git a/docs/src/reference/docbook/ftp.xml b/docs/src/reference/docbook/ftp.xml new file mode 100644 index 0000000000..9e9df9d580 --- /dev/null +++ b/docs/src/reference/docbook/ftp.xml @@ -0,0 +1,14 @@ + + + FTP Adapter + + Spring Integration provides support for FTP + +
+ Introduction + + TODO + +
+
diff --git a/docs/src/reference/docbook/index.xml b/docs/src/reference/docbook/index.xml index 47cb8618a3..4938bffadd 100644 --- a/docs/src/reference/docbook/index.xml +++ b/docs/src/reference/docbook/index.xml @@ -83,7 +83,9 @@ Adapters TODO + + @@ -91,6 +93,7 @@ + diff --git a/docs/src/reference/docbook/sftp.xml b/docs/src/reference/docbook/sftp.xml new file mode 100644 index 0000000000..8c859c117b --- /dev/null +++ b/docs/src/reference/docbook/sftp.xml @@ -0,0 +1,14 @@ + + + SFTP Adapter + + Spring Integration provides support for SFTP + +
+ Introduction + + TODO + +
+
From 3490779396042a8b91a3331b227c238bb88cf34e Mon Sep 17 00:00:00 2001 From: Mark Fisher Date: Tue, 2 Nov 2010 17:03:40 -0400 Subject: [PATCH 11/82] polishing --- .../AbstractXPathMessageSelector.java | 20 +++--- .../BooleanTestXPathMessageSelector.java | 24 ++++--- .../StringValueTestXPathMessageSelector.java | 29 +++++---- .../XmlValidatingMessageSelector.java | 62 +++++++++++-------- .../xml/source/DomSourceFactory.java | 62 ++++++++++++------- 5 files changed, 109 insertions(+), 88 deletions(-) diff --git a/spring-integration-xml/src/main/java/org/springframework/integration/xml/selector/AbstractXPathMessageSelector.java b/spring-integration-xml/src/main/java/org/springframework/integration/xml/selector/AbstractXPathMessageSelector.java index 24c963e51d..af5d217642 100644 --- a/spring-integration-xml/src/main/java/org/springframework/integration/xml/selector/AbstractXPathMessageSelector.java +++ b/spring-integration-xml/src/main/java/org/springframework/integration/xml/selector/AbstractXPathMessageSelector.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2008 the original author or authors. + * Copyright 2002-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. @@ -34,20 +34,20 @@ public abstract class AbstractXPathMessageSelector implements MessageSelector { private final XPathExpression xPathExpresion; - private XmlPayloadConverter converter = new DefaultXmlPayloadConverter(); + private volatile XmlPayloadConverter converter = new DefaultXmlPayloadConverter(); /** - * @param xPathExpression simple String expression + * @param xPathExpression XPath expression as a String */ public AbstractXPathMessageSelector(String xPathExpression) { this.xPathExpresion = XPathExpressionFactory.createXPathExpression(xPathExpression); } /** - * @param xPathExpression - * @param prefix - * @param namespace + * @param xPathExpression XPath expression as a String + * @param prefix namespace prefix + * @param namespace namespace URI */ public AbstractXPathMessageSelector(String xPathExpression, String prefix, String namespace) { Map namespaces = new HashMap(); @@ -56,15 +56,15 @@ public abstract class AbstractXPathMessageSelector implements MessageSelector { } /** - * @param xPathExpression - * @param namespaces + * @param xPathExpression XPath expression as a String + * @param namespaces Map of namespaces with prefixes as the Map keys */ - public AbstractXPathMessageSelector(String xPathExpression, Map namespaces) { + public AbstractXPathMessageSelector(String xPathExpression, Map namespaces) { this.xPathExpresion = XPathExpressionFactory.createXPathExpression(xPathExpression, namespaces); } /** - * @param xPathExpression + * @param xPathExpression XPath expression */ public AbstractXPathMessageSelector(XPathExpression xPathExpression) { this.xPathExpresion = xPathExpression; diff --git a/spring-integration-xml/src/main/java/org/springframework/integration/xml/selector/BooleanTestXPathMessageSelector.java b/spring-integration-xml/src/main/java/org/springframework/integration/xml/selector/BooleanTestXPathMessageSelector.java index 638721aa20..adfc32132f 100644 --- a/spring-integration-xml/src/main/java/org/springframework/integration/xml/selector/BooleanTestXPathMessageSelector.java +++ b/spring-integration-xml/src/main/java/org/springframework/integration/xml/selector/BooleanTestXPathMessageSelector.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2008 the original author or authors. + * Copyright 2002-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. @@ -36,32 +36,30 @@ public class BooleanTestXPathMessageSelector extends AbstractXPathMessageSelecto /** * Create a boolean testing XPath {@link MessageSelector} supporting - * mutliple namespaces. + * multiple namespaces. * - * @param expression - * @param namespaces + * @param expression XPath expression as a String + * @param namespaces Map of namespaces where the keys are namespace prefixes */ public BooleanTestXPathMessageSelector(String expression, Map namespaces) { super(expression, namespaces); } /** - * Create a boolean testing XPath {@link MessageSelector} supporting a - * single namespace. + * Create a boolean testing XPath {@link MessageSelector} supporting a single namespace. * - * @param expression - * @param prefix - * @param namespace + * @param expression XPath expression as a String + * @param prefix namespace prefix + * @param namespace namespace URI */ public BooleanTestXPathMessageSelector(String expression, String prefix, String namespace) { super(expression, prefix, namespace); } /** - * Create a boolean testing XPath {@link MessageSelector} with no namespace - * support. + * Create a boolean testing XPath {@link MessageSelector} with no namespace support. * - * @param expression + * @param expression XPath expression as a String */ public BooleanTestXPathMessageSelector(String expression) { super(expression); @@ -71,7 +69,7 @@ public class BooleanTestXPathMessageSelector extends AbstractXPathMessageSelecto * Create a boolean testing XPath {@link MessageSelector} using the * provided {@link XPathExpression}. * - * @param expression + * @param expression XPath expression */ public BooleanTestXPathMessageSelector(XPathExpression expression) { super(expression); diff --git a/spring-integration-xml/src/main/java/org/springframework/integration/xml/selector/StringValueTestXPathMessageSelector.java b/spring-integration-xml/src/main/java/org/springframework/integration/xml/selector/StringValueTestXPathMessageSelector.java index bb4bb6a566..5972032d3f 100644 --- a/spring-integration-xml/src/main/java/org/springframework/integration/xml/selector/StringValueTestXPathMessageSelector.java +++ b/spring-integration-xml/src/main/java/org/springframework/integration/xml/selector/StringValueTestXPathMessageSelector.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2008 the original author or authors. + * Copyright 2002-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. @@ -39,12 +39,11 @@ public class StringValueTestXPathMessageSelector extends AbstractXPathMessageSel /** - * Create a selector which tests for the given value and supports multiple - * namespaces. + * Create a selector which tests for the given value and supports multiple namespaces. * - * @param expression - * @param namespaces - * @param valueToTestFor + * @param expression XPath expression as a String + * @param namespaces Map of namespaces where the keys are namespace prefixes + * @param valueToTestFor value to test for */ public StringValueTestXPathMessageSelector(String expression, Map namespaces, String valueToTestFor) { super(expression, namespaces); @@ -54,10 +53,10 @@ public class StringValueTestXPathMessageSelector extends AbstractXPathMessageSel /** * Creates a single namespace Xpath selector. * - * @param expression - * @param prefix - * @param namespace - * @param valueToTestFor + * @param expression XPath expression as a String + * @param prefix namespace prefix + * @param namespace namespace URI + * @param valueToTestFor value to test for */ public StringValueTestXPathMessageSelector(String expression, String prefix, String namespace, String valueToTestFor) { super(expression, prefix, namespace); @@ -65,10 +64,10 @@ public class StringValueTestXPathMessageSelector extends AbstractXPathMessageSel } /** - * Creates non-namespaced testing selector. + * Creates a non-namespaced testing selector. * - * @param expression - * @param valueToTestFor + * @param expression XPath expression as a String + * @param valueToTestFor value to test for */ public StringValueTestXPathMessageSelector(String expression, String valueToTestFor) { super(expression); @@ -78,8 +77,8 @@ public class StringValueTestXPathMessageSelector extends AbstractXPathMessageSel /** * Creates a selector with the provided {@link XPathExpression}. * - * @param expression - * @param valueToTestFor + * @param expression XPath expression + * @param valueToTestFor value to test for */ public StringValueTestXPathMessageSelector(XPathExpression expression, String valueToTestFor) { super(expression); diff --git a/spring-integration-xml/src/main/java/org/springframework/integration/xml/selector/XmlValidatingMessageSelector.java b/spring-integration-xml/src/main/java/org/springframework/integration/xml/selector/XmlValidatingMessageSelector.java index 471f021c25..5639dc9641 100644 --- a/spring-integration-xml/src/main/java/org/springframework/integration/xml/selector/XmlValidatingMessageSelector.java +++ b/spring-integration-xml/src/main/java/org/springframework/integration/xml/selector/XmlValidatingMessageSelector.java @@ -18,6 +18,10 @@ package org.springframework.integration.xml.selector; import java.io.IOException; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.xml.sax.SAXParseException; + import org.springframework.core.io.Resource; import org.springframework.integration.Message; import org.springframework.integration.MessageHandlingException; @@ -32,70 +36,76 @@ import org.springframework.util.ObjectUtils; import org.springframework.util.StringUtils; import org.springframework.xml.validation.XmlValidator; import org.springframework.xml.validation.XmlValidatorFactory; -import org.xml.sax.SAXParseException; + /** - * * @author Oleg Zhurakousky * @since 2.0 - * */ public class XmlValidatingMessageSelector implements MessageSelector { - + + private final Log logger = LogFactory.getLog(this.getClass()); + private final XmlValidator xmlValidator; - + private volatile boolean throwExceptionOnRejection; private volatile XmlPayloadConverter converter = new DefaultXmlPayloadConverter(); - - public XmlValidatingMessageSelector(XmlValidator xmlValidator) throws Exception{ - Assert.notNull(xmlValidator, "XmlValidator can not be 'null'"); + + + public XmlValidatingMessageSelector(XmlValidator xmlValidator) { + Assert.notNull(xmlValidator, "XmlValidator must not be null"); this.xmlValidator = xmlValidator; } + /** - * Will create this selector with default {@link XmlValidator} which - * will be initialized with 'schema' location as {@link Resource} and 'schemaType' as - * either {@link XmlValidatorFactory#SCHEMA_W3C_XML} or {@link XmlValidatorFactory#SCHEMA_RELAX_NG}. + * Creates a selector with a default {@link XmlValidator}. The validator will be initialized with + * the provided 'schema' location {@link Resource} and 'schemaType'. The valid options for schema + * type are {@link XmlValidatorFactory#SCHEMA_W3C_XML} or {@link XmlValidatorFactory#SCHEMA_RELAX_NG}. * If no 'schemaType' is provided it will default to {@link XmlValidatorFactory#SCHEMA_W3C_XML}; * - * @param schema - * @param schemaType - * @throws IOException + * @throws IOException if the XmlValidatorFactory fails to create a validator */ public XmlValidatingMessageSelector(Resource schema, String schemaType) throws IOException { Assert.notNull(schema, "You must provide XML schema location to perform validation"); - if (!StringUtils.hasText(schemaType)){ + if (!StringUtils.hasText(schemaType)) { schemaType = XmlValidatorFactory.SCHEMA_W3C_XML; } this.xmlValidator = XmlValidatorFactory.createValidator(schema, schemaType); } - + + public void setThrowExceptionOnRejection(boolean throwExceptionOnRejection) { this.throwExceptionOnRejection = throwExceptionOnRejection; } - + /** - * Converter used to convert payloads prior to validation - * - * @param converter + * Specify the Converter to use when converting payloads prior to validation. */ public void setConverter(XmlPayloadConverter converter) { Assert.notNull(converter, "'converter' must not be null"); this.converter = converter; } - + @SuppressWarnings("unchecked") public boolean accept(Message message) { SAXParseException[] validationExceptions = null; try { - validationExceptions = xmlValidator.validate(converter.convertToSource(message.getPayload())); - } catch (Exception e) { + validationExceptions = this.xmlValidator.validate(this.converter.convertToSource(message.getPayload())); + } + catch (Exception e) { throw new MessageHandlingException(message, e); } boolean validationSuccess = ObjectUtils.isEmpty(validationExceptions); - if (!validationSuccess && throwExceptionOnRejection){ - throw new MessageRejectedException(message, "Message was rejected due to XML Validation errors", - new AggregatedXmlMessageValidationException(CollectionUtils.arrayToList(validationExceptions))); + if (!validationSuccess) { + if (this.throwExceptionOnRejection) { + throw new MessageRejectedException(message, "Message was rejected due to XML Validation errors", + new AggregatedXmlMessageValidationException(CollectionUtils.arrayToList(validationExceptions))); + } + if (logger.isDebugEnabled()) { + logger.debug("Message was rejected due to XML Validation errors"); + } } return validationSuccess; } + } diff --git a/spring-integration-xml/src/main/java/org/springframework/integration/xml/source/DomSourceFactory.java b/spring-integration-xml/src/main/java/org/springframework/integration/xml/source/DomSourceFactory.java index 811826c7a4..979e7ad674 100644 --- a/spring-integration-xml/src/main/java/org/springframework/integration/xml/source/DomSourceFactory.java +++ b/spring-integration-xml/src/main/java/org/springframework/integration/xml/source/DomSourceFactory.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2008 the original author or authors. + * Copyright 2002-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. @@ -16,6 +16,7 @@ package org.springframework.integration.xml.source; +import java.io.File; import java.io.StringReader; import javax.xml.parsers.DocumentBuilder; @@ -24,31 +25,34 @@ import javax.xml.parsers.ParserConfigurationException; import javax.xml.transform.Source; import javax.xml.transform.dom.DOMSource; -import org.springframework.integration.MessagingException; - import org.w3c.dom.Document; import org.xml.sax.InputSource; +import org.springframework.integration.MessagingException; + /** - * {@link SourceFactory} implementation which supports creation of a - * {@link DOMSource} from a {@link Document} or {@link String} payload. + * {@link SourceFactory} implementation which supports creation of a {@link DOMSource} + * from a {@link Document}, {@link File} or {@link String} payload. * * @author Jonas Partner * @author Mark Fisher */ public class DomSourceFactory implements SourceFactory { - private final DocumentBuilderFactory docBuilderFactory; + private final DocumentBuilderFactory documentBuilderFactory; + public DomSourceFactory() { - this.docBuilderFactory = DocumentBuilderFactory.newInstance(); - this.docBuilderFactory.setNamespaceAware(true); + DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); + factory.setNamespaceAware(true); + this.documentBuilderFactory = factory; } - public DomSourceFactory(DocumentBuilderFactory docBuilderFactory) { - this.docBuilderFactory = docBuilderFactory; + public DomSourceFactory(DocumentBuilderFactory documentBuilderFactory) { + this.documentBuilderFactory = documentBuilderFactory; } + public Source createSource(Object payload) { Source source = null; if (payload instanceof Document) { @@ -57,34 +61,44 @@ public class DomSourceFactory implements SourceFactory { else if (payload instanceof String) { source = createDomSourceForString((String) payload); } - + else if (payload instanceof File) { + source = createDomSourceForFile((File) payload); + } if (source == null) { - throw new MessagingException("Failed to create Source for payload type [" + payload.getClass().getName() - + "]"); + throw new MessagingException("failed to create Source for payload type [" + + payload.getClass().getName() + "]"); } return source; } - protected DOMSource createDomSourceForDocument(Document document) { - DOMSource source = new DOMSource(document.getDocumentElement()); - return source; + private DOMSource createDomSourceForDocument(Document document) { + return new DOMSource(document.getDocumentElement()); } - protected DOMSource createDomSourceForString(String s) { + private DOMSource createDomSourceForString(String s) { try { - Document doc = getNewDocumentBuilder().parse(new InputSource(new StringReader(s))); - DOMSource source = new DOMSource(doc.getDocumentElement()); - return source; + Document document = getNewDocumentBuilder().parse(new InputSource(new StringReader(s))); + return new DOMSource(document.getDocumentElement()); } catch (Exception e) { - throw new MessagingException("Exception creating DOMSource", e); + throw new MessagingException("failed to create DOMSource for String payload", e); + } + } + + private DOMSource createDomSourceForFile(File file) { + try { + Document document = this.getNewDocumentBuilder().parse(file); + return new DOMSource(document.getDocumentElement()); + } + catch (Exception e) { + throw new MessagingException("failed to create DOMSource for File payload", e); } } protected DocumentBuilder getNewDocumentBuilder() throws ParserConfigurationException { - synchronized (docBuilderFactory) { - return docBuilderFactory.newDocumentBuilder(); + synchronized (this.documentBuilderFactory) { + return documentBuilderFactory.newDocumentBuilder(); } - } + } From b3456bf09869b036581c7bbbcca9869cf2f3ecbc Mon Sep 17 00:00:00 2001 From: Mark Fisher Date: Tue, 2 Nov 2010 17:18:27 -0400 Subject: [PATCH 12/82] polishing --- .../xml/source/DomSourceFactory.java | 2 +- .../xml/source/StringSourceFactory.java | 64 ++++++++++++------- 2 files changed, 43 insertions(+), 23 deletions(-) diff --git a/spring-integration-xml/src/main/java/org/springframework/integration/xml/source/DomSourceFactory.java b/spring-integration-xml/src/main/java/org/springframework/integration/xml/source/DomSourceFactory.java index 979e7ad674..5e9675a1ca 100644 --- a/spring-integration-xml/src/main/java/org/springframework/integration/xml/source/DomSourceFactory.java +++ b/spring-integration-xml/src/main/java/org/springframework/integration/xml/source/DomSourceFactory.java @@ -95,7 +95,7 @@ public class DomSourceFactory implements SourceFactory { } } - protected DocumentBuilder getNewDocumentBuilder() throws ParserConfigurationException { + private DocumentBuilder getNewDocumentBuilder() throws ParserConfigurationException { synchronized (this.documentBuilderFactory) { return documentBuilderFactory.newDocumentBuilder(); } diff --git a/spring-integration-xml/src/main/java/org/springframework/integration/xml/source/StringSourceFactory.java b/spring-integration-xml/src/main/java/org/springframework/integration/xml/source/StringSourceFactory.java index c15ad6e947..54a65210dc 100644 --- a/spring-integration-xml/src/main/java/org/springframework/integration/xml/source/StringSourceFactory.java +++ b/spring-integration-xml/src/main/java/org/springframework/integration/xml/source/StringSourceFactory.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2007 the original author or authors. + * Copyright 2002-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. @@ -13,29 +13,36 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.springframework.integration.xml.source; +import java.io.File; +import java.io.FileReader; + import javax.xml.transform.Source; import javax.xml.transform.Transformer; import javax.xml.transform.TransformerFactory; import javax.xml.transform.dom.DOMSource; -import org.springframework.integration.MessagingException; -import org.springframework.xml.transform.StringResult; -import org.springframework.xml.transform.StringSource; import org.w3c.dom.Document; +import org.springframework.integration.MessagingException; +import org.springframework.util.FileCopyUtils; +import org.springframework.xml.transform.StringResult; +import org.springframework.xml.transform.StringSource; + /** - * {@link SourceFactory} implementation which supports creation of a - * {@link StringSource} from either a {@link Document} or {@link String} payload + * {@link SourceFactory} implementation which supports creation of a {@link StringSource} + * from a {@link Document}, {@link File} or {@link String} payload * * @author Jonas Partner - * + * @author Mark Fisher */ public class StringSourceFactory implements SourceFactory { private final TransformerFactory transformerFactory; + public StringSourceFactory() { this(TransformerFactory.newInstance()); } @@ -44,39 +51,52 @@ public class StringSourceFactory implements SourceFactory { this.transformerFactory = transformerFactory; } + public Source createSource(Object payload) { Source source = null; - if (payload instanceof Document) { - source = createStringSourceForDocument((Document) payload); - } else if (payload instanceof String) { + if (payload instanceof String) { source = new StringSource((String) payload); } - + else if (payload instanceof Document) { + source = createStringSourceForDocument((Document) payload); + } + else if (payload instanceof File) { + source = createStringSourceForFile((File) payload); + } if (source == null) { - throw new MessagingException( - "Failed to create Source for payload type [" - + payload.getClass().getName() + "]"); + throw new MessagingException("Failed to create Source for payload type [" + + payload.getClass().getName() + "]"); } return source; - } - protected StringSource createStringSourceForDocument(Document doc) { + private StringSource createStringSourceForDocument(Document document) { try { StringResult result = new StringResult(); Transformer transformer = getTransformer(); - transformer.transform(new DOMSource(doc), result); + transformer.transform(new DOMSource(document), result); return new StringSource(result.toString()); - } catch (Exception e) { - throw new MessagingException( - "Exception creating StringSource from document", e); + } + catch (Exception e) { + throw new MessagingException("failed to create StringSource from document", e); } } - protected synchronized Transformer getTransformer() { + private StringSource createStringSourceForFile(File file) { + try { + String content = FileCopyUtils.copyToString(new FileReader(file)); + return new StringSource(content); + } + catch (Exception e) { + throw new MessagingException("failed to create StringSource from file", e); + } + } + + private synchronized Transformer getTransformer() { try { return transformerFactory.newTransformer(); - } catch (Exception e) { + } + catch (Exception e) { throw new MessagingException("Exception creating transformer", e); } } From 55941036e4d6c83c4d748b6a8bd78be1adda419b Mon Sep 17 00:00:00 2001 From: Mark Fisher Date: Tue, 2 Nov 2010 17:41:06 -0400 Subject: [PATCH 13/82] polishing --- .../xml/splitter/XPathMessageSplitter.java | 60 ++++++++----------- 1 file changed, 26 insertions(+), 34 deletions(-) diff --git a/spring-integration-xml/src/main/java/org/springframework/integration/xml/splitter/XPathMessageSplitter.java b/spring-integration-xml/src/main/java/org/springframework/integration/xml/splitter/XPathMessageSplitter.java index 44eeb9d248..35a3a0035b 100644 --- a/spring-integration-xml/src/main/java/org/springframework/integration/xml/splitter/XPathMessageSplitter.java +++ b/spring-integration-xml/src/main/java/org/springframework/integration/xml/splitter/XPathMessageSplitter.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2009 the original author or authors. + * Copyright 2002-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. @@ -16,6 +16,7 @@ package org.springframework.integration.xml.splitter; +import java.io.File; import java.util.ArrayList; import java.util.HashMap; import java.util.List; @@ -25,9 +26,7 @@ import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; import javax.xml.transform.Transformer; -import javax.xml.transform.TransformerException; import javax.xml.transform.TransformerFactory; -import javax.xml.transform.TransformerFactoryConfigurationError; import javax.xml.transform.dom.DOMSource; import org.w3c.dom.Document; @@ -46,12 +45,13 @@ import org.springframework.xml.xpath.XPathExpressionFactory; /** * Message Splitter that uses an {@link XPathExpression} to split a - * {@link Document} or {@link String} payload into a {@link NodeList}. The - * return value will be either Strings or {@link Node}s depending on the + * {@link Document}, {@link File} or {@link String} payload into a {@link NodeList}. + * The return value will be either Strings or {@link Node}s depending on the * received payload type. Additionally, node types will be converted to * Documents if the 'createDocuments' property is set to true. * * @author Jonas Partner + * @author Mark Fisher */ public class XPathMessageSplitter extends AbstractMessageSplitter { @@ -83,6 +83,10 @@ public class XPathMessageSplitter extends AbstractMessageSplitter { this.createDocuments = createDocuments; } + public String getComponentType() { + return "xml:xpath-splitter"; + } + public void setDocumentBuilder(DocumentBuilderFactory documentBuilderFactory) { Assert.notNull(documentBuilderFactory, "DocumentBuilderFactory must not be null"); this.documentBuilderFactory = documentBuilderFactory; @@ -99,17 +103,12 @@ public class XPathMessageSplitter extends AbstractMessageSplitter { Object payload = message.getPayload(); Object result = null; if (payload instanceof Node) { - result = splitNodePayload((Node) payload, message); - } - else if (payload instanceof String) { - payload = xmlPayloadConverter.convertToDocument(payload); - result = splitStringPayload(message); + result = splitNode((Node) payload); } else { - throw new IllegalArgumentException( - "Unsupported payload type [" + payload.getClass().getName() - + "]. The XPathMessageSplitter only accepts [" + Node.class.getName() - + "] or [java.lang.String] typed payloads."); + Document document = this.xmlPayloadConverter.convertToDocument(payload); + Assert.notNull(document, "unsupported payload type [" + payload.getClass().getName() + "]"); + result = splitDocument(document); } return result; } @@ -121,10 +120,8 @@ public class XPathMessageSplitter extends AbstractMessageSplitter { } } - private Object splitStringPayload(Message message) throws ParserConfigurationException, - TransformerFactoryConfigurationError, TransformerException { - Node node = xmlPayloadConverter.convertToDocument(message.getPayload()); - List nodes = splitNodePayload(node, message); + private Object splitDocument(Document document) throws Exception { + List nodes = splitNode(document); Transformer transformer = TransformerFactory.newInstance().newTransformer(); List splitStrings = new ArrayList(nodes.size()); for (Node nodeFromList : nodes) { @@ -136,37 +133,32 @@ public class XPathMessageSplitter extends AbstractMessageSplitter { } @SuppressWarnings("unchecked") - protected List splitNodePayload(Node node, Message message) throws ParserConfigurationException { - List nodeList = xpathExpression.evaluateAsNodeList(node); + private List splitNode(Node node) throws ParserConfigurationException { + List nodeList = this.xpathExpression.evaluateAsNodeList(node); if (nodeList.size() == 0) { - throw new MessagingException(message, "Could not split message with XPath " + xpathExpression); + throw new IllegalArgumentException("failed to split message with XPath expression: " + this.xpathExpression); } if (this.createDocuments) { return convertNodesToDocuments(nodeList); } return nodeList; - } - private List convertNodesToDocuments(List nodeList) throws ParserConfigurationException { + private List convertNodesToDocuments(List nodes) throws ParserConfigurationException { DocumentBuilder documentBuilder = this.getNewDocumentBuilder(); - List docList = new ArrayList(nodeList.size()); - for (Node node : nodeList) { - Document doc = documentBuilder.newDocument(); - doc.appendChild(doc.importNode(node, true)); - docList.add(doc); + List documents = new ArrayList(nodes.size()); + for (Node node : nodes) { + Document document = documentBuilder.newDocument(); + document.appendChild(document.importNode(node, true)); + documents.add(document); } - return docList; + return documents; } - protected DocumentBuilder getNewDocumentBuilder() throws ParserConfigurationException { + private DocumentBuilder getNewDocumentBuilder() throws ParserConfigurationException { synchronized (this.documentBuilderFactory) { return this.documentBuilderFactory.newDocumentBuilder(); } } - - public String getComponentType(){ - return "xml:xpath-splitter"; - } } From d3cfac25fecfbc26fbd429aabdb1a97dac7a0f63 Mon Sep 17 00:00:00 2001 From: Mark Fisher Date: Tue, 2 Nov 2010 18:33:41 -0400 Subject: [PATCH 14/82] polishing, also fixed concurrency issue in XsltPayloadTransfomer.buildTransformer() method (assigning rootObject to instance var SpEL EvaluationContext) --- .../transformer/MarshallingTransformer.java | 8 +- .../ResultToDocumentTransformer.java | 37 ++--- .../ResultToStringTransformer.java | 59 +++----- .../xml/transformer/ResultTransformer.java | 10 +- .../SourceCreatingTransformer.java | 3 +- .../transformer/UnmarshallingTransformer.java | 23 ++- .../xml/transformer/XPathHeaderEnricher.java | 4 +- .../xml/transformer/XsltHeaders.java | 35 ----- .../transformer/XsltPayloadTransformer.java | 134 +++++++++--------- .../xml/xpath/XPathEvaluationType.java | 67 ++++++--- 10 files changed, 184 insertions(+), 196 deletions(-) delete mode 100644 spring-integration-xml/src/main/java/org/springframework/integration/xml/transformer/XsltHeaders.java diff --git a/spring-integration-xml/src/main/java/org/springframework/integration/xml/transformer/MarshallingTransformer.java b/spring-integration-xml/src/main/java/org/springframework/integration/xml/transformer/MarshallingTransformer.java index 0c4e2e497e..c5a24f461c 100644 --- a/spring-integration-xml/src/main/java/org/springframework/integration/xml/transformer/MarshallingTransformer.java +++ b/spring-integration-xml/src/main/java/org/springframework/integration/xml/transformer/MarshallingTransformer.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2009 the original author or authors. + * Copyright 2002-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. @@ -46,8 +46,7 @@ public class MarshallingTransformer extends AbstractTransformer { private volatile boolean extractPayload = true; - public MarshallingTransformer(Marshaller marshaller, ResultTransformer resultTransformer) - throws ParserConfigurationException { + public MarshallingTransformer(Marshaller marshaller, ResultTransformer resultTransformer) throws ParserConfigurationException { Assert.notNull(marshaller, "a marshaller is required"); this.marshaller = marshaller; this.resultTransformer = resultTransformer; @@ -89,9 +88,6 @@ public class MarshallingTransformer extends AbstractTransformer { catch (IOException e) { throw new MessagingException("Failed to marshal payload", e); } - if (transformedPayload == null) { - throw new MessagingException("Failed to transform payload"); - } if (this.resultTransformer != null) { transformedPayload = this.resultTransformer.transformResult(result); } diff --git a/spring-integration-xml/src/main/java/org/springframework/integration/xml/transformer/ResultToDocumentTransformer.java b/spring-integration-xml/src/main/java/org/springframework/integration/xml/transformer/ResultToDocumentTransformer.java index 1267116a07..5e13461a5a 100644 --- a/spring-integration-xml/src/main/java/org/springframework/integration/xml/transformer/ResultToDocumentTransformer.java +++ b/spring-integration-xml/src/main/java/org/springframework/integration/xml/transformer/ResultToDocumentTransformer.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2008 the original author or authors. + * Copyright 2002-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. @@ -24,11 +24,12 @@ import javax.xml.parsers.ParserConfigurationException; import javax.xml.transform.Result; import javax.xml.transform.dom.DOMResult; -import org.springframework.integration.MessagingException; -import org.springframework.xml.transform.StringResult; import org.w3c.dom.Document; import org.xml.sax.InputSource; +import org.springframework.integration.MessagingException; +import org.springframework.xml.transform.StringResult; + /** * Creates a {@link Document} from a {@link Result} payload. Supports * {@link DOMResult} and {@link StringResult} implementations. @@ -40,6 +41,7 @@ public class ResultToDocumentTransformer implements ResultTransformer { // Not guaranteed to be thread safe private final DocumentBuilderFactory documentBuilderFactory; + public ResultToDocumentTransformer(DocumentBuilderFactory documentBuilderFactory) { this.documentBuilderFactory = documentBuilderFactory; } @@ -49,40 +51,41 @@ public class ResultToDocumentTransformer implements ResultTransformer { this.documentBuilderFactory.setNamespaceAware(true); } - public Object transformResult(Result res) { - Document doc = null; - if (DOMResult.class.isAssignableFrom(res.getClass())) { - doc = createDocumentFromDomResult((DOMResult) res); + + public Object transformResult(Result result) { + Document document = null; + if (DOMResult.class.isAssignableFrom(result.getClass())) { + document = createDocumentFromDomResult((DOMResult) result); } - else if (StringResult.class.isAssignableFrom(res.getClass())) { - doc = createDocumentFromStringResult((StringResult) res); + else if (StringResult.class.isAssignableFrom(result.getClass())) { + document = createDocumentFromStringResult((StringResult) result); } else { - throw new MessagingException("Failed to create document from payload type [" + res.getClass().getName() - + "]"); + throw new MessagingException("failed to create document from payload type [" + + result.getClass().getName() + "]"); } - return doc; + return document; } - protected Document createDocumentFromDomResult(DOMResult domResult) { + private Document createDocumentFromDomResult(DOMResult domResult) { return (Document) domResult.getNode(); } - protected Document createDocumentFromStringResult(StringResult stringResult) { + private Document createDocumentFromStringResult(StringResult stringResult) { try { return getDocumentBuilder().parse(new InputSource(new StringReader(stringResult.toString()))); } catch (Exception e) { - throw new MessagingException("Failed to create Document from StringResult payload", e); + throw new MessagingException("failed to create Document from StringResult payload", e); } } - protected synchronized DocumentBuilder getDocumentBuilder() { + private synchronized DocumentBuilder getDocumentBuilder() { try { return this.documentBuilderFactory.newDocumentBuilder(); } catch (ParserConfigurationException e) { - throw new MessagingException("Failed to create a new DocumentBuilder", e); + throw new MessagingException("failed to create a new DocumentBuilder", e); } } diff --git a/spring-integration-xml/src/main/java/org/springframework/integration/xml/transformer/ResultToStringTransformer.java b/spring-integration-xml/src/main/java/org/springframework/integration/xml/transformer/ResultToStringTransformer.java index 33d9249115..3382864806 100644 --- a/spring-integration-xml/src/main/java/org/springframework/integration/xml/transformer/ResultToStringTransformer.java +++ b/spring-integration-xml/src/main/java/org/springframework/integration/xml/transformer/ResultToStringTransformer.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2007 the original author or authors. + * Copyright 2002-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. @@ -13,11 +13,9 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.springframework.integration.xml.transformer; -import javax.xml.parsers.DocumentBuilder; -import javax.xml.parsers.DocumentBuilderFactory; -import javax.xml.parsers.ParserConfigurationException; import javax.xml.transform.Result; import javax.xml.transform.Transformer; import javax.xml.transform.TransformerConfigurationException; @@ -30,62 +28,49 @@ import org.springframework.integration.MessagingException; import org.springframework.xml.transform.StringResult; /** - * Converts the passed {@link Result} to an instance of {@link String} - * + * Converts the passed {@link Result} to an instance of {@link String}. * Supports {@link StringResult} and {@link DOMResult} * * @author Jonas Partner - * + * @author Mark Fisher */ public class ResultToStringTransformer implements ResultTransformer { - private DocumentBuilderFactory docBuilderFactory; + private final TransformerFactory transformerFactory; - private TransformerFactory transformerFactory; public ResultToStringTransformer() { - this.docBuilderFactory = DocumentBuilderFactory.newInstance(); - this.docBuilderFactory.setNamespaceAware(true); this.transformerFactory = TransformerFactory.newInstance(); } - protected Transformer getNewTransformer() - throws TransformerConfigurationException { - synchronized (transformerFactory) { - return transformerFactory.newTransformer(); - } - } - public Object transformResult(Result res) { + public Object transformResult(Result result) { String returnString = null; - if (res instanceof StringResult) { - returnString = ((StringResult) res).toString(); - } else if (res instanceof DOMResult) { + if (result instanceof StringResult) { + returnString = ((StringResult) result).toString(); + } + else if (result instanceof DOMResult) { try { - StringResult strRes = new StringResult(); - getNewTransformer().transform( - new DOMSource(((DOMResult) res).getNode()), strRes); - returnString = strRes.toString(); - } catch (TransformerException transE) { - throw new MessagingException( - "Transformation from DOMSOurce failed", transE); + StringResult stringResult = new StringResult(); + this.getNewTransformer().transform( + new DOMSource(((DOMResult) result).getNode()), stringResult); + returnString = stringResult.toString(); + } + catch (TransformerException e) { + throw new MessagingException("failed to transform from DOMSource failed", e); } } - if (returnString == null) { - throw new MessagingException("Could not convert Result type " - + res.getClass().getName() + " to string"); + throw new MessagingException("failed to convert Result type [" + + result.getClass().getName() + "] to string"); } - return returnString; } - protected DocumentBuilder getNewDocumentBuilder() - throws ParserConfigurationException { - synchronized (docBuilderFactory) { - return docBuilderFactory.newDocumentBuilder(); + private Transformer getNewTransformer() throws TransformerConfigurationException { + synchronized (this.transformerFactory) { + return this.transformerFactory.newTransformer(); } - } } diff --git a/spring-integration-xml/src/main/java/org/springframework/integration/xml/transformer/ResultTransformer.java b/spring-integration-xml/src/main/java/org/springframework/integration/xml/transformer/ResultTransformer.java index c2769349e8..62c73b0a6b 100644 --- a/spring-integration-xml/src/main/java/org/springframework/integration/xml/transformer/ResultTransformer.java +++ b/spring-integration-xml/src/main/java/org/springframework/integration/xml/transformer/ResultTransformer.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2007 the original author or authors. + * Copyright 2002-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. @@ -13,10 +13,16 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.springframework.integration.xml.transformer; +import javax.xml.transform.Result; + +/** + * @author Jonas Partner + */ public interface ResultTransformer { - Object transformResult(javax.xml.transform.Result res); + Object transformResult(Result result); } diff --git a/spring-integration-xml/src/main/java/org/springframework/integration/xml/transformer/SourceCreatingTransformer.java b/spring-integration-xml/src/main/java/org/springframework/integration/xml/transformer/SourceCreatingTransformer.java index b2fd320f7c..539cad4293 100644 --- a/spring-integration-xml/src/main/java/org/springframework/integration/xml/transformer/SourceCreatingTransformer.java +++ b/spring-integration-xml/src/main/java/org/springframework/integration/xml/transformer/SourceCreatingTransformer.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2008 the original author or authors. + * Copyright 2002-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. @@ -41,6 +41,7 @@ public class SourceCreatingTransformer extends AbstractPayloadTransformer { - private volatile boolean alwaysUseSourceFactory = false; - private final Unmarshaller unmarshaller; private volatile SourceFactory sourceFactory = new DomSourceFactory(); + private volatile boolean alwaysUseSourceFactory = false; + public UnmarshallingTransformer(Unmarshaller unmarshaller) { this.unmarshaller = unmarshaller; @@ -63,22 +63,21 @@ public class UnmarshallingTransformer extends AbstractPayloadTransformer { + static class XPathExpressionEvaluatingHeaderValueMessageProcessor implements HeaderValueMessageProcessor { private final XPathExpression expression; diff --git a/spring-integration-xml/src/main/java/org/springframework/integration/xml/transformer/XsltHeaders.java b/spring-integration-xml/src/main/java/org/springframework/integration/xml/transformer/XsltHeaders.java deleted file mode 100644 index 464ebd80ab..0000000000 --- a/spring-integration-xml/src/main/java/org/springframework/integration/xml/transformer/XsltHeaders.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright 2002-2010 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.integration.xml.transformer; - -import javax.xml.transform.Transformer; - -/** - * Message headers that can be used to configure the {@link Transformer} - * instance used for XSL transformation. - * - * @author Jonas Partner - */ -public abstract class XsltHeaders { - - public static final String PREFIX = "xslt_"; - - public static final String OUTPUT_PROPERTY = PREFIX + "output_property_"; - - public static final String PARAMETER = PREFIX + "parameter_"; - -} diff --git a/spring-integration-xml/src/main/java/org/springframework/integration/xml/transformer/XsltPayloadTransformer.java b/spring-integration-xml/src/main/java/org/springframework/integration/xml/transformer/XsltPayloadTransformer.java index 48e6f87690..e6adbf96cc 100644 --- a/spring-integration-xml/src/main/java/org/springframework/integration/xml/transformer/XsltPayloadTransformer.java +++ b/spring-integration-xml/src/main/java/org/springframework/integration/xml/transformer/XsltPayloadTransformer.java @@ -13,6 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.springframework.integration.xml.transformer; import java.io.IOException; @@ -44,6 +45,7 @@ import org.springframework.integration.xml.result.ResultFactory; import org.springframework.integration.xml.source.DomSourceFactory; import org.springframework.integration.xml.source.SourceFactory; import org.springframework.util.Assert; +import org.springframework.util.ObjectUtils; import org.springframework.util.PatternMatchUtils; import org.springframework.xml.transform.StringResult; import org.springframework.xml.transform.StringSource; @@ -76,8 +78,11 @@ import org.w3c.dom.Document; public class XsltPayloadTransformer extends AbstractTransformer { private final Log logger = LogFactory.getLog(this.getClass()); + private final Templates templates; - private final StandardEvaluationContext context = new StandardEvaluationContext(); + + private final StandardEvaluationContext evaluationContext = new StandardEvaluationContext(); + private Map xslParameterMappings; private final ResultTransformer resultTransformer; @@ -88,17 +93,13 @@ public class XsltPayloadTransformer extends AbstractTransformer { private volatile boolean alwaysUseSourceResultFactories = false; - private String[] xsltParamHeaders; + private volatile String[] xsltParamHeaders; + public XsltPayloadTransformer(Templates templates) throws ParserConfigurationException { this(templates, null); } - public XsltPayloadTransformer(Templates templates, ResultTransformer resultTransformer) throws ParserConfigurationException { - this.templates = templates; - this.resultTransformer = resultTransformer; - } - public XsltPayloadTransformer(Resource xslResource) throws Exception { this(TransformerFactory.newInstance().newTemplates(createStreamSourceOnResource(xslResource)), null); } @@ -107,28 +108,18 @@ public class XsltPayloadTransformer extends AbstractTransformer { this(TransformerFactory.newInstance().newTemplates(createStreamSourceOnResource(xslResource)), resultTransformer); } - - /** - * Compensate for the fact that a Resource may not be a File or even - * addressable through a URI. If it is, we want the created StreamSource to - * read other resources relative to the provided one. If it isn't, it loads - * from the default path. - */ - private static StreamSource createStreamSourceOnResource(Resource xslResource) throws IOException { - try { - String systemId = xslResource.getURI().toString(); - return new StreamSource(xslResource.getInputStream(), systemId); - } - catch (IOException e) { - return new StreamSource(xslResource.getInputStream()); - } + public XsltPayloadTransformer(Templates templates, ResultTransformer resultTransformer) throws ParserConfigurationException { + this.templates = templates; + this.resultTransformer = resultTransformer; + this.evaluationContext.addPropertyAccessor(new MapAccessor()); } + /** * Sets the SourceFactory. */ public void setSourceFactory(SourceFactory sourceFactory) { - Assert.notNull(sourceFactory, "SourceFactory can not be null"); + Assert.notNull(sourceFactory, "SourceFactory must not be null"); this.sourceFactory = sourceFactory; } @@ -136,7 +127,7 @@ public class XsltPayloadTransformer extends AbstractTransformer { * Sets the ResultFactory */ public void setResultFactory(ResultFactory resultFactory) { - Assert.notNull(sourceFactory, "ResultFactory can not be null"); + Assert.notNull(sourceFactory, "ResultFactory must not be null"); this.resultFactory = resultFactory; } @@ -144,8 +135,20 @@ public class XsltPayloadTransformer extends AbstractTransformer { * Specifies whether {@link ResultFactory} and {@link SourceFactory} should always * be used, even for directly supported payloads such as {@link String} and {@link Document}. */ - public void setAlwaysUseSourceResultFactories(boolean alwaysUserSourceResultFactories) { - this.alwaysUseSourceResultFactories = alwaysUserSourceResultFactories; + public void setAlwaysUseSourceResultFactories(boolean alwaysUseSourceResultFactories) { + this.alwaysUseSourceResultFactories = alwaysUseSourceResultFactories; + } + + public void setXslParameterMappings(Map xslParameterMappings) { + this.xslParameterMappings = xslParameterMappings; + } + + public void setXsltParamHeaders(String[] xsltParamHeaders) { + this.xsltParamHeaders = xsltParamHeaders; + } + + public String getComponentType() { + return "xml:xslt-transformer"; } @Override @@ -172,29 +175,29 @@ public class XsltPayloadTransformer extends AbstractTransformer { return transformedPayload; } - protected Object transformUsingFactories(Object payload, Transformer transformer) throws TransformerException { - Source source = sourceFactory.createSource(payload); + private Object transformUsingFactories(Object payload, Transformer transformer) throws TransformerException { + Source source = this.sourceFactory.createSource(payload); return transformSource(source, payload, transformer); } - protected Object transformSource(Source source, Object payload, Transformer transformer) throws TransformerException { - Result result = resultFactory.createResult(payload); + private Object transformSource(Source source, Object payload, Transformer transformer) throws TransformerException { + Result result = this.resultFactory.createResult(payload); transformer.transform(source, result); - if (resultTransformer != null) { - return resultTransformer.transformResult(result); + if (this.resultTransformer != null) { + return this.resultTransformer.transformResult(result); } return result; } - protected String transformString(String stringPayload, Transformer transformer) throws TransformerException { + private String transformString(String stringPayload, Transformer transformer) throws TransformerException { StringResult result = new StringResult(); transformer.transform(new StringSource(stringPayload), result); return result.toString(); } - protected Document transformDocument(Document documentPayload, Transformer transformer) throws TransformerException { + private Document transformDocument(Document documentPayload, Transformer transformer) throws TransformerException { DOMSource source = new DOMSource(documentPayload); - Result result = resultFactory.createResult(documentPayload); + Result result = this.resultFactory.createResult(documentPayload); if (!DOMResult.class.isAssignableFrom(result.getClass())) { throw new MessagingException( "Document to Document conversion requires a DOMResult-producing ResultFactory implementation."); @@ -203,51 +206,52 @@ public class XsltPayloadTransformer extends AbstractTransformer { transformer.transform(source, domResult); return (Document) domResult.getNode(); } - - protected Transformer buildTransformer(Message message) throws TransformerException { + + private Transformer buildTransformer(Message message) throws TransformerException { //process individual mappings Transformer transformer = this.templates.newTransformer(); - context.setRootObject(message); - context.addPropertyAccessor(new MapAccessor()); - if (xslParameterMappings != null){ - for (String parameterName: xslParameterMappings.keySet()) { - Expression expression = xslParameterMappings.get(parameterName); - Object value = null; + if (this.xslParameterMappings != null){ + for (String parameterName: this.xslParameterMappings.keySet()) { + Expression expression = this.xslParameterMappings.get(parameterName); try { - value = expression.getValue(context); + Object value = expression.getValue(this.evaluationContext, message); transformer.setParameter(parameterName, value); - } catch (Exception e) { - logger.warn("Header expression '" + expression.getExpressionString() + "' can not resolve within current message and will not be mapped to XSLT parameter"); - } + } + catch (Exception e) { + if (logger.isWarnEnabled()) { + logger.warn("Evaluation of header expression '" + expression.getExpressionString() + + "' failed. The XSLT parameter '" + parameterName + "' will be skipped."); + } + } } } // process xslt-parameter-headers MessageHeaders headers = message.getHeaders(); - if (xsltParamHeaders != null){ + if (!ObjectUtils.isEmpty(this.xsltParamHeaders)) { for (String headerName : headers.keySet()) { - if (PatternMatchUtils.simpleMatch(xsltParamHeaders, headerName)){ + if (PatternMatchUtils.simpleMatch(this.xsltParamHeaders, headerName)) { transformer.setParameter(headerName, headers.get(headerName)); - } + } } } return transformer; } - public Map getXslParameterMappings() { - return xslParameterMappings; + + /** + * Compensate for the fact that a Resource may not be a File or even + * addressable through a URI. If it is, we want the created StreamSource to + * read other resources relative to the provided one. If it isn't, it loads + * from the default path. + */ + private static StreamSource createStreamSourceOnResource(Resource xslResource) throws IOException { + try { + String systemId = xslResource.getURI().toString(); + return new StreamSource(xslResource.getInputStream(), systemId); + } + catch (IOException e) { + return new StreamSource(xslResource.getInputStream()); + } } - public void setXslParameterMappings(Map xslParameterMappings) { - this.xslParameterMappings = xslParameterMappings; - } - public String[] getXsltParamHeaders() { - return xsltParamHeaders; - } - - public void setXsltParamHeaders(String[] xsltParamHeaders) { - this.xsltParamHeaders = xsltParamHeaders; - } - public String getComponentType(){ - return "xml:xslt-transformer"; - } } diff --git a/spring-integration-xml/src/main/java/org/springframework/integration/xml/xpath/XPathEvaluationType.java b/spring-integration-xml/src/main/java/org/springframework/integration/xml/xpath/XPathEvaluationType.java index ca3966e4d9..92ec5d655e 100644 --- a/spring-integration-xml/src/main/java/org/springframework/integration/xml/xpath/XPathEvaluationType.java +++ b/spring-integration-xml/src/main/java/org/springframework/integration/xml/xpath/XPathEvaluationType.java @@ -1,33 +1,62 @@ +/* + * Copyright 2002-2010 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package org.springframework.integration.xml.xpath; -import org.springframework.xml.xpath.XPathExpression; import org.w3c.dom.Node; +import org.springframework.xml.xpath.XPathExpression; /** - * Enumeration of different types o XPath evaluation used to indicate the type of evaluation that should be carried out - * using a provided XPath expression + * Enumeration of different types of XPath evaluation used to indicate the type + * of evaluation that should be carried out using a provided XPath expression. */ public enum XPathEvaluationType { - BOOLEAN_RESULT {public Object evaluateXPath(XPathExpression expression, Node node) { - return expression.evaluateAsBoolean(node); - }}, + BOOLEAN_RESULT { + public Object evaluateXPath(XPathExpression expression, Node node) { + return expression.evaluateAsBoolean(node); + } + }, - STRING_RESULT {public Object evaluateXPath(XPathExpression expression, Node node) { - return expression.evaluateAsString(node); - }}, - NUMBER_RESULT {public Object evaluateXPath(XPathExpression expression, Node node) { - return expression.evaluateAsNumber(node); - }}, + STRING_RESULT { + public Object evaluateXPath(XPathExpression expression, Node node) { + return expression.evaluateAsString(node); + } + }, - NODE_RESULT {public Object evaluateXPath(XPathExpression expression, Node node) { - return expression.evaluateAsNode(node); - }}, - NODE_LIST_RESULT {public Object evaluateXPath(XPathExpression expression, Node node) { - return expression.evaluateAsNodeList(node); - }}; + NUMBER_RESULT { + public Object evaluateXPath(XPathExpression expression, Node node) { + return expression.evaluateAsNumber(node); + } + }, - public abstract Object evaluateXPath(XPathExpression expression, Node node); + NODE_RESULT { + public Object evaluateXPath(XPathExpression expression, Node node) { + return expression.evaluateAsNode(node); + } + }, + + NODE_LIST_RESULT { + public Object evaluateXPath(XPathExpression expression, Node node) { + return expression.evaluateAsNodeList(node); + } + }; + + + public abstract Object evaluateXPath(XPathExpression expression, Node node); } From 52c958ead0d7ed787c323287bf555d3b990ff183 Mon Sep 17 00:00:00 2001 From: Oleg Zhurakousky Date: Tue, 2 Nov 2010 18:43:40 -0400 Subject: [PATCH 15/82] INT-1557 added Twiter Outbound adapter documentation --- docs/src/reference/docbook/twitter.xml | 46 ++++++++++++++++++++++++-- 1 file changed, 43 insertions(+), 3 deletions(-) diff --git a/docs/src/reference/docbook/twitter.xml b/docs/src/reference/docbook/twitter.xml index 1443d7007a..88086ab00f 100644 --- a/docs/src/reference/docbook/twitter.xml +++ b/docs/src/reference/docbook/twitter.xml @@ -106,11 +106,12 @@ and configuring a property-placeholder pointing to he above propert
Twitter Inbound Adapters - Twitter inbound adapters allow you to receive Twitter Messages. There are several types of twitter messages: - Types of Tweets + Twitter inbound adapters allow you to receive Twitter Messages. There are several types of + twitter messages - tweets - Current release of Spring Integration provides support for Public Messages, Direct Messages as well as Mention Messages + Current release of Spring Integration provides support for receiving Public Messages, + Direct Messages as well as Mention Messages Every Inbound Twitter Channel Adapter is a Polling consumer which means you have to provide a poller @@ -175,4 +176,43 @@ The Poller that is configured as part of the any Inbound Twitter Adapter (see be simply invoke getText() method. For more information please refer to Twitter4J API
+ +
+ Twitter Outbound Adapter + + Twitter outbound channels adapters allow you to send Twitter Messages - tweets + + + Current release of Spring Integration supports sending Status Update Messages and Direct Messages. + Twitter outbound channels adapters as any other outbound adapter will take the Message payload and send it as + Twitter message. Currently the only supported payload type is String, so consider adding a transformer + if the payload of the incoming message is not a String. + + +
+ Twitter Outbound Update Channel Adapter + + This adapter allows you to send regular status updates by simply sending a Message to a channel + identified via channel attribute. + ]]> + The only extra configuration that is required for this adapter is twitter-connection + +
+ +
+ Twitter Outbound Direct Message Channel Adapter + + This adapter allows you to send Direct Twitter Messages (i.e., @user) by simply sending a Message to a channel + identified via channel attribute. + ]]> + The only extra configuration that is required for this adapter is twitter-connection + +
+ + Twitter does not allow you to post duplicate Messages. This is a common problem during testing when + the same code works the first time but doesn't work the second time,so make sure to change the content of the Message. + One thing that works good for testing is appent timestamp to the end of the message. + + +
From 155cc0717ccd65c7fd048068e689691729a5fe13 Mon Sep 17 00:00:00 2001 From: Josh Long Date: Tue, 2 Nov 2010 16:34:22 -0700 Subject: [PATCH 16/82] INT-1580 this is a beanfactory that knows how to factory an SSL XMPPConnection (as opposed to the regular XmppConnectionFactory) --- .../xmpp/SslXmppConnectionFactory.java | 110 ++++++++++++++++++ .../xmpp/XmppConnectionFactory.java | 44 +++++-- 2 files changed, 146 insertions(+), 8 deletions(-) create mode 100644 spring-integration-xmpp/src/main/java/org/springframework/integration/xmpp/SslXmppConnectionFactory.java diff --git a/spring-integration-xmpp/src/main/java/org/springframework/integration/xmpp/SslXmppConnectionFactory.java b/spring-integration-xmpp/src/main/java/org/springframework/integration/xmpp/SslXmppConnectionFactory.java new file mode 100644 index 0000000000..3c9095dacf --- /dev/null +++ b/spring-integration-xmpp/src/main/java/org/springframework/integration/xmpp/SslXmppConnectionFactory.java @@ -0,0 +1,110 @@ +package org.springframework.integration.xmpp; + +import org.jivesoftware.smack.ConnectionConfiguration; + +import org.springframework.core.io.Resource; + +import org.springframework.util.Assert; +import org.springframework.util.StringUtils; + +import javax.net.SocketFactory; +import javax.net.ssl.SSLSocketFactory; + + +/** + * An extension of {@link org.springframework.integration.xmpp.XmppConnectionFactory} that handles factorying a secure XMPP connection factory. + *

+ * This is interchangeable with existing {@link org.jivesoftware.smack.XMPPConnection} references, of course. + * + * @author Josh Long + */ +public class SslXmppConnectionFactory extends XmppConnectionFactory { + private volatile String trustStorePassword; + private volatile String trustStoreType; + private volatile Resource trustStore; + private volatile boolean securityEnabled = true ; + private volatile SocketFactory socketFactory; + private volatile ConnectionConfiguration.SecurityMode securityMode = ConnectionConfiguration.SecurityMode.enabled; + + /** + * This method is a callback provided by the super type that lets us plugin to the configuration mechanism + * + * @param connectionConfiguration the connection Configuration + * @throws Exception + */ + + @Override + protected void setupConnectionConfiguration( ConnectionConfiguration connectionConfiguration) throws Exception { + + this.securityEnabled = securityMode != null && + (ConnectionConfiguration.SecurityMode.enabled.equals(securityMode)|| + ConnectionConfiguration.SecurityMode.required.equals(securityMode) ); + + if (this.securityEnabled) { + if (this.socketFactory == null) { + this.socketFactory = SSLSocketFactory.getDefault(); + } + + Assert.notNull(this.trustStore, "'trustStore' must not be null"); + + String trustStorePath = this.trustStore.toString(); + connectionConfiguration.setTruststorePath( trustStorePath); + + // not required + if(StringUtils.hasText( this.trustStorePassword)) + connectionConfiguration.setTruststorePassword(this.trustStorePassword); + + // not required + if(StringUtils.hasText(this.trustStoreType)) + connectionConfiguration.setTruststoreType( this.trustStoreType); + } + } + + /** + * Not required. If not specified, we will load reference using {@link javax.net.ssl.SSLSocketFactory#getDefault()} + * + * @param socketFactory the socket factory to be passed to the {@link org.jivesoftware.smack.ConnectionConfiguration} + * + */ + public void setSocketFactory(SocketFactory socketFactory) { + this.socketFactory = socketFactory; + } + + /** + * the password to use to access the trust store (optional) + * + * @param trustStorePassword + */ + public void setTrustStorePassword(String trustStorePassword) { + this.trustStorePassword = trustStorePassword; + } + + /** + * This is required and specifies the path to the keystore (ie: /path/to/foo.jks) + * + * @param trustStore a {@link org.springframework.core.io.Resource} to the path itself + * + */ + public void setTrustStore(Resource trustStore) { + this.trustStore = trustStore; + } + + /** + * the type of trust store. + * + * @param trustStoreType the type of trust store + */ + public void setTrustStoreType(String trustStoreType) { + this.trustStoreType = trustStoreType; + } + + + /** + * used on {@link org.jivesoftware.smack.ConnectionConfiguration#setSecurityMode(org.jivesoftware.smack.ConnectionConfiguration.SecurityMode)} + * + * basically, if you're using this class we assume you want security enabled. If you don't you can always override it by specifying {@link org.jivesoftware.smack.ConnectionConfiguration.SecurityMode#disabled} + */ + public void setSecurityMode(ConnectionConfiguration.SecurityMode securityMode) { + this.securityMode = securityMode; + } +} diff --git a/spring-integration-xmpp/src/main/java/org/springframework/integration/xmpp/XmppConnectionFactory.java b/spring-integration-xmpp/src/main/java/org/springframework/integration/xmpp/XmppConnectionFactory.java index cb2364bbb4..a7592b1127 100644 --- a/spring-integration-xmpp/src/main/java/org/springframework/integration/xmpp/XmppConnectionFactory.java +++ b/spring-integration-xmpp/src/main/java/org/springframework/integration/xmpp/XmppConnectionFactory.java @@ -149,23 +149,49 @@ public class XmppConnectionFactory extends AbstractFactoryBean { this.subscriptionMode = subscriptionMode; } + @Override public Class getObjectType() { return XMPPConnection.class; } - private XMPPConnection configureAndConnect(String usr, String pw, String host, int port, String serviceName, String resource, String saslMechanismSupported, int saslMechanismSupportedIndex) { + /** + * this provides a hook for subclasses to provide extra setup before the {@link org.jivesoftware.smack.XMPPConnection} is created + * + * @param xmppConnection the connection to configure + * @throws Exception + */ + protected void setupXmppConnectionConfiguration(XMPPConnection xmppConnection) throws Exception { + // noop + } + + /** + * this provides a hook for subclasses to provide extra setup before the {@link org.jivesoftware.smack.ConnectionConfiguration} is created. + * + * @param connectionConfiguration + * @throws Exception + */ + protected void setupConnectionConfiguration(ConnectionConfiguration connectionConfiguration) throws Exception { + // noop + } + + protected XMPPConnection configureAndConnect(String usr, String pw, String host, int port, String serviceName, String resource, String saslMechanismSupported, int saslMechanismSupportedIndex) { if (logger.isDebugEnabled()) { logger.debug(String.format("usr=%s, pw=%s, host=%s, port=%s, serviceName=%s, resource=%s, saslMechanismSupported=%s, saslMechanismSupportedIndex=%s", usr, pw, host, port, serviceName, resource, saslMechanismSupported, saslMechanismSupportedIndex)); } - XMPPConnection.DEBUG_ENABLED = false; // default - - ConnectionConfiguration connectionConfiguration = new ConnectionConfiguration(host, port, serviceName); - XMPPConnection connection = new XMPPConnection(connectionConfiguration); - try { + + XMPPConnection.DEBUG_ENABLED = false; // default + + ConnectionConfiguration connectionConfiguration = new ConnectionConfiguration(host, port, serviceName); + setupConnectionConfiguration(connectionConfiguration); + XMPPConnection connection = new XMPPConnection(connectionConfiguration); + + + setupXmppConnectionConfiguration(connection); + connection.connect(); // You have to put this code before you login @@ -173,6 +199,7 @@ public class XmppConnectionFactory extends AbstractFactoryBean { SASLAuthentication.supportSASLMechanism(saslMechanismSupported, saslMechanismSupportedIndex); } + // You have to specify the resoure (e.g. "@host.com") at the end if (StringUtils.hasText(resource)) { connection.login(usr, pw, resource); @@ -188,11 +215,12 @@ public class XmppConnectionFactory extends AbstractFactoryBean { if (logger.isDebugEnabled()) { logger.debug("authenticated? " + connection.isAuthenticated()); } + + return connection; } catch (Exception e) { logger.warn("failed to establish XMPP connnection", e); } - - return connection; + return null; } From d6891a2ea22a6ded7b59c3213451c0bbd00b3c62 Mon Sep 17 00:00:00 2001 From: Josh Long Date: Tue, 2 Nov 2010 16:35:56 -0700 Subject: [PATCH 17/82] INT-1580 this is a beanfactory that knows how to factory an SSL XMPPConnection (as opposed to the regular XmppConnectionFactory) --- .../xmpp/SslXmppConnectionFactory.java | 72 +++++++++---------- 1 file changed, 34 insertions(+), 38 deletions(-) diff --git a/spring-integration-xmpp/src/main/java/org/springframework/integration/xmpp/SslXmppConnectionFactory.java b/spring-integration-xmpp/src/main/java/org/springframework/integration/xmpp/SslXmppConnectionFactory.java index 3c9095dacf..0cbf6f2382 100644 --- a/spring-integration-xmpp/src/main/java/org/springframework/integration/xmpp/SslXmppConnectionFactory.java +++ b/spring-integration-xmpp/src/main/java/org/springframework/integration/xmpp/SslXmppConnectionFactory.java @@ -1,9 +1,7 @@ package org.springframework.integration.xmpp; import org.jivesoftware.smack.ConnectionConfiguration; - import org.springframework.core.io.Resource; - import org.springframework.util.Assert; import org.springframework.util.StringUtils; @@ -19,89 +17,87 @@ import javax.net.ssl.SSLSocketFactory; * @author Josh Long */ public class SslXmppConnectionFactory extends XmppConnectionFactory { - private volatile String trustStorePassword; - private volatile String trustStoreType; - private volatile Resource trustStore; - private volatile boolean securityEnabled = true ; - private volatile SocketFactory socketFactory; + private volatile String trustStorePassword; + private volatile String trustStoreType; + private volatile Resource trustStore; + private volatile boolean securityEnabled = true; + private volatile SocketFactory socketFactory; private volatile ConnectionConfiguration.SecurityMode securityMode = ConnectionConfiguration.SecurityMode.enabled; /** * This method is a callback provided by the super type that lets us plugin to the configuration mechanism * - * @param connectionConfiguration the connection Configuration + * @param connectionConfiguration the connection Configuration * @throws Exception */ - @Override - protected void setupConnectionConfiguration( ConnectionConfiguration connectionConfiguration) throws Exception { + @Override + protected void setupConnectionConfiguration(ConnectionConfiguration connectionConfiguration) throws Exception { this.securityEnabled = securityMode != null && - (ConnectionConfiguration.SecurityMode.enabled.equals(securityMode)|| - ConnectionConfiguration.SecurityMode.required.equals(securityMode) ); + (ConnectionConfiguration.SecurityMode.enabled.equals(securityMode) || + ConnectionConfiguration.SecurityMode.required.equals(securityMode)); - if (this.securityEnabled) { - if (this.socketFactory == null) { - this.socketFactory = SSLSocketFactory.getDefault(); - } + if (this.securityEnabled) { + if (this.socketFactory == null) { + this.socketFactory = SSLSocketFactory.getDefault(); + } - Assert.notNull(this.trustStore, "'trustStore' must not be null"); + Assert.notNull(this.trustStore, "'trustStore' must not be null"); String trustStorePath = this.trustStore.toString(); - connectionConfiguration.setTruststorePath( trustStorePath); + connectionConfiguration.setTruststorePath(trustStorePath); // not required - if(StringUtils.hasText( this.trustStorePassword)) + if (StringUtils.hasText(this.trustStorePassword)) connectionConfiguration.setTruststorePassword(this.trustStorePassword); // not required - if(StringUtils.hasText(this.trustStoreType)) - connectionConfiguration.setTruststoreType( this.trustStoreType); - } - } + if (StringUtils.hasText(this.trustStoreType)) + connectionConfiguration.setTruststoreType(this.trustStoreType); + } + } /** * Not required. If not specified, we will load reference using {@link javax.net.ssl.SSLSocketFactory#getDefault()} * * @param socketFactory the socket factory to be passed to the {@link org.jivesoftware.smack.ConnectionConfiguration} - * */ - public void setSocketFactory(SocketFactory socketFactory) { - this.socketFactory = socketFactory; - } + public void setSocketFactory(SocketFactory socketFactory) { + this.socketFactory = socketFactory; + } /** * the password to use to access the trust store (optional) * * @param trustStorePassword */ - public void setTrustStorePassword(String trustStorePassword) { - this.trustStorePassword = trustStorePassword; - } + public void setTrustStorePassword(String trustStorePassword) { + this.trustStorePassword = trustStorePassword; + } /** * This is required and specifies the path to the keystore (ie: /path/to/foo.jks) * * @param trustStore a {@link org.springframework.core.io.Resource} to the path itself - * */ - public void setTrustStore(Resource trustStore) { - this.trustStore = trustStore; - } + public void setTrustStore(Resource trustStore) { + this.trustStore = trustStore; + } /** * the type of trust store. * * @param trustStoreType the type of trust store */ - public void setTrustStoreType(String trustStoreType) { - this.trustStoreType = trustStoreType; - } + public void setTrustStoreType(String trustStoreType) { + this.trustStoreType = trustStoreType; + } /** * used on {@link org.jivesoftware.smack.ConnectionConfiguration#setSecurityMode(org.jivesoftware.smack.ConnectionConfiguration.SecurityMode)} - * + *

* basically, if you're using this class we assume you want security enabled. If you don't you can always override it by specifying {@link org.jivesoftware.smack.ConnectionConfiguration.SecurityMode#disabled} */ public void setSecurityMode(ConnectionConfiguration.SecurityMode securityMode) { From c3a51394d79592609776d52c66fac6253ebf5f98 Mon Sep 17 00:00:00 2001 From: Oleg Zhurakousky Date: Tue, 2 Nov 2010 22:29:18 -0400 Subject: [PATCH 18/82] polishing --- .../integration/ftp/FtpParserOutboundTests-context.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/spring-integration-ftp/src/test/java/org/springframework/integration/ftp/FtpParserOutboundTests-context.xml b/spring-integration-ftp/src/test/java/org/springframework/integration/ftp/FtpParserOutboundTests-context.xml index b8445cd02b..aacfa1abc2 100644 --- a/spring-integration-ftp/src/test/java/org/springframework/integration/ftp/FtpParserOutboundTests-context.xml +++ b/spring-integration-ftp/src/test/java/org/springframework/integration/ftp/FtpParserOutboundTests-context.xml @@ -10,8 +10,8 @@ Date: Wed, 3 Nov 2010 08:45:38 -0400 Subject: [PATCH 19/82] polishing/formatting OAuth part of Twitter adapter --- ...tractOAuthAccessTokenBasedFactoryBean.java | 133 +++++++----------- ...essTokenInitialRequestProcessListener.java | 1 + ...uthAccessTokenBasedTwitterFactoryBean.java | 6 +- .../twitter/oauth/OAuthConfiguration.java | 5 +- ...essTokenInitialRequestProcessListener.java | 0 5 files changed, 57 insertions(+), 88 deletions(-) rename spring-integration-twitter/src/{main => test}/java/org/springframework/integration/twitter/oauth/ConsoleBasedAccessTokenInitialRequestProcessListener.java (100%) diff --git a/spring-integration-twitter/src/main/java/org/springframework/integration/twitter/oauth/AbstractOAuthAccessTokenBasedFactoryBean.java b/spring-integration-twitter/src/main/java/org/springframework/integration/twitter/oauth/AbstractOAuthAccessTokenBasedFactoryBean.java index 6f4ed65190..f5f34acd11 100644 --- a/spring-integration-twitter/src/main/java/org/springframework/integration/twitter/oauth/AbstractOAuthAccessTokenBasedFactoryBean.java +++ b/spring-integration-twitter/src/main/java/org/springframework/integration/twitter/oauth/AbstractOAuthAccessTokenBasedFactoryBean.java @@ -15,17 +15,18 @@ */ package org.springframework.integration.twitter.oauth; +import java.util.Properties; + import org.springframework.beans.factory.FactoryBean; import org.springframework.beans.factory.InitializingBean; import org.springframework.beans.factory.config.PropertiesFactoryBean; import org.springframework.core.io.Resource; import org.springframework.util.Assert; import org.springframework.util.StringUtils; + import twitter4j.http.AccessToken; import twitter4j.http.RequestToken; -import java.util.Properties; - /** * base-class for {@link org.springframework.integration.twitter.oauth.OAuthAccessTokenBasedTwitterFactoryBean}. @@ -42,9 +43,53 @@ abstract public class AbstractOAuthAccessTokenBasedFactoryBean implements Ini protected OAuthConfiguration configuration; protected final Object monitor = new Object(); protected volatile T twitter; -// protected volatile AccessTokenInitialRequestProcessListener accessTokenInitialRequestProcessListener; protected volatile boolean initialized = false; + /** + * Standard {@link org.springframework.beans.factory.FactoryBean} method. Implementations may override if there's a specific method + * + * @return whether or not this is a singleton + */ + public boolean isSingleton() { + return true; + } + + /** + * Rubber meets the road: builds up a reference to the twitter4j.(Async)Twitter instance + * + * @return the instance + * @throws Exception thrown in case some condition isn't met correctly in construction + */ + public T getObject() throws Exception { + if (!initialized) { + afterPropertiesSet(); + } + + return this.twitter; + } + /** + * provides lifecycle for initiation of the reference. By the time this method is left we should have a fully configured twitter connection that can connect and make calls + * + * @throws Exception + */ + public void afterPropertiesSet() throws Exception { + synchronized (this.monitor) { + + Assert.notNull(this.configuration.getConsumerKey(), "'consumerKey' mustn't be null"); + Assert.notNull(this.configuration.getConsumerSecret(), "'consumerSecret' mustn't be null"); + + AccessToken accessTokenObj=null; + establishTwitterObject(accessTokenObj); + if (StringUtils.hasText(this.configuration.getAccessToken()) && StringUtils.hasText(this.configuration.getAccessTokenSecret())) { + accessTokenObj = new AccessToken(this.configuration.getAccessToken(), this.configuration.getAccessTokenSecret()); + } + establishTwitterObject(accessTokenObj); + + Assert.notNull(accessTokenObj, "'accessTokenObj' can't be null"); + + this.initialized = true; + } + } /** * Nasty little bit of circular indirection here: the {@link org.springframework.integration.twitter.oauth.OAuthConfiguration} hosts the String values for authentication, * which we need to build up this instance, but the {@link org.springframework.integration.twitter.oauth.OAuthConfiguration} in turn needs references to the instances provided by @@ -66,7 +111,6 @@ abstract public class AbstractOAuthAccessTokenBasedFactoryBean implements Ini * @return returns a fully configured {@link java.util.Properties} instance * @throws Exception thrown if anythign goes wrong */ - @SuppressWarnings("unused") protected static Properties fromResource(Resource resource) throws Exception { PropertiesFactoryBean propertiesFactoryBean = new PropertiesFactoryBean(); @@ -77,41 +121,6 @@ abstract public class AbstractOAuthAccessTokenBasedFactoryBean implements Ini return propertiesFactoryBean.getObject(); } - /** - * provides lifecycle for initiation of the reference. By the time this method is left we should have a fully configured twitter connection that can connect and make calls - * - * @throws Exception - */ - public void afterPropertiesSet() throws Exception { - synchronized (this.monitor) { - /*if (this.accessTokenInitialRequestProcessListener == null) { - accessTokenInitialRequestProcessListener = new ConsoleBasedAccessTokenInitialRequestProcessListener(); - }*/ - - Assert.notNull(this.configuration.getConsumerKey(), "'consumerKey' mustn't be null"); - Assert.notNull(this.configuration.getConsumerSecret(), "'consumerSecret' mustn't be null"); - - AccessToken accessTokenObj=null; - establishTwitterObject(accessTokenObj); - if (StringUtils.hasText(this.configuration.getAccessToken()) && StringUtils.hasText(this.configuration.getAccessTokenSecret())) { - accessTokenObj = new AccessToken(this.configuration.getAccessToken(), this.configuration.getAccessTokenSecret()); - } /*else { - // accessTokenObj = initialAuthorizationWizard(); - }*/ - - establishTwitterObject(accessTokenObj); - - Assert.notNull(accessTokenObj, "'accessTokenObj' can't be null"); - - this.initialized = true; - } - } - - /*@SuppressWarnings("unused") - public void setAccessTokenInitialRequestProcessListener(AccessTokenInitialRequestProcessListener accessTokenInitialRequestProcessListener) { - this.accessTokenInitialRequestProcessListener = accessTokenInitialRequestProcessListener; - } -*/ public abstract void establishTwitterObject(AccessToken accessToken) throws Exception; @@ -150,29 +159,6 @@ abstract public class AbstractOAuthAccessTokenBasedFactoryBean implements Ini */ public abstract AccessToken getOAuthAccessToken() throws Exception; - /** - * @return returns the freshly created {@link twitter4j.http.AccessToken} object from the service - * @throws Exception for just about any deviation from the expected - */ -/* - private AccessToken initialAuthorizationWizard() throws Exception { - Assert.notNull(this.accessTokenInitialRequestProcessListener, "'accessTokenInitialRequestProcessListener' can't be null"); - - try { - RequestToken requestToken = getOAuthRequestToken(); - String pin = this.accessTokenInitialRequestProcessListener.openUrlAndReturnPin(requestToken.getAuthorizationURL()); - AccessToken at = StringUtils.hasText(pin) ? getOAuthAccessToken(requestToken, pin) : getOAuthAccessToken(); - this.accessTokenInitialRequestProcessListener.persistReturnedAccessToken(at); - - return at; - } catch (Throwable th) { - this.accessTokenInitialRequestProcessListener.failure(th); - } - - return null; - } -*/ - /** * Responsibility of subclasses to call this because we cant dereference the generic type appropriately. The responsibility is * to call {@link twitter4j.Twitter#verifyCredentials()} or {@link twitter4j.AsyncTwitter#verifyCredentials()} as appropriate @@ -181,33 +167,10 @@ abstract public class AbstractOAuthAccessTokenBasedFactoryBean implements Ini */ public abstract void verifyCredentials() throws Exception; - /** - * Rubber meets the road: builds up a reference to the twitter4j.(Async)Twitter instance - * - * @return the instance - * @throws Exception thrown in case some condition isn't met correctly in construction - */ - public T getObject() throws Exception { - if (!initialized) { - afterPropertiesSet(); - } - - return this.twitter; - } - /** * this method is delegated to implementations because we can't correctly dereference the generic type's class * * @return a class */ abstract public Class getObjectType(); - - /** - * Standard {@link org.springframework.beans.factory.FactoryBean} method. Implementations may override if there's a specific method - * - * @return whether or not this is a singleton - */ - public boolean isSingleton() { - return true; - } } diff --git a/spring-integration-twitter/src/main/java/org/springframework/integration/twitter/oauth/AccessTokenInitialRequestProcessListener.java b/spring-integration-twitter/src/main/java/org/springframework/integration/twitter/oauth/AccessTokenInitialRequestProcessListener.java index 35f312d74a..3f40a34425 100644 --- a/spring-integration-twitter/src/main/java/org/springframework/integration/twitter/oauth/AccessTokenInitialRequestProcessListener.java +++ b/spring-integration-twitter/src/main/java/org/springframework/integration/twitter/oauth/AccessTokenInitialRequestProcessListener.java @@ -24,6 +24,7 @@ import twitter4j.http.AccessToken; * In doing so it will need input fro the user (automatic or human intervention is required) * * @author Josh Long + * @since 2.0 */ public interface AccessTokenInitialRequestProcessListener { diff --git a/spring-integration-twitter/src/main/java/org/springframework/integration/twitter/oauth/OAuthAccessTokenBasedTwitterFactoryBean.java b/spring-integration-twitter/src/main/java/org/springframework/integration/twitter/oauth/OAuthAccessTokenBasedTwitterFactoryBean.java index c7d7e82975..9b99bb7e26 100644 --- a/spring-integration-twitter/src/main/java/org/springframework/integration/twitter/oauth/OAuthAccessTokenBasedTwitterFactoryBean.java +++ b/spring-integration-twitter/src/main/java/org/springframework/integration/twitter/oauth/OAuthAccessTokenBasedTwitterFactoryBean.java @@ -20,7 +20,11 @@ import twitter4j.TwitterFactory; import twitter4j.http.AccessToken; import twitter4j.http.RequestToken; - +/** + * + * @author Josh Long + * @since 2.0 + */ public class OAuthAccessTokenBasedTwitterFactoryBean extends AbstractOAuthAccessTokenBasedFactoryBean { protected OAuthAccessTokenBasedTwitterFactoryBean(OAuthConfiguration configuration) { super(configuration); diff --git a/spring-integration-twitter/src/main/java/org/springframework/integration/twitter/oauth/OAuthConfiguration.java b/spring-integration-twitter/src/main/java/org/springframework/integration/twitter/oauth/OAuthConfiguration.java index b7ee022475..e2857756e7 100644 --- a/spring-integration-twitter/src/main/java/org/springframework/integration/twitter/oauth/OAuthConfiguration.java +++ b/spring-integration-twitter/src/main/java/org/springframework/integration/twitter/oauth/OAuthConfiguration.java @@ -23,10 +23,11 @@ import twitter4j.Twitter; * and an {@link twitter4j.Twitter} instance. *

* client should store this bean and simply lookup the Twitter configuration from there + * @author Josh Long + * @since 2.0 */ public class OAuthConfiguration { - // - // private AsyncTwitter asyncTwitter; + private Twitter twitter; private volatile String consumerKey; private volatile String consumerSecret; diff --git a/spring-integration-twitter/src/main/java/org/springframework/integration/twitter/oauth/ConsoleBasedAccessTokenInitialRequestProcessListener.java b/spring-integration-twitter/src/test/java/org/springframework/integration/twitter/oauth/ConsoleBasedAccessTokenInitialRequestProcessListener.java similarity index 100% rename from spring-integration-twitter/src/main/java/org/springframework/integration/twitter/oauth/ConsoleBasedAccessTokenInitialRequestProcessListener.java rename to spring-integration-twitter/src/test/java/org/springframework/integration/twitter/oauth/ConsoleBasedAccessTokenInitialRequestProcessListener.java From 6cc758eefcda7d6562abae4662c66ec4e0a9931c Mon Sep 17 00:00:00 2001 From: Mark Fisher Date: Wed, 3 Nov 2010 12:39:11 -0400 Subject: [PATCH 20/82] INT-1582 if the payload is an ApplicationEvent it is passed as-is (no wrapping in MessagingException). Also, general polishing --- docs/src/reference/docbook/event.xml | 25 ++- .../endpoint/MessageProducerSupport.java | 16 ++ .../EventInboundChannelAdapterParser.java | 10 +- .../event/config/EventNamespaceHandler.java | 2 +- .../EventOutboundChannelAdapterParser.java | 31 +--- .../event/{ => core}/MessagingEvent.java | 2 +- ...icationEventListeningMessageProducer.java} | 41 +++-- ...licationEventPublishingMessageHandler.java | 12 +- .../config/spring-integration-event-2.0.xsd | 172 +++++++++--------- ...EventInboundChannelAdapterParserTests.java | 10 +- ...ventOutboundChannelAdapterParserTests.java | 57 +++--- ...AdapterParserTestsWithPollable-context.xml | 4 +- ...onEventListeningMessageProducerTests.java} | 25 +-- ...icationEventInboundChannelAdapterTests.xml | 2 +- ...ionEventPublishingMessageHandlerTests.java | 29 ++- 15 files changed, 238 insertions(+), 200 deletions(-) rename spring-integration-event/src/main/java/org/springframework/integration/event/{ => core}/MessagingEvent.java (95%) rename spring-integration-event/src/main/java/org/springframework/integration/event/{ApplicationEventInboundChannelAdapter.java => inbound/ApplicationEventListeningMessageProducer.java} (80%) rename spring-integration-event/src/main/java/org/springframework/integration/event/{ => outbound}/ApplicationEventPublishingMessageHandler.java (77%) rename spring-integration-event/src/test/java/org/springframework/integration/event/{ApplicationEventInboundChannelAdapterTests.java => inbound/ApplicationEventListeningMessageProducerTests.java} (89%) rename spring-integration-event/src/test/java/org/springframework/integration/event/{ => inbound}/applicationEventInboundChannelAdapterTests.xml (92%) rename spring-integration-event/src/test/java/org/springframework/integration/event/{ => outbound}/ApplicationEventPublishingMessageHandlerTests.java (65%) diff --git a/docs/src/reference/docbook/event.xml b/docs/src/reference/docbook/event.xml index 3a9546edbf..cc6336d97a 100644 --- a/docs/src/reference/docbook/event.xml +++ b/docs/src/reference/docbook/event.xml @@ -13,21 +13,20 @@ Receiving Spring ApplicationEvents To receive events and send them to a channel, simply define an instance of Spring Integration's - ApplicationEventListeningChannelAdapter. This class is an implementation of + ApplicationEventListeningMessageProducer. This class is an implementation of Spring's ApplicationListener interface. By default it will pass all received events as Spring Integration Messages. To limit based on the type of event, configure the list of event types that you want to receive with the 'eventTypes' property. - For convenience namespace support was provided to configure ApplicationEventListeningChannelAdapter via inbound-channel-adapter - + For convenience namespace support was provided to configure ApplicationEventListeningMessageProducer via inbound-channel-adapter + -]]> -In the above sample, all Application Context events that are of type specified by the 'event-types' (optional) attribute will be -delivered as Spring Integration Messages to 'sampleEventChannel'. +]]> +In the above example, all Application Context events that match one of the types specified by the 'event-types' (optional) attribute will be +delivered as Spring Integration Messages to 'eventChannel'. -

@@ -41,21 +40,21 @@ delivered as Spring Integration Messages to 'sampleEventChannel'. For convenience namespace support was provided to configure ApplicationEventPublishingMessageHandler via outbound-channel-adapter element - + -]]> -If you are using PollableChannel (e.g., Queue), you can also provide poller as sub-element of outbound-channel-adapter, optionally providing task-executor - +]]> +If you are using a PollableChannel (e.g., Queue), you can also provide poller as a sub-element of the outbound-channel-adapter element. You can also optionally provide a task-executor reference for that poller. + - + ]]> -In the above sample, all messages sent to an 'input' channel will be published as ApplicationEvents to Spring Application sContext +In the above example, all messages sent to the 'eventChannel' channel will be published as ApplicationEvents to any relevant ApplicationListeners within the Spring ApplicationContext. If the payload of the Message is an ApplicationEvent, it will be passed as-is. Otherwise the Message itself will be wrapped in a MessagingEvent instance.
diff --git a/spring-integration-core/src/main/java/org/springframework/integration/endpoint/MessageProducerSupport.java b/spring-integration-core/src/main/java/org/springframework/integration/endpoint/MessageProducerSupport.java index 7eb6eb3340..835f2e4618 100644 --- a/spring-integration-core/src/main/java/org/springframework/integration/endpoint/MessageProducerSupport.java +++ b/spring-integration-core/src/main/java/org/springframework/integration/endpoint/MessageProducerSupport.java @@ -57,6 +57,22 @@ public abstract class MessageProducerSupport extends AbstractEndpoint implements Assert.notNull(this.outputChannel, "outputChannel is required"); } + /** + * Takes no action by default. Subclasses may override this if they + * need lifecycle-managed behavior. + */ + @Override + protected void doStart() { + } + + /** + * Takes no action by default. Subclasses may override this if they + * need lifecycle-managed behavior. + */ + @Override + protected void doStop() { + } + protected void sendMessage(Message message) { if (message == null) { throw new MessagingException("cannot send a null message"); diff --git a/spring-integration-event/src/main/java/org/springframework/integration/event/config/EventInboundChannelAdapterParser.java b/spring-integration-event/src/main/java/org/springframework/integration/event/config/EventInboundChannelAdapterParser.java index 37d924f60c..6fddae8854 100644 --- a/spring-integration-event/src/main/java/org/springframework/integration/event/config/EventInboundChannelAdapterParser.java +++ b/spring-integration-event/src/main/java/org/springframework/integration/event/config/EventInboundChannelAdapterParser.java @@ -16,23 +16,25 @@ package org.springframework.integration.event.config; +import org.w3c.dom.Element; + import org.springframework.beans.factory.support.AbstractBeanDefinition; import org.springframework.beans.factory.support.BeanDefinitionBuilder; import org.springframework.beans.factory.xml.ParserContext; import org.springframework.integration.config.xml.AbstractChannelAdapterParser; import org.springframework.integration.config.xml.IntegrationNamespaceUtils; -import org.springframework.integration.event.ApplicationEventInboundChannelAdapter; -import org.w3c.dom.Element; /** * @author Oleg Zhurakousky + * @author Mark Fisher * @since 2.0 */ -public class EventInboundChannelAdapterParser extends AbstractChannelAdapterParser{ +public class EventInboundChannelAdapterParser extends AbstractChannelAdapterParser { @Override protected AbstractBeanDefinition doParse(Element element, ParserContext parserContext, String channelName) { - BeanDefinitionBuilder adapterBuilder = BeanDefinitionBuilder.rootBeanDefinition(ApplicationEventInboundChannelAdapter.class); + BeanDefinitionBuilder adapterBuilder = BeanDefinitionBuilder.rootBeanDefinition( + "org.springframework.integration.event.inbound.ApplicationEventListeningMessageProducer"); IntegrationNamespaceUtils.setReferenceIfAttributeDefined(adapterBuilder, element, "channel", "outputChannel"); IntegrationNamespaceUtils.setValueIfAttributeDefined(adapterBuilder, element, "event-types"); IntegrationNamespaceUtils.setValueIfAttributeDefined(adapterBuilder, element, "payload-expression"); diff --git a/spring-integration-event/src/main/java/org/springframework/integration/event/config/EventNamespaceHandler.java b/spring-integration-event/src/main/java/org/springframework/integration/event/config/EventNamespaceHandler.java index dea502859f..bb049925db 100644 --- a/spring-integration-event/src/main/java/org/springframework/integration/event/config/EventNamespaceHandler.java +++ b/spring-integration-event/src/main/java/org/springframework/integration/event/config/EventNamespaceHandler.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2009 the original author or authors. + * Copyright 2002-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. diff --git a/spring-integration-event/src/main/java/org/springframework/integration/event/config/EventOutboundChannelAdapterParser.java b/spring-integration-event/src/main/java/org/springframework/integration/event/config/EventOutboundChannelAdapterParser.java index 6dea1cd10e..8e2cd0a5e5 100644 --- a/spring-integration-event/src/main/java/org/springframework/integration/event/config/EventOutboundChannelAdapterParser.java +++ b/spring-integration-event/src/main/java/org/springframework/integration/event/config/EventOutboundChannelAdapterParser.java @@ -13,44 +13,27 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.springframework.integration.event.config; +import org.w3c.dom.Element; + import org.springframework.beans.factory.support.AbstractBeanDefinition; import org.springframework.beans.factory.support.BeanDefinitionBuilder; import org.springframework.beans.factory.xml.ParserContext; import org.springframework.integration.config.xml.AbstractOutboundChannelAdapterParser; -import org.springframework.integration.event.ApplicationEventPublishingMessageHandler; -import org.w3c.dom.Element; /** * @author Oleg Zhurakousky * @since 2.0 */ public class EventOutboundChannelAdapterParser extends AbstractOutboundChannelAdapterParser{ - @Override - protected AbstractBeanDefinition parseConsumer(Element element, - ParserContext parserContext) { - BeanDefinitionBuilder invokerBuilder = BeanDefinitionBuilder.genericBeanDefinition(ApplicationEventPublishingMessageHandler.class); -// BeanComponentDefinition innerHandlerDefinition = -// IntegrationNamespaceUtils.parseInnerHandlerDefinition(element, parserContext); -// if (innerHandlerDefinition == null){ -// Assert.hasText(element.getAttribute(IntegrationNamespaceUtils.REF_ATTRIBUTE), -// "You must provide 'ref' attribute or register inner bean for " + -// "Outbound Channel consumer."); -// invokerBuilder.addConstructorArgReference(element.getAttribute(IntegrationNamespaceUtils.REF_ATTRIBUTE)); -// } else { -// invokerBuilder.addConstructorArgValue(innerHandlerDefinition); -// } -// invokerBuilder.addConstructorArgValue(element.getAttribute(IntegrationNamespaceUtils.METHOD_ATTRIBUTE)); -// String order = element.getAttribute(IntegrationNamespaceUtils.ORDER); -// if (StringUtils.hasText(order)) { -// invokerBuilder.addPropertyValue(IntegrationNamespaceUtils.ORDER, order); -// } - return invokerBuilder.getBeanDefinition(); + protected AbstractBeanDefinition parseConsumer(Element element, ParserContext parserContext) { + BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition( + "org.springframework.integration.event.outbound.ApplicationEventPublishingMessageHandler"); + return builder.getBeanDefinition(); } - - } diff --git a/spring-integration-event/src/main/java/org/springframework/integration/event/MessagingEvent.java b/spring-integration-event/src/main/java/org/springframework/integration/event/core/MessagingEvent.java similarity index 95% rename from spring-integration-event/src/main/java/org/springframework/integration/event/MessagingEvent.java rename to spring-integration-event/src/main/java/org/springframework/integration/event/core/MessagingEvent.java index 8be2fe1eb5..a146355d28 100644 --- a/spring-integration-event/src/main/java/org/springframework/integration/event/MessagingEvent.java +++ b/spring-integration-event/src/main/java/org/springframework/integration/event/core/MessagingEvent.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.springframework.integration.event; +package org.springframework.integration.event.core; import org.springframework.context.ApplicationEvent; import org.springframework.integration.Message; diff --git a/spring-integration-event/src/main/java/org/springframework/integration/event/ApplicationEventInboundChannelAdapter.java b/spring-integration-event/src/main/java/org/springframework/integration/event/inbound/ApplicationEventListeningMessageProducer.java similarity index 80% rename from spring-integration-event/src/main/java/org/springframework/integration/event/ApplicationEventInboundChannelAdapter.java rename to spring-integration-event/src/main/java/org/springframework/integration/event/inbound/ApplicationEventListeningMessageProducer.java index 41f0b99773..41d1a1ad61 100644 --- a/spring-integration-event/src/main/java/org/springframework/integration/event/ApplicationEventInboundChannelAdapter.java +++ b/spring-integration-event/src/main/java/org/springframework/integration/event/inbound/ApplicationEventListeningMessageProducer.java @@ -14,13 +14,14 @@ * limitations under the License. */ -package org.springframework.integration.event; +package org.springframework.integration.event.inbound; import java.util.Set; import java.util.concurrent.CopyOnWriteArraySet; import org.springframework.context.ApplicationEvent; import org.springframework.context.ApplicationListener; +import org.springframework.context.event.ApplicationContextEvent; import org.springframework.expression.Expression; import org.springframework.expression.spel.standard.SpelExpressionParser; import org.springframework.integration.endpoint.MessageProducerSupport; @@ -31,16 +32,18 @@ import org.springframework.util.CollectionUtils; /** * An inbound Channel Adapter that passes Spring {@link ApplicationEvent ApplicationEvents} within messages. * If a {@link #setPayloadExpression(String) payloadExpression} is provided, it will be evaluated against - * the ApplicationEvent instance to create the Message payload. + * the ApplicationEvent instance to create the Message payload. Otherwise, the event itself will be the payload. * * @author Mark Fisher */ -public class ApplicationEventInboundChannelAdapter extends MessageProducerSupport implements ApplicationListener { +public class ApplicationEventListeningMessageProducer extends MessageProducerSupport implements ApplicationListener { private final Set> eventTypes = new CopyOnWriteArraySet>(); private volatile Expression payloadExpression; + private volatile boolean active; + private final SpelExpressionParser parser = new SpelExpressionParser(); @@ -77,29 +80,33 @@ public class ApplicationEventInboundChannelAdapter extends MessageProducerSuppor } public void onApplicationEvent(ApplicationEvent event) { - if (CollectionUtils.isEmpty(this.eventTypes)) { - this.sendEventAsMessage(event); - return; - } - for (Class eventType : this.eventTypes) { - if (eventType.isAssignableFrom(event.getClass())) { + if (this.active || event instanceof ApplicationContextEvent) { + if (CollectionUtils.isEmpty(this.eventTypes)) { this.sendEventAsMessage(event); return; } + for (Class eventType : this.eventTypes) { + if (eventType.isAssignableFrom(event.getClass())) { + this.sendEventAsMessage(event); + return; + } + } } } + @Override + protected void doStart() { + this.active = true; + } + + @Override + protected void doStop() { + this.active = false; + } + private void sendEventAsMessage(ApplicationEvent event) { Object payload = (this.payloadExpression != null) ? this.payloadExpression.getValue(event) : event; this.sendMessage(MessageBuilder.withPayload(payload).build()); } - @Override - protected void doStart() { - } - - @Override - protected void doStop() { - } - } diff --git a/spring-integration-event/src/main/java/org/springframework/integration/event/ApplicationEventPublishingMessageHandler.java b/spring-integration-event/src/main/java/org/springframework/integration/event/outbound/ApplicationEventPublishingMessageHandler.java similarity index 77% rename from spring-integration-event/src/main/java/org/springframework/integration/event/ApplicationEventPublishingMessageHandler.java rename to spring-integration-event/src/main/java/org/springframework/integration/event/outbound/ApplicationEventPublishingMessageHandler.java index 2959c27761..2e4236dadb 100644 --- a/spring-integration-event/src/main/java/org/springframework/integration/event/ApplicationEventPublishingMessageHandler.java +++ b/spring-integration-event/src/main/java/org/springframework/integration/event/outbound/ApplicationEventPublishingMessageHandler.java @@ -14,12 +14,13 @@ * limitations under the License. */ -package org.springframework.integration.event; +package org.springframework.integration.event.outbound; import org.springframework.context.ApplicationEvent; import org.springframework.context.ApplicationEventPublisher; import org.springframework.context.ApplicationEventPublisherAware; import org.springframework.integration.Message; +import org.springframework.integration.event.core.MessagingEvent; import org.springframework.integration.handler.AbstractMessageHandler; import org.springframework.util.Assert; @@ -31,7 +32,7 @@ import org.springframework.util.Assert; * * @author Mark Fisher */ -public class ApplicationEventPublishingMessageHandler extends AbstractMessageHandler implements ApplicationEventPublisherAware { +public class ApplicationEventPublishingMessageHandler extends AbstractMessageHandler implements ApplicationEventPublisherAware { private ApplicationEventPublisher applicationEventPublisher; @@ -43,7 +44,12 @@ public class ApplicationEventPublishingMessageHandler extends AbstractMessage @Override protected void handleMessageInternal(Message message) { Assert.notNull(this.applicationEventPublisher, "applicationEventPublisher is required"); - this.applicationEventPublisher.publishEvent(new MessagingEvent(message)); + if (message.getPayload() instanceof ApplicationEvent) { + this.applicationEventPublisher.publishEvent((ApplicationEvent) message.getPayload()); + } + else { + this.applicationEventPublisher.publishEvent(new MessagingEvent(message)); + } } } diff --git a/spring-integration-event/src/main/resources/org/springframework/integration/event/config/spring-integration-event-2.0.xsd b/spring-integration-event/src/main/resources/org/springframework/integration/event/config/spring-integration-event-2.0.xsd index c57993c7fe..eedb92b4c7 100644 --- a/spring-integration-event/src/main/resources/org/springframework/integration/event/config/spring-integration-event-2.0.xsd +++ b/spring-integration-event/src/main/resources/org/springframework/integration/event/config/spring-integration-event-2.0.xsd @@ -1,104 +1,98 @@ + xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:beans="http://www.springframework.org/schema/beans" + xmlns:tool="http://www.springframework.org/schema/tool" + xmlns:integration="http://www.springframework.org/schema/integration" + targetNamespace="http://www.springframework.org/schema/integration/event" + elementFormDefault="qualified" attributeFormDefault="unqualified"> - - + + - - + - + - - - - Configures an inbound Channel Adapter which listens for an Application Context events, converts them to - Messages and sends them to a 'channel' - - - - - - - - - - - - - Identifies inbound 'channel' which accepts Messages generated from Application Context events. - - - - - - - Comma delimited list of event types (classes that extend ApplicationEvent) that - this adapter should send to the message channel. By default, all event - types will be sent [OPTIONAL] - - - - - - - - - - - - + - Defines a Channel Adapter that receives from a MessageChannel and passes to - a method-invoking - MessageHandler. + Configures an inbound Channel Adapter which listens for Application Context + events, converts them to Messages and sends them to a Message Channel. + + + + + + + + + + + + + The channel to which Messages generated from Application Context events will be sent. + + + + + + + Comma delimited list of event types (classes that extend ApplicationEvent) that this adapter + should send to the message channel. By default, all event types will be sent [OPTIONAL] + + + + + + + + + + + + + + + + Defines a Channel Adapter that receives Messages from a MessageChannel and then publishes + MessagingEvents containing those Messages. - - - - - - Specifies the order for invocation when this endpoint is connected as a - subscriber to a - SubscribableChannel. - - - - - + + + + + + + + + + + + The Message Channel from which this adapter receives Messages. + + + + + + + + Specifies the order for invocation when this endpoint is connected as a + subscriber to a SubscribableChannel. + + + + - - - - - - - - - - - - - - - - - diff --git a/spring-integration-event/src/test/java/org/springframework/integration/event/config/EventInboundChannelAdapterParserTests.java b/spring-integration-event/src/test/java/org/springframework/integration/event/config/EventInboundChannelAdapterParserTests.java index d1e5d9eebc..6eff5c7cea 100644 --- a/spring-integration-event/src/test/java/org/springframework/integration/event/config/EventInboundChannelAdapterParserTests.java +++ b/spring-integration-event/src/test/java/org/springframework/integration/event/config/EventInboundChannelAdapterParserTests.java @@ -36,7 +36,7 @@ import org.springframework.context.event.ContextRefreshedEvent; import org.springframework.expression.Expression; import org.springframework.integration.Message; import org.springframework.integration.core.PollableChannel; -import org.springframework.integration.event.ApplicationEventInboundChannelAdapter; +import org.springframework.integration.event.inbound.ApplicationEventListeningMessageProducer; import org.springframework.integration.history.MessageHistory; import org.springframework.integration.test.util.TestUtils; import org.springframework.test.context.ContextConfiguration; @@ -59,7 +59,7 @@ public class EventInboundChannelAdapterParserTests { public void validateEventParser() { Object adapter = context.getBean("eventAdapterSimple"); Assert.assertNotNull(adapter); - Assert.assertTrue(adapter instanceof ApplicationEventInboundChannelAdapter); + Assert.assertTrue(adapter instanceof ApplicationEventListeningMessageProducer); DirectFieldAccessor adapterAccessor = new DirectFieldAccessor(adapter); Assert.assertEquals(context.getBean("input"), adapterAccessor.getPropertyValue("outputChannel")); } @@ -69,7 +69,7 @@ public class EventInboundChannelAdapterParserTests { public void validateEventParserWithEventTypes() { Object adapter = context.getBean("eventAdapterFiltered"); Assert.assertNotNull(adapter); - Assert.assertTrue(adapter instanceof ApplicationEventInboundChannelAdapter); + Assert.assertTrue(adapter instanceof ApplicationEventListeningMessageProducer); DirectFieldAccessor adapterAccessor = new DirectFieldAccessor(adapter); Assert.assertEquals(context.getBean("inputFiltered"), adapterAccessor.getPropertyValue("outputChannel")); Set> eventTypes = (Set>) adapterAccessor.getPropertyValue("eventTypes"); @@ -84,7 +84,7 @@ public class EventInboundChannelAdapterParserTests { public void validateEventParserWithEventTypesAndPlaceholder() { Object adapter = context.getBean("eventAdapterFilteredPlaceHolder"); Assert.assertNotNull(adapter); - Assert.assertTrue(adapter instanceof ApplicationEventInboundChannelAdapter); + Assert.assertTrue(adapter instanceof ApplicationEventListeningMessageProducer); DirectFieldAccessor adapterAccessor = new DirectFieldAccessor(adapter); Assert.assertEquals(context.getBean("inputFilteredPlaceHolder"), adapterAccessor.getPropertyValue("outputChannel")); Set> eventTypes = (Set>) adapterAccessor.getPropertyValue("eventTypes"); @@ -113,7 +113,7 @@ public class EventInboundChannelAdapterParserTests { public void validatePayloadExpression() { Object adapter = context.getBean("eventAdapterSpel"); Assert.assertNotNull(adapter); - Assert.assertTrue(adapter instanceof ApplicationEventInboundChannelAdapter); + Assert.assertTrue(adapter instanceof ApplicationEventListeningMessageProducer); DirectFieldAccessor adapterAccessor = new DirectFieldAccessor(adapter); Expression expression = (Expression) adapterAccessor.getPropertyValue("payloadExpression"); Assert.assertEquals("source + '-test'", expression.getExpressionString()); diff --git a/spring-integration-event/src/test/java/org/springframework/integration/event/config/EventOutboundChannelAdapterParserTests.java b/spring-integration-event/src/test/java/org/springframework/integration/event/config/EventOutboundChannelAdapterParserTests.java index 32cb017381..caa379e49f 100644 --- a/spring-integration-event/src/test/java/org/springframework/integration/event/config/EventOutboundChannelAdapterParserTests.java +++ b/spring-integration-event/src/test/java/org/springframework/integration/event/config/EventOutboundChannelAdapterParserTests.java @@ -16,6 +16,7 @@ package org.springframework.integration.event.config; +import java.util.concurrent.BrokenBarrierException; import java.util.concurrent.CyclicBarrier; import junit.framework.Assert; @@ -34,7 +35,7 @@ import org.springframework.integration.channel.DirectChannel; import org.springframework.integration.channel.QueueChannel; import org.springframework.integration.core.MessageHandler; import org.springframework.integration.endpoint.EventDrivenConsumer; -import org.springframework.integration.event.ApplicationEventPublishingMessageHandler; +import org.springframework.integration.event.outbound.ApplicationEventPublishingMessageHandler; import org.springframework.integration.message.GenericMessage; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; @@ -46,13 +47,15 @@ import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration public class EventOutboundChannelAdapterParserTests { + @Autowired - private ConfigurableApplicationContext context; - - private boolean recievedEvent; - + private volatile ConfigurableApplicationContext context; + + private volatile boolean receivedEvent; + + @Test - public void validateEventParser(){ + public void validateEventParser() { EventDrivenConsumer adapter = context.getBean("eventAdapter", EventDrivenConsumer.class); Assert.assertNotNull(adapter); DirectFieldAccessor adapterAccessor = new DirectFieldAccessor(adapter); @@ -60,16 +63,16 @@ public class EventOutboundChannelAdapterParserTests { Assert.assertTrue(handler instanceof ApplicationEventPublishingMessageHandler); Assert.assertEquals(context.getBean("input"), adapterAccessor.getPropertyValue("inputChannel")); } + @Test - public void validateUsage(){ - - ApplicationListener listener = new ApplicationListener() { + public void validateUsage() { + ApplicationListener listener = new ApplicationListener() { public void onApplicationEvent(ApplicationEvent event) { Object source = event.getSource(); if (source instanceof Message){ - String payload = (String) ((Message)source).getPayload(); - if (payload.equals("hello")){ - recievedEvent = true; + String payload = (String) ((Message) source).getPayload(); + if (payload.equals("hello")) { + receivedEvent = true; } } } @@ -77,34 +80,38 @@ public class EventOutboundChannelAdapterParserTests { context.addApplicationListener(listener); DirectChannel channel = context.getBean("input", DirectChannel.class); channel.send(new GenericMessage("hello")); - Assert.assertTrue(recievedEvent); + Assert.assertTrue(receivedEvent); } - + @Test(timeout=2000) public void validateUsageWithPollableChannel() throws Exception { - ConfigurableApplicationContext ac = new ClassPathXmlApplicationContext("EventOutboundChannelAdapterParserTestsWithPollable-context.xml", EventOutboundChannelAdapterParserTests.class); + ConfigurableApplicationContext context = new ClassPathXmlApplicationContext("EventOutboundChannelAdapterParserTestsWithPollable-context.xml", EventOutboundChannelAdapterParserTests.class); final CyclicBarrier barier = new CyclicBarrier(2); - ApplicationListener listener = new ApplicationListener() { + ApplicationListener listener = new ApplicationListener() { public void onApplicationEvent(ApplicationEvent event) { Object source = event.getSource(); if (source instanceof Message){ - String payload = (String) ((Message)source).getPayload(); + String payload = (String) ((Message) source).getPayload(); if (payload.equals("hello")){ - recievedEvent = true; + receivedEvent = true; try { barier.await(); - } catch (Exception e) { - e.printStackTrace(); - } + } + catch (InterruptedException e) { + Thread.currentThread().interrupt(); + } + catch (BrokenBarrierException e) { + throw new IllegalStateException("broken barrier", e); + } } } } }; - ac.addApplicationListener(listener); - QueueChannel channel = ac.getBean("input", QueueChannel.class); + context.addApplicationListener(listener); + QueueChannel channel = context.getBean("input", QueueChannel.class); channel.send(new GenericMessage("hello")); barier.await(); - Assert.assertTrue(recievedEvent); + Assert.assertTrue(receivedEvent); } - + } diff --git a/spring-integration-event/src/test/java/org/springframework/integration/event/config/EventOutboundChannelAdapterParserTestsWithPollable-context.xml b/spring-integration-event/src/test/java/org/springframework/integration/event/config/EventOutboundChannelAdapterParserTestsWithPollable-context.xml index c8321ad960..086598d2cc 100644 --- a/spring-integration-event/src/test/java/org/springframework/integration/event/config/EventOutboundChannelAdapterParserTestsWithPollable-context.xml +++ b/spring-integration-event/src/test/java/org/springframework/integration/event/config/EventOutboundChannelAdapterParserTestsWithPollable-context.xml @@ -15,9 +15,7 @@ - - - + diff --git a/spring-integration-event/src/test/java/org/springframework/integration/event/ApplicationEventInboundChannelAdapterTests.java b/spring-integration-event/src/test/java/org/springframework/integration/event/inbound/ApplicationEventListeningMessageProducerTests.java similarity index 89% rename from spring-integration-event/src/test/java/org/springframework/integration/event/ApplicationEventInboundChannelAdapterTests.java rename to spring-integration-event/src/test/java/org/springframework/integration/event/inbound/ApplicationEventListeningMessageProducerTests.java index e044983b9e..6664d3eb2c 100644 --- a/spring-integration-event/src/test/java/org/springframework/integration/event/ApplicationEventInboundChannelAdapterTests.java +++ b/spring-integration-event/src/test/java/org/springframework/integration/event/inbound/ApplicationEventListeningMessageProducerTests.java @@ -14,9 +14,14 @@ * limitations under the License. */ -package org.springframework.integration.event; +package org.springframework.integration.event.inbound; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; import org.junit.Test; + import org.springframework.context.ApplicationEvent; import org.springframework.context.event.ContextClosedEvent; import org.springframework.context.event.ContextRefreshedEvent; @@ -26,21 +31,19 @@ import org.springframework.context.support.ClassPathXmlApplicationContext; import org.springframework.integration.Message; import org.springframework.integration.channel.QueueChannel; import org.springframework.integration.core.PollableChannel; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertNull; +import org.springframework.integration.event.inbound.ApplicationEventListeningMessageProducer; /** * @author Mark Fisher */ -public class ApplicationEventInboundChannelAdapterTests { +public class ApplicationEventListeningMessageProducerTests { @Test public void anyApplicationEventSentByDefault() { QueueChannel channel = new QueueChannel(); - ApplicationEventInboundChannelAdapter adapter = new ApplicationEventInboundChannelAdapter(); + ApplicationEventListeningMessageProducer adapter = new ApplicationEventListeningMessageProducer(); adapter.setOutputChannel(channel); + adapter.start(); Message message1 = channel.receive(0); assertNull(message1); adapter.onApplicationEvent(new TestApplicationEvent1()); @@ -57,9 +60,10 @@ public class ApplicationEventInboundChannelAdapterTests { @SuppressWarnings("unchecked") public void onlyConfiguredEventTypesAreSent() { QueueChannel channel = new QueueChannel(); - ApplicationEventInboundChannelAdapter adapter = new ApplicationEventInboundChannelAdapter(); + ApplicationEventListeningMessageProducer adapter = new ApplicationEventListeningMessageProducer(); adapter.setOutputChannel(channel); adapter.setEventTypes(new Class[]{TestApplicationEvent1.class}); + adapter.start(); Message message1 = channel.receive(0); assertNull(message1); adapter.onApplicationEvent(new TestApplicationEvent1()); @@ -96,9 +100,10 @@ public class ApplicationEventInboundChannelAdapterTests { @Test public void payloadExpressionEvaluatedAgainstApplicationEvent() { QueueChannel channel = new QueueChannel(); - ApplicationEventInboundChannelAdapter adapter = new ApplicationEventInboundChannelAdapter(); + ApplicationEventListeningMessageProducer adapter = new ApplicationEventListeningMessageProducer(); adapter.setPayloadExpression("'received: ' + source"); adapter.setOutputChannel(channel); + adapter.start(); Message message1 = channel.receive(0); assertNull(message1); adapter.onApplicationEvent(new TestApplicationEvent1()); @@ -118,8 +123,6 @@ public class ApplicationEventInboundChannelAdapterTests { public TestApplicationEvent1() { super("event1"); } - - } diff --git a/spring-integration-event/src/test/java/org/springframework/integration/event/applicationEventInboundChannelAdapterTests.xml b/spring-integration-event/src/test/java/org/springframework/integration/event/inbound/applicationEventInboundChannelAdapterTests.xml similarity index 92% rename from spring-integration-event/src/test/java/org/springframework/integration/event/applicationEventInboundChannelAdapterTests.xml rename to spring-integration-event/src/test/java/org/springframework/integration/event/inbound/applicationEventInboundChannelAdapterTests.xml index c99b9a81d7..996da5c8cb 100644 --- a/spring-integration-event/src/test/java/org/springframework/integration/event/applicationEventInboundChannelAdapterTests.xml +++ b/spring-integration-event/src/test/java/org/springframework/integration/event/inbound/applicationEventInboundChannelAdapterTests.xml @@ -9,7 +9,7 @@ - + diff --git a/spring-integration-event/src/test/java/org/springframework/integration/event/ApplicationEventPublishingMessageHandlerTests.java b/spring-integration-event/src/test/java/org/springframework/integration/event/outbound/ApplicationEventPublishingMessageHandlerTests.java similarity index 65% rename from spring-integration-event/src/test/java/org/springframework/integration/event/ApplicationEventPublishingMessageHandlerTests.java rename to spring-integration-event/src/test/java/org/springframework/integration/event/outbound/ApplicationEventPublishingMessageHandlerTests.java index cc05728ea8..41ce0c4d9b 100644 --- a/spring-integration-event/src/test/java/org/springframework/integration/event/ApplicationEventPublishingMessageHandlerTests.java +++ b/spring-integration-event/src/test/java/org/springframework/integration/event/outbound/ApplicationEventPublishingMessageHandlerTests.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.springframework.integration.event; +package org.springframework.integration.event.outbound; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNull; @@ -24,6 +24,8 @@ import org.junit.Test; import org.springframework.context.ApplicationEvent; import org.springframework.context.ApplicationEventPublisher; import org.springframework.integration.Message; +import org.springframework.integration.event.core.MessagingEvent; +import org.springframework.integration.event.outbound.ApplicationEventPublishingMessageHandler; import org.springframework.integration.message.GenericMessage; /** @@ -32,8 +34,7 @@ import org.springframework.integration.message.GenericMessage; public class ApplicationEventPublishingMessageHandlerTests { @Test - @SuppressWarnings("unchecked") - public void testSendingEvent() throws InterruptedException { + public void messagingEvent() throws InterruptedException { TestApplicationEventPublisher publisher = new TestApplicationEventPublisher(); ApplicationEventPublishingMessageHandler handler = new ApplicationEventPublishingMessageHandler(); handler.setApplicationEventPublisher(publisher); @@ -45,6 +46,19 @@ public class ApplicationEventPublishingMessageHandlerTests { assertEquals(message, ((MessagingEvent) event).getMessage()); } + @Test + public void payloadAsEvent() { + TestApplicationEventPublisher publisher = new TestApplicationEventPublisher(); + ApplicationEventPublishingMessageHandler handler = new ApplicationEventPublishingMessageHandler(); + handler.setApplicationEventPublisher(publisher); + assertNull(publisher.getLastEvent()); + Message message = new GenericMessage(new TestEvent("foo")); + handler.handleMessage(message); + ApplicationEvent event = publisher.getLastEvent(); + assertEquals(TestEvent.class, event.getClass()); + assertEquals("foo", ((TestEvent) event).getSource()); + } + private static class TestApplicationEventPublisher implements ApplicationEventPublisher { @@ -59,4 +73,13 @@ public class ApplicationEventPublishingMessageHandlerTests { } } + + @SuppressWarnings("serial") + private static class TestEvent extends ApplicationEvent { + + public TestEvent(String text) { + super(text); + } + } + } From d8ca51abc248d8d5e23cb59ac8ad07d602c6c3ce Mon Sep 17 00:00:00 2001 From: Mark Fisher Date: Wed, 3 Nov 2010 12:56:17 -0400 Subject: [PATCH 21/82] INT-1583 if received event has a Message as its source, it will be passed as-is --- ...licationEventListeningMessageProducer.java | 10 ++++- ...ionEventListeningMessageProducerTests.java | 40 ++++++++++++++++++- 2 files changed, 47 insertions(+), 3 deletions(-) diff --git a/spring-integration-event/src/main/java/org/springframework/integration/event/inbound/ApplicationEventListeningMessageProducer.java b/spring-integration-event/src/main/java/org/springframework/integration/event/inbound/ApplicationEventListeningMessageProducer.java index 41d1a1ad61..6ca0b752b3 100644 --- a/spring-integration-event/src/main/java/org/springframework/integration/event/inbound/ApplicationEventListeningMessageProducer.java +++ b/spring-integration-event/src/main/java/org/springframework/integration/event/inbound/ApplicationEventListeningMessageProducer.java @@ -24,6 +24,7 @@ import org.springframework.context.ApplicationListener; import org.springframework.context.event.ApplicationContextEvent; import org.springframework.expression.Expression; import org.springframework.expression.spel.standard.SpelExpressionParser; +import org.springframework.integration.Message; import org.springframework.integration.endpoint.MessageProducerSupport; import org.springframework.integration.support.MessageBuilder; import org.springframework.util.Assert; @@ -105,8 +106,13 @@ public class ApplicationEventListeningMessageProducer extends MessageProducerSup } private void sendEventAsMessage(ApplicationEvent event) { - Object payload = (this.payloadExpression != null) ? this.payloadExpression.getValue(event) : event; - this.sendMessage(MessageBuilder.withPayload(payload).build()); + if (event.getSource() instanceof Message) { + this.sendMessage((Message) event.getSource()); + } + else { + Object payload = (this.payloadExpression != null) ? this.payloadExpression.getValue(event) : event; + this.sendMessage(MessageBuilder.withPayload(payload).build()); + } } } diff --git a/spring-integration-event/src/test/java/org/springframework/integration/event/inbound/ApplicationEventListeningMessageProducerTests.java b/spring-integration-event/src/test/java/org/springframework/integration/event/inbound/ApplicationEventListeningMessageProducerTests.java index 6664d3eb2c..7424a89ab8 100644 --- a/spring-integration-event/src/test/java/org/springframework/integration/event/inbound/ApplicationEventListeningMessageProducerTests.java +++ b/spring-integration-event/src/test/java/org/springframework/integration/event/inbound/ApplicationEventListeningMessageProducerTests.java @@ -31,7 +31,8 @@ import org.springframework.context.support.ClassPathXmlApplicationContext; import org.springframework.integration.Message; import org.springframework.integration.channel.QueueChannel; import org.springframework.integration.core.PollableChannel; -import org.springframework.integration.event.inbound.ApplicationEventListeningMessageProducer; +import org.springframework.integration.event.core.MessagingEvent; +import org.springframework.integration.message.GenericMessage; /** * @author Mark Fisher @@ -116,6 +117,34 @@ public class ApplicationEventListeningMessageProducerTests { assertEquals("received: event2", message3.getPayload()); } + @Test + public void messagingEventReceived() { + QueueChannel channel = new QueueChannel(); + ApplicationEventListeningMessageProducer adapter = new ApplicationEventListeningMessageProducer(); + adapter.setOutputChannel(channel); + adapter.start(); + Message message1 = channel.receive(0); + assertNull(message1); + adapter.onApplicationEvent(new MessagingEvent(new GenericMessage("test"))); + Message message2 = channel.receive(20); + assertNotNull(message2); + assertEquals("test", message2.getPayload()); + } + + @Test + public void messageAsSourceOrCustomEventType() { + QueueChannel channel = new QueueChannel(); + ApplicationEventListeningMessageProducer adapter = new ApplicationEventListeningMessageProducer(); + adapter.setOutputChannel(channel); + adapter.start(); + Message message1 = channel.receive(0); + assertNull(message1); + adapter.onApplicationEvent(new TestMessagingEvent(new GenericMessage("test"))); + Message message2 = channel.receive(20); + assertNotNull(message2); + assertEquals("test", message2.getPayload()); + } + @SuppressWarnings("serial") private static class TestApplicationEvent1 extends ApplicationEvent { @@ -134,4 +163,13 @@ public class ApplicationEventListeningMessageProducerTests { } } + + @SuppressWarnings("serial") + private static class TestMessagingEvent extends ApplicationEvent { + + public TestMessagingEvent(Message message) { + super(message); + } + } + } From e35de5a05433767462e45c495f56d3077cafadb1 Mon Sep 17 00:00:00 2001 From: Mark Fisher Date: Wed, 3 Nov 2010 13:03:49 -0400 Subject: [PATCH 22/82] INT-1583 updated documentation --- docs/src/reference/docbook/event.xml | 69 ++++++++++++++++------------ 1 file changed, 40 insertions(+), 29 deletions(-) diff --git a/docs/src/reference/docbook/event.xml b/docs/src/reference/docbook/event.xml index cc6336d97a..9f759ef787 100644 --- a/docs/src/reference/docbook/event.xml +++ b/docs/src/reference/docbook/event.xml @@ -1,50 +1,59 @@ + Spring ApplicationEvent Support Spring Integration provides support for inbound and outbound ApplicationEvents - as defined by the underlying Spring Framework. For more information about the events and listeners, + as defined by the underlying Spring Framework. For more information about Spring's support for events and listeners, refer to the Spring Reference Manual.
Receiving Spring ApplicationEvents - - To receive events and send them to a channel, simply define an instance of Spring Integration's - ApplicationEventListeningMessageProducer. This class is an implementation of - Spring's ApplicationListener interface. By default it will pass all - received events as Spring Integration Messages. To limit based on the type of event, configure the - list of event types that you want to receive with the 'eventTypes' property. - - - For convenience namespace support was provided to configure ApplicationEventListeningMessageProducer via inbound-channel-adapter - + + To receive events and send them to a channel, simply define an instance of Spring Integration's + ApplicationEventListeningMessageProducer. This class is an implementation of + Spring's ApplicationListener interface. By default it will pass all + received events as Spring Integration Messages. To limit based on the type of event, configure the + list of event types that you want to receive with the 'eventTypes' property. If a received event + has a Message instance as its 'source', then that will be passed as-is. Otherwise, if a SpEL-based + "payloadExpression" has been provided, that will be evaluated against the ApplicationEvent instance. + If the event's source is not a Message instance and no "payloadExpression" has been provided, then + the ApplicationEvent itself will be passed as the payload. + + + For convenience namespace support is provided to configure an ApplicationEventListeningMessageProducer + via the inbound-channel-adapter element. + ]]> In the above example, all Application Context events that match one of the types specified by the 'event-types' (optional) attribute will be -delivered as Spring Integration Messages to 'eventChannel'. - - +delivered as Spring Integration Messages to the Message Channel named 'eventChannel'. +
- Sending Spring ApplicationEvents - - To send Spring ApplicationEvents, create an instance of the - ApplicationEventPublishingMessageHandler and register it within an endpoint. - This implementation of the MessageHandler interface also implements - Spring's ApplicationEventPublisherAware interface and thus acts as a - bridge between Spring Integration Messages and ApplicationEvents. - - - For convenience namespace support was provided to configure ApplicationEventPublishingMessageHandler via outbound-channel-adapter element - + Sending Spring ApplicationEvents + + To send Spring ApplicationEvents, create an instance of the + ApplicationEventPublishingMessageHandler and register it within an endpoint. + This implementation of the MessageHandler interface also implements + Spring's ApplicationEventPublisherAware interface and thus acts as a + bridge between Spring Integration Messages and ApplicationEvents. + + + + For convenience namespace support is provided to configure an ApplicationEventPublishingMessageHandler + via the outbound-channel-adapter element. + ]]> -If you are using a PollableChannel (e.g., Queue), you can also provide poller as a sub-element of the outbound-channel-adapter element. You can also optionally provide a task-executor reference for that poller. - + If you are using a PollableChannel (e.g., Queue), you can also provide poller as a sub-element of the + outbound-channel-adapter element. You can also optionally provide a task-executor + reference for that poller. The following example demonstrates both. + @@ -54,8 +63,10 @@ If you are using a PollableChannel (e.g., Queue), you can also provide ]]> -In the above example, all messages sent to the 'eventChannel' channel will be published as ApplicationEvents to any relevant ApplicationListeners within the Spring ApplicationContext. If the payload of the Message is an ApplicationEvent, it will be passed as-is. Otherwise the Message itself will be wrapped in a MessagingEvent instance. - + In the above example, all messages sent to the 'eventChannel' channel will be published as ApplicationEvents to any relevant + ApplicationListener instances that are registered within the same Spring ApplicationContext. If the payload of the Message is + an ApplicationEvent, it will be passed as-is. Otherwise the Message itself will be wrapped in a MessagingEvent instance. +
From 9e178c1de8fb27085fcf715991ae723f88ffa34e Mon Sep 17 00:00:00 2001 From: Oleg Zhurakousky Date: Wed, 3 Nov 2010 16:12:40 -0400 Subject: [PATCH 23/82] INT-1580 changed XmppConnectionFactoryBean to be bootstrapped with ConnectionConfiguration --- .../xmpp/SslXmppConnectionFactory.java | 106 -------- .../xmpp/XmppConnectionFactory.java | 232 ------------------ .../xmpp/XmppConnectionFactoryBean.java | 111 +++++++++ .../xmpp/config/XmppConnectionParser.java | 55 +++++ .../xmpp/config/XmppNamespaceHandler.java | 71 +++--- .../messages/XmppMessageDrivenEndpoint.java | 2 - .../XmppRosterEventMessageDrivenEndpoint.java | 2 +- .../main/resources/META-INF/smack-config.xml | 24 ++ .../config/spring-integration-xmpp-2.0.xsd | 6 +- .../XmppConnectionParserTest-simple.xml | 13 + .../config/XmppConnectionParserTests.java | 24 ++ .../InboundXmppEndpointParserTests.java | 2 + 12 files changed, 268 insertions(+), 380 deletions(-) delete mode 100644 spring-integration-xmpp/src/main/java/org/springframework/integration/xmpp/SslXmppConnectionFactory.java delete mode 100644 spring-integration-xmpp/src/main/java/org/springframework/integration/xmpp/XmppConnectionFactory.java create mode 100644 spring-integration-xmpp/src/main/java/org/springframework/integration/xmpp/XmppConnectionFactoryBean.java create mode 100644 spring-integration-xmpp/src/main/java/org/springframework/integration/xmpp/config/XmppConnectionParser.java create mode 100644 spring-integration-xmpp/src/main/resources/META-INF/smack-config.xml create mode 100644 spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/config/XmppConnectionParserTest-simple.xml create mode 100644 spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/config/XmppConnectionParserTests.java diff --git a/spring-integration-xmpp/src/main/java/org/springframework/integration/xmpp/SslXmppConnectionFactory.java b/spring-integration-xmpp/src/main/java/org/springframework/integration/xmpp/SslXmppConnectionFactory.java deleted file mode 100644 index 0cbf6f2382..0000000000 --- a/spring-integration-xmpp/src/main/java/org/springframework/integration/xmpp/SslXmppConnectionFactory.java +++ /dev/null @@ -1,106 +0,0 @@ -package org.springframework.integration.xmpp; - -import org.jivesoftware.smack.ConnectionConfiguration; -import org.springframework.core.io.Resource; -import org.springframework.util.Assert; -import org.springframework.util.StringUtils; - -import javax.net.SocketFactory; -import javax.net.ssl.SSLSocketFactory; - - -/** - * An extension of {@link org.springframework.integration.xmpp.XmppConnectionFactory} that handles factorying a secure XMPP connection factory. - *

- * This is interchangeable with existing {@link org.jivesoftware.smack.XMPPConnection} references, of course. - * - * @author Josh Long - */ -public class SslXmppConnectionFactory extends XmppConnectionFactory { - private volatile String trustStorePassword; - private volatile String trustStoreType; - private volatile Resource trustStore; - private volatile boolean securityEnabled = true; - private volatile SocketFactory socketFactory; - private volatile ConnectionConfiguration.SecurityMode securityMode = ConnectionConfiguration.SecurityMode.enabled; - - /** - * This method is a callback provided by the super type that lets us plugin to the configuration mechanism - * - * @param connectionConfiguration the connection Configuration - * @throws Exception - */ - - @Override - protected void setupConnectionConfiguration(ConnectionConfiguration connectionConfiguration) throws Exception { - - this.securityEnabled = securityMode != null && - (ConnectionConfiguration.SecurityMode.enabled.equals(securityMode) || - ConnectionConfiguration.SecurityMode.required.equals(securityMode)); - - if (this.securityEnabled) { - if (this.socketFactory == null) { - this.socketFactory = SSLSocketFactory.getDefault(); - } - - Assert.notNull(this.trustStore, "'trustStore' must not be null"); - - String trustStorePath = this.trustStore.toString(); - connectionConfiguration.setTruststorePath(trustStorePath); - - // not required - if (StringUtils.hasText(this.trustStorePassword)) - connectionConfiguration.setTruststorePassword(this.trustStorePassword); - - // not required - if (StringUtils.hasText(this.trustStoreType)) - connectionConfiguration.setTruststoreType(this.trustStoreType); - } - } - - /** - * Not required. If not specified, we will load reference using {@link javax.net.ssl.SSLSocketFactory#getDefault()} - * - * @param socketFactory the socket factory to be passed to the {@link org.jivesoftware.smack.ConnectionConfiguration} - */ - public void setSocketFactory(SocketFactory socketFactory) { - this.socketFactory = socketFactory; - } - - /** - * the password to use to access the trust store (optional) - * - * @param trustStorePassword - */ - public void setTrustStorePassword(String trustStorePassword) { - this.trustStorePassword = trustStorePassword; - } - - /** - * This is required and specifies the path to the keystore (ie: /path/to/foo.jks) - * - * @param trustStore a {@link org.springframework.core.io.Resource} to the path itself - */ - public void setTrustStore(Resource trustStore) { - this.trustStore = trustStore; - } - - /** - * the type of trust store. - * - * @param trustStoreType the type of trust store - */ - public void setTrustStoreType(String trustStoreType) { - this.trustStoreType = trustStoreType; - } - - - /** - * used on {@link org.jivesoftware.smack.ConnectionConfiguration#setSecurityMode(org.jivesoftware.smack.ConnectionConfiguration.SecurityMode)} - *

- * basically, if you're using this class we assume you want security enabled. If you don't you can always override it by specifying {@link org.jivesoftware.smack.ConnectionConfiguration.SecurityMode#disabled} - */ - public void setSecurityMode(ConnectionConfiguration.SecurityMode securityMode) { - this.securityMode = securityMode; - } -} diff --git a/spring-integration-xmpp/src/main/java/org/springframework/integration/xmpp/XmppConnectionFactory.java b/spring-integration-xmpp/src/main/java/org/springframework/integration/xmpp/XmppConnectionFactory.java deleted file mode 100644 index a7592b1127..0000000000 --- a/spring-integration-xmpp/src/main/java/org/springframework/integration/xmpp/XmppConnectionFactory.java +++ /dev/null @@ -1,232 +0,0 @@ -/* - * Copyright 2002-2010 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.integration.xmpp; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.jivesoftware.smack.ConnectionConfiguration; -import org.jivesoftware.smack.Roster; -import org.jivesoftware.smack.SASLAuthentication; -import org.jivesoftware.smack.XMPPConnection; -import org.springframework.beans.factory.config.AbstractFactoryBean; -import org.springframework.util.StringUtils; - -/** - * This class configures an {@link org.jivesoftware.smack.XMPPConnection} object. This object is used for all scenarios to talk to a Smack server. - * - * @author Josh Long - * @author Mark Fisher - * @see org.jivesoftware.smack.XMPPConnection - * @since 2.0 - */ -public class XmppConnectionFactory extends AbstractFactoryBean { - // TODO provide a default subscription mode for this class: Roster.setSubscriptionMode(Roster.SubscriptionMode) - private static final Log logger = LogFactory.getLog(XmppConnectionFactory.class); - - private volatile String user; - - private volatile String password; - - private volatile String host; - - private volatile String serviceName; - - private volatile String resource; - - private volatile String saslMechanismSupported; - - private volatile int saslMechanismSupportedIndex; - - private volatile int port; - - private volatile String subscriptionMode; - - - private volatile boolean debug = false; - - public XmppConnectionFactory() { - } - - public XmppConnectionFactory(String user, String password, String host, String serviceName, String resource, String saslMechanismSupported, int saslMechanismSupportedIndex, int port) { - this.user = user; - this.password = password; - this.host = host; - this.serviceName = serviceName; - this.resource = resource; - this.saslMechanismSupported = saslMechanismSupported; - this.saslMechanismSupportedIndex = saslMechanismSupportedIndex; - this.port = port; - } - - public String getUser() { - return user; - } - - public void setUser(String user) { - this.user = user; - } - - public String getPassword() { - return password; - } - - public void setPassword(String password) { - this.password = password; - } - - public String getHost() { - return host; - } - - public void setHost(String host) { - this.host = host; - } - - public String getServiceName() { - return serviceName; - } - - public void setServiceName(String serviceName) { - this.serviceName = serviceName; - } - - public String getResource() { - return resource; - } - - public void setResource(String resource) { - this.resource = resource; - } - - public String getSaslMechanismSupported() { - return saslMechanismSupported; - } - - public void setSaslMechanismSupported(String saslMechanismSupported) { - this.saslMechanismSupported = saslMechanismSupported; - } - - public int getSaslMechanismSupportedIndex() { - return saslMechanismSupportedIndex; - } - - public void setSaslMechanismSupportedIndex(int saslMechanismSupportedIndex) { - this.saslMechanismSupportedIndex = saslMechanismSupportedIndex; - } - - public int getPort() { - return port; - } - - public void setPort(int port) { - this.port = port; - } - - public boolean isDebug() { - return debug; - } - - public void setDebug(boolean debug) { - XMPPConnection.DEBUG_ENABLED = debug; - this.debug = debug; - } - - - public void setSubscriptionMode(final String subscriptionMode) { - this.subscriptionMode = subscriptionMode; - } - - - @Override - public Class getObjectType() { - return XMPPConnection.class; - } - - /** - * this provides a hook for subclasses to provide extra setup before the {@link org.jivesoftware.smack.XMPPConnection} is created - * - * @param xmppConnection the connection to configure - * @throws Exception - */ - protected void setupXmppConnectionConfiguration(XMPPConnection xmppConnection) throws Exception { - // noop - } - - /** - * this provides a hook for subclasses to provide extra setup before the {@link org.jivesoftware.smack.ConnectionConfiguration} is created. - * - * @param connectionConfiguration - * @throws Exception - */ - protected void setupConnectionConfiguration(ConnectionConfiguration connectionConfiguration) throws Exception { - // noop - } - - protected XMPPConnection configureAndConnect(String usr, String pw, String host, int port, String serviceName, String resource, String saslMechanismSupported, int saslMechanismSupportedIndex) { - if (logger.isDebugEnabled()) { - logger.debug(String.format("usr=%s, pw=%s, host=%s, port=%s, serviceName=%s, resource=%s, saslMechanismSupported=%s, saslMechanismSupportedIndex=%s", usr, pw, host, port, serviceName, - resource, saslMechanismSupported, saslMechanismSupportedIndex)); - } - - try { - - XMPPConnection.DEBUG_ENABLED = false; // default - - ConnectionConfiguration connectionConfiguration = new ConnectionConfiguration(host, port, serviceName); - setupConnectionConfiguration(connectionConfiguration); - XMPPConnection connection = new XMPPConnection(connectionConfiguration); - - - setupXmppConnectionConfiguration(connection); - - connection.connect(); - - // You have to put this code before you login - if (StringUtils.hasText(saslMechanismSupported)) { - SASLAuthentication.supportSASLMechanism(saslMechanismSupported, saslMechanismSupportedIndex); - } - - - // You have to specify the resoure (e.g. "@host.com") at the end - if (StringUtils.hasText(resource)) { - connection.login(usr, pw, resource); - } else { - connection.login(usr, pw); - } - - if (StringUtils.hasText(this.subscriptionMode)) { - Roster.SubscriptionMode subscriptionMode = Roster.SubscriptionMode.valueOf(this.subscriptionMode); - connection.getRoster().setSubscriptionMode(subscriptionMode); - } - - if (logger.isDebugEnabled()) { - logger.debug("authenticated? " + connection.isAuthenticated()); - } - - return connection; - } catch (Exception e) { - logger.warn("failed to establish XMPP connnection", e); - } - return null; - } - - - @Override - protected XMPPConnection createInstance() throws Exception { - return this.configureAndConnect(this.getUser(), this.getPassword(), this.getHost(), this.getPort(), this.getServiceName(), this.getResource(), this.getSaslMechanismSupported(), - this.getSaslMechanismSupportedIndex()); - } -} diff --git a/spring-integration-xmpp/src/main/java/org/springframework/integration/xmpp/XmppConnectionFactoryBean.java b/spring-integration-xmpp/src/main/java/org/springframework/integration/xmpp/XmppConnectionFactoryBean.java new file mode 100644 index 0000000000..a61d40b946 --- /dev/null +++ b/spring-integration-xmpp/src/main/java/org/springframework/integration/xmpp/XmppConnectionFactoryBean.java @@ -0,0 +1,111 @@ +/* + * Copyright 2002-2010 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.integration.xmpp; + +import org.jivesoftware.smack.ConnectionConfiguration; +import org.jivesoftware.smack.Roster; +import org.jivesoftware.smack.XMPPConnection; +import org.springframework.beans.factory.config.AbstractFactoryBean; +import org.springframework.util.Assert; +import org.springframework.util.StringUtils; + +/** + * This class configures an {@link org.jivesoftware.smack.XMPPConnection} object. + * This object is used for all scenarios to talk to a Smack server. + * + * @author Josh Long + * @author Mark Fisher + * @author Oleg Zhurakousky + * @see org.jivesoftware.smack.XMPPConnection + * @since 2.0 + */ +public class XmppConnectionFactoryBean extends AbstractFactoryBean { + + private volatile ConnectionConfiguration connectionConfiguration; + + private volatile String resource = "Smack"; // default value used by Smack + + private volatile String user; + + private volatile String password; + + private volatile String subscriptionMode = "accept_all"; + + public XmppConnectionFactoryBean(ConnectionConfiguration connectionConfiguration) { + Assert.notNull(connectionConfiguration, "'connectionConfiguration' must not be null"); + this.connectionConfiguration = connectionConfiguration; + } + + public String getSubscriptionMode() { + return subscriptionMode; + } + + public void setSubscriptionMode(String subscriptionMode) { + this.subscriptionMode = subscriptionMode; + } + + public String getUser() { + return user; + } + + public void setUser(String user) { + this.user = user; + } + + public String getPassword() { + return password; + } + + public void setPassword(String password) { + this.password = password; + } + + public void setResource(String resource) { + this.resource = resource; + } + + public String getResource() { + return resource; + } + + @Override + public Class getObjectType() { + return XMPPConnection.class; + } + + @Override + protected XMPPConnection createInstance() throws Exception { + Assert.notNull(connectionConfiguration, "'connectionConfiguration' must not be null"); + + XMPPConnection connection = new XMPPConnection(connectionConfiguration); + connection.connect(); + if (StringUtils.hasText(user)){ + connection.login(user, password, resource); + + Assert.isTrue(connection.isAuthenticated(), "Failed to authenticate user: " + user); + + if (StringUtils.hasText(this.subscriptionMode)) { + Roster.SubscriptionMode subscriptionMode = Roster.SubscriptionMode.valueOf(this.subscriptionMode); + connection.getRoster().setSubscriptionMode(subscriptionMode); + } + } + else { + connection.loginAnonymously(); + } + + return connection; + } +} diff --git a/spring-integration-xmpp/src/main/java/org/springframework/integration/xmpp/config/XmppConnectionParser.java b/spring-integration-xmpp/src/main/java/org/springframework/integration/xmpp/config/XmppConnectionParser.java new file mode 100644 index 0000000000..45fe5a1cf3 --- /dev/null +++ b/spring-integration-xmpp/src/main/java/org/springframework/integration/xmpp/config/XmppConnectionParser.java @@ -0,0 +1,55 @@ +/** + * + */ +package org.springframework.integration.xmpp.config; + +import org.springframework.beans.factory.support.BeanDefinitionBuilder; +import org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser; +import org.springframework.beans.factory.xml.ParserContext; +import org.springframework.integration.config.xml.IntegrationNamespaceUtils; +import org.springframework.util.Assert; +import org.springframework.util.StringUtils; +import org.w3c.dom.Element; + +/** + * @author ozhurakousky + * + */ +public class XmppConnectionParser extends AbstractSingleBeanDefinitionParser { + private static String[] connectionFactoryAttributes = + new String[]{"userid", "password", "resource","subscription-mode"}; + + @Override + protected String getBeanClassName(Element element) { + return "org.springframework.integration.xmpp" + ".XmppConnectionFactoryBean"; + } + + @Override + protected boolean shouldGenerateIdAsFallback() { + return true; + } + + @Override + protected void doParse(Element element, ParserContext parserContext, BeanDefinitionBuilder builder) { + String serviceName = element.getAttribute("service-name"); + String host = element.getAttribute("host"); + String port = element.getAttribute("port"); + BeanDefinitionBuilder connectionConfigurationBuilder = + BeanDefinitionBuilder.genericBeanDefinition("org.jivesoftware.smack.ConnectionConfiguration"); + if (StringUtils.hasText(host)) { + Assert.hasLength(port, "Port must be provided if 'host' is specified"); + connectionConfigurationBuilder.addConstructorArgValue(host); + connectionConfigurationBuilder.addConstructorArgValue(port); + } + else { + Assert.hasText(serviceName, "'serviceName' is requuired if 'host' is not provided"); + } + if (StringUtils.hasText(serviceName)){ + connectionConfigurationBuilder.addConstructorArgValue(port); + } + for (String attribute : connectionFactoryAttributes) { + IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, attribute); + } + builder.addConstructorArgValue(connectionConfigurationBuilder.getBeanDefinition()); + } +} diff --git a/spring-integration-xmpp/src/main/java/org/springframework/integration/xmpp/config/XmppNamespaceHandler.java b/spring-integration-xmpp/src/main/java/org/springframework/integration/xmpp/config/XmppNamespaceHandler.java index 6e6846c4f1..a56b8b0201 100644 --- a/spring-integration-xmpp/src/main/java/org/springframework/integration/xmpp/config/XmppNamespaceHandler.java +++ b/spring-integration-xmpp/src/main/java/org/springframework/integration/xmpp/config/XmppNamespaceHandler.java @@ -26,7 +26,6 @@ import org.springframework.integration.config.xml.AbstractOutboundChannelAdapter import org.springframework.integration.config.xml.HeaderEnricherParserSupport; import org.springframework.integration.config.xml.IntegrationNamespaceUtils; import org.springframework.integration.xmpp.XmppHeaders; -import org.springframework.util.StringUtils; import org.w3c.dom.Element; /** @@ -40,10 +39,10 @@ public class XmppNamespaceHandler extends NamespaceHandlerSupport { private static final String PACKAGE_NAME = "org.springframework.integration.xmpp"; - private static String[] attributes = new String[]{ - "user", "password", "host", "service-name", "resource", - "sasl-mechanism-supported", "sasl-mechanism-supported-index", "port", "subscription-mode" - }; +// private static String[] connectionFactoryAttributes = +// new String[]{"userid", "password", "resource","subscription-mode"}; + + public void init() { @@ -62,37 +61,37 @@ public class XmppNamespaceHandler extends NamespaceHandlerSupport { } - private static void configureXMPPConnection(Element element, BeanDefinitionBuilder builder, ParserContext parserContext) { - String ref = element.getAttribute("xmpp-connection"); - if (StringUtils.hasText(ref)) { - builder.addPropertyReference("xmppConnection", ref); - } else { - for (String attribute : attributes) { - IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, attribute); - } - } - } +// private static void configureXMPPConnection(Element element, BeanDefinitionBuilder builder, ParserContext parserContext) { +// String ref = element.getAttribute("xmpp-connection"); +// if (StringUtils.hasText(ref)) { +// builder.addPropertyReference("xmppConnection", ref); +// } else { +// for (String attribute : attributes) { +// IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, attribute); +// } +// } +// } // connection management - private static class XmppConnectionParser extends AbstractSingleBeanDefinitionParser { - - @Override - protected String getBeanClassName(Element element) { - return PACKAGE_NAME + ".XmppConnectionFactory"; - } - - @Override - protected boolean shouldGenerateIdAsFallback() { - return true; - } - - @Override - protected void doParse(Element element, ParserContext parserContext, BeanDefinitionBuilder builder) { - configureXMPPConnection(element, builder, parserContext); - } - } +// private static class XmppConnectionParser extends AbstractSingleBeanDefinitionParser { +// +// @Override +// protected String getBeanClassName(Element element) { +// return PACKAGE_NAME + ".XmppConnectionFactory"; +// } +// +// @Override +// protected boolean shouldGenerateIdAsFallback() { +// return true; +// } +// +// @Override +// protected void doParse(Element element, ParserContext parserContext, BeanDefinitionBuilder builder) { +// configureXMPPConnection(element, builder, parserContext); +// } +// } // messages @@ -102,7 +101,7 @@ public class XmppNamespaceHandler extends NamespaceHandlerSupport { protected AbstractBeanDefinition parseConsumer(Element element, ParserContext parserContext) { BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition( PACKAGE_NAME + ".messages.XmppMessageSendingMessageHandler"); - configureXMPPConnection(element, builder, parserContext); + //configureXMPPConnection(element, builder, parserContext); return builder.getBeanDefinition(); } } @@ -121,7 +120,7 @@ public class XmppNamespaceHandler extends NamespaceHandlerSupport { @Override protected void doParse(Element element, ParserContext parserContext, BeanDefinitionBuilder builder) { - configureXMPPConnection(element, builder, parserContext); + //configureXMPPConnection(element, builder, parserContext); IntegrationNamespaceUtils.setReferenceIfAttributeDefined(builder, element, "channel", "requestChannel"); IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, "extract-payload"); IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, "auto-startup"); @@ -134,7 +133,7 @@ public class XmppNamespaceHandler extends NamespaceHandlerSupport { protected AbstractBeanDefinition parseConsumer(Element element, ParserContext parserContext) { BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition( PACKAGE_NAME + ".presence.XmppRosterEventMessageSendingHandler"); - configureXMPPConnection(element, builder, parserContext); + //configureXMPPConnection(element, builder, parserContext); return builder.getBeanDefinition(); } } @@ -153,7 +152,7 @@ public class XmppNamespaceHandler extends NamespaceHandlerSupport { @Override protected void doParse(Element element, ParserContext parserContext, BeanDefinitionBuilder builder) { - configureXMPPConnection(element, builder, parserContext); + //configureXMPPConnection(element, builder, parserContext); IntegrationNamespaceUtils.setReferenceIfAttributeDefined(builder, element, "channel", "requestChannel"); IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, "extract-payload"); IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, "auto-startup"); diff --git a/spring-integration-xmpp/src/main/java/org/springframework/integration/xmpp/messages/XmppMessageDrivenEndpoint.java b/spring-integration-xmpp/src/main/java/org/springframework/integration/xmpp/messages/XmppMessageDrivenEndpoint.java index 79d61e89bc..89f1633b8a 100644 --- a/spring-integration-xmpp/src/main/java/org/springframework/integration/xmpp/messages/XmppMessageDrivenEndpoint.java +++ b/spring-integration-xmpp/src/main/java/org/springframework/integration/xmpp/messages/XmppMessageDrivenEndpoint.java @@ -18,7 +18,6 @@ package org.springframework.integration.xmpp.messages; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; - import org.jivesoftware.smack.Chat; import org.jivesoftware.smack.ChatManager; import org.jivesoftware.smack.PacketListener; @@ -29,7 +28,6 @@ import org.springframework.integration.MessageChannel; import org.springframework.integration.core.MessagingTemplate; import org.springframework.integration.endpoint.AbstractEndpoint; import org.springframework.integration.support.MessageBuilder; -import org.springframework.integration.xmpp.XmppConnectionFactory; import org.springframework.integration.xmpp.XmppHeaders; /** diff --git a/spring-integration-xmpp/src/main/java/org/springframework/integration/xmpp/presence/XmppRosterEventMessageDrivenEndpoint.java b/spring-integration-xmpp/src/main/java/org/springframework/integration/xmpp/presence/XmppRosterEventMessageDrivenEndpoint.java index 3ef78717a9..77a3bfbd86 100644 --- a/spring-integration-xmpp/src/main/java/org/springframework/integration/xmpp/presence/XmppRosterEventMessageDrivenEndpoint.java +++ b/spring-integration-xmpp/src/main/java/org/springframework/integration/xmpp/presence/XmppRosterEventMessageDrivenEndpoint.java @@ -34,7 +34,7 @@ import java.util.Collection; /** - * Describes an endpoint that is able to login as usual with a {@link org.springframework.integration.xmpp.XmppConnectionFactory} and then emit {@link org.springframework.integration.Message}s when a particular event happens to the logged in users {@link org.jivesoftware.smack.Roster}. We try + * Describes an endpoint that is able to login as usual with a {@link org.springframework.integration.xmpp.XmppConnectionFactoryBean} and then emit {@link org.springframework.integration.Message}s when a particular event happens to the logged in users {@link org.jivesoftware.smack.Roster}. We try * and generically propagate these events. In practical terms, there are a few events worth being notified of:

  • the {@link org.jivesoftware.smack.packet.Presence} of a user in the {@link org.jivesoftware.smack.Roster} has changed.
  • the actual makeup of the logged-in user's {@link * org.jivesoftware.smack.Roster} has changed: entries added, deleted, etc.
* diff --git a/spring-integration-xmpp/src/main/resources/META-INF/smack-config.xml b/spring-integration-xmpp/src/main/resources/META-INF/smack-config.xml new file mode 100644 index 0000000000..09b7da5422 --- /dev/null +++ b/spring-integration-xmpp/src/main/resources/META-INF/smack-config.xml @@ -0,0 +1,24 @@ + + + + + + + org.jivesoftware.smackx.ServiceDiscoveryManager + org.jivesoftware.smack.PrivacyListManager + org.jivesoftware.smackx.XHTMLManager + org.jivesoftware.smackx.muc.MultiUserChat + org.jivesoftware.smackx.filetransfer.FileTransferManager + org.jivesoftware.smackx.LastActivityManager + org.jivesoftware.smack.ReconnectionManager + org.jivesoftware.smackx.commands.AdHocCommandManager + + + + 5000 + + + 30000 + + PLAIN + \ No newline at end of file diff --git a/spring-integration-xmpp/src/main/resources/org/springframework/integration/xmpp/config/spring-integration-xmpp-2.0.xsd b/spring-integration-xmpp/src/main/resources/org/springframework/integration/xmpp/config/spring-integration-xmpp-2.0.xsd index 1baa6ee0f3..9db8378544 100644 --- a/spring-integration-xmpp/src/main/resources/org/springframework/integration/xmpp/config/spring-integration-xmpp-2.0.xsd +++ b/spring-integration-xmpp/src/main/resources/org/springframework/integration/xmpp/config/spring-integration-xmpp-2.0.xsd @@ -35,15 +35,15 @@ - + - + - + + + + + + + diff --git a/spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/config/XmppConnectionParserTests.java b/spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/config/XmppConnectionParserTests.java new file mode 100644 index 0000000000..673fbaa1b8 --- /dev/null +++ b/spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/config/XmppConnectionParserTests.java @@ -0,0 +1,24 @@ +/** + * + */ +package org.springframework.integration.xmpp.config; + +import static org.mockito.Mockito.when; + +import org.junit.Ignore; +import org.junit.Test; +import org.springframework.context.ApplicationContext; +import org.springframework.context.support.ClassPathXmlApplicationContext; + +/** + * @author ozhurakousky + * + */ +public class XmppConnectionParserTests { + + @Test + @Ignore // temporary + public void testSimpleConfiguration(){ + ApplicationContext ac = new ClassPathXmlApplicationContext("XmppConnectionParserTest-simple.xml", this.getClass()); + } +} diff --git a/spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/messages/InboundXmppEndpointParserTests.java b/spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/messages/InboundXmppEndpointParserTests.java index 131ae52e1e..07b2fb2baa 100644 --- a/spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/messages/InboundXmppEndpointParserTests.java +++ b/spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/messages/InboundXmppEndpointParserTests.java @@ -7,6 +7,7 @@ import static junit.framework.Assert.assertEquals; import static junit.framework.Assert.assertFalse; import org.jivesoftware.smack.XMPPConnection; +import org.junit.Ignore; import org.junit.Test; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; @@ -20,6 +21,7 @@ import org.springframework.integration.test.util.TestUtils; public class InboundXmppEndpointParserTests { @Test + @Ignore // temporary public void testInboundAdapter(){ ApplicationContext context = new ClassPathXmlApplicationContext("InboundXmppEndpointParserTests-context.xml", this.getClass()); From cc242ae69bef06d0c76f1959e53143c4980ce299 Mon Sep 17 00:00:00 2001 From: Mark Fisher Date: Wed, 3 Nov 2010 16:43:52 -0400 Subject: [PATCH 24/82] polishing --- .../integration/rmi/RmiInboundGateway.java | 8 ++++---- .../integration/rmi/config/RmiInboundGatewayParser.java | 7 ++----- .../integration/rmi/config/RmiNamespaceHandler.java | 2 +- .../integration/rmi/config/DefaultConfigurationTests.java | 2 +- .../rmi/config/StubRemoteInvocationExecutor.java | 2 +- 5 files changed, 9 insertions(+), 12 deletions(-) diff --git a/spring-integration-rmi/src/main/java/org/springframework/integration/rmi/RmiInboundGateway.java b/spring-integration-rmi/src/main/java/org/springframework/integration/rmi/RmiInboundGateway.java index c78adb44ea..2cb5f3aa51 100644 --- a/spring-integration-rmi/src/main/java/org/springframework/integration/rmi/RmiInboundGateway.java +++ b/spring-integration-rmi/src/main/java/org/springframework/integration/rmi/RmiInboundGateway.java @@ -77,6 +77,10 @@ public class RmiInboundGateway extends RemotingInboundGatewaySupport implements public void setRemoteInvocationExecutor(RemoteInvocationExecutor remoteInvocationExecutor) { this.remoteInvocationExecutor = remoteInvocationExecutor; } + + public String getComponentType() { + return "rmi:inbound-gateway"; + } @Override protected void onInit() throws Exception { @@ -99,9 +103,5 @@ public class RmiInboundGateway extends RemotingInboundGatewaySupport implements } super.onInit(); } - - public String getComponentType(){ - return "rmi:inbound-gateway"; - } } diff --git a/spring-integration-rmi/src/main/java/org/springframework/integration/rmi/config/RmiInboundGatewayParser.java b/spring-integration-rmi/src/main/java/org/springframework/integration/rmi/config/RmiInboundGatewayParser.java index 9ebd0077db..c4d4f58704 100644 --- a/spring-integration-rmi/src/main/java/org/springframework/integration/rmi/config/RmiInboundGatewayParser.java +++ b/spring-integration-rmi/src/main/java/org/springframework/integration/rmi/config/RmiInboundGatewayParser.java @@ -20,7 +20,7 @@ import org.w3c.dom.Element; import org.springframework.beans.factory.support.BeanDefinitionBuilder; import org.springframework.integration.config.xml.AbstractInboundGatewayParser; -import org.springframework.util.StringUtils; +import org.springframework.integration.config.xml.IntegrationNamespaceUtils; /** * Parser for the <inbound-gateway/> element of the 'rmi' namespace. @@ -45,10 +45,7 @@ public class RmiInboundGatewayParser extends AbstractInboundGatewayParser { @Override protected void doPostProcess(BeanDefinitionBuilder builder, Element element) { - String executorRef = element.getAttribute(REMOTE_INVOCATION_EXECUTOR_ATTRIBUTE); - if (StringUtils.hasText(executorRef)) { - builder.addPropertyReference("remoteInvocationExecutor", executorRef); - } + IntegrationNamespaceUtils.setReferenceIfAttributeDefined(builder, element, REMOTE_INVOCATION_EXECUTOR_ATTRIBUTE); } } diff --git a/spring-integration-rmi/src/main/java/org/springframework/integration/rmi/config/RmiNamespaceHandler.java b/spring-integration-rmi/src/main/java/org/springframework/integration/rmi/config/RmiNamespaceHandler.java index dcf7a2e793..352ec5835d 100644 --- a/spring-integration-rmi/src/main/java/org/springframework/integration/rmi/config/RmiNamespaceHandler.java +++ b/spring-integration-rmi/src/main/java/org/springframework/integration/rmi/config/RmiNamespaceHandler.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2009 the original author or authors. + * Copyright 2002-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. diff --git a/spring-integration-rmi/src/test/java/org/springframework/integration/rmi/config/DefaultConfigurationTests.java b/spring-integration-rmi/src/test/java/org/springframework/integration/rmi/config/DefaultConfigurationTests.java index 1850185aef..630fac9e4e 100644 --- a/spring-integration-rmi/src/test/java/org/springframework/integration/rmi/config/DefaultConfigurationTests.java +++ b/spring-integration-rmi/src/test/java/org/springframework/integration/rmi/config/DefaultConfigurationTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2009 the original author or authors. + * Copyright 2002-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. diff --git a/spring-integration-rmi/src/test/java/org/springframework/integration/rmi/config/StubRemoteInvocationExecutor.java b/spring-integration-rmi/src/test/java/org/springframework/integration/rmi/config/StubRemoteInvocationExecutor.java index b905172ba7..bdc1908212 100644 --- a/spring-integration-rmi/src/test/java/org/springframework/integration/rmi/config/StubRemoteInvocationExecutor.java +++ b/spring-integration-rmi/src/test/java/org/springframework/integration/rmi/config/StubRemoteInvocationExecutor.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2008 the original author or authors. + * Copyright 2002-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. From 6eb8f16cb406774307716421d1e23c2e03348487 Mon Sep 17 00:00:00 2001 From: Mark Fisher Date: Wed, 3 Nov 2010 17:13:31 -0400 Subject: [PATCH 25/82] INT-1584 upgraded the Spring Security dependency to 3.0.4.RELEASE --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 327f7c663c..50171b85e7 100644 --- a/build.gradle +++ b/build.gradle @@ -111,7 +111,7 @@ configure(javaprojects) { log4jVersion = '1.2.12' mockitoVersion = '1.8.4' springVersion = '3.0.5.RELEASE' - springSecurityVersion = '3.0.3.RELEASE' + springSecurityVersion = '3.0.4.RELEASE' springWsVersion = '1.5.9' sourceSets { From a9a1a499d913ce6829df4abec2e39d29f45e4f9d Mon Sep 17 00:00:00 2001 From: Mark Fisher Date: Wed, 3 Nov 2010 17:16:25 -0400 Subject: [PATCH 26/82] updated copyright --- .../httpinvoker/config/HttpInvokerNamespaceHandler.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spring-integration-httpinvoker/src/main/java/org/springframework/integration/httpinvoker/config/HttpInvokerNamespaceHandler.java b/spring-integration-httpinvoker/src/main/java/org/springframework/integration/httpinvoker/config/HttpInvokerNamespaceHandler.java index e8e2e4ac79..e44e0fb9ba 100644 --- a/spring-integration-httpinvoker/src/main/java/org/springframework/integration/httpinvoker/config/HttpInvokerNamespaceHandler.java +++ b/spring-integration-httpinvoker/src/main/java/org/springframework/integration/httpinvoker/config/HttpInvokerNamespaceHandler.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2009 the original author or authors. + * Copyright 2002-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. From 6c2c34543b7d2f1668ed21ba7537b2669e58bee3 Mon Sep 17 00:00:00 2001 From: Mark Fisher Date: Wed, 3 Nov 2010 17:22:13 -0400 Subject: [PATCH 27/82] polishing --- .../stream/ByteStreamReadingMessageSource.java | 2 +- .../stream/ByteStreamWritingMessageHandler.java | 2 +- .../stream/CharacterStreamReadingMessageSource.java | 9 +++++---- .../stream/CharacterStreamWritingMessageHandler.java | 2 +- .../config/ConsoleOutboundChannelAdapterParser.java | 2 +- .../stream/config/StreamNamespaceHandler.java | 2 +- 6 files changed, 10 insertions(+), 9 deletions(-) diff --git a/spring-integration-stream/src/main/java/org/springframework/integration/stream/ByteStreamReadingMessageSource.java b/spring-integration-stream/src/main/java/org/springframework/integration/stream/ByteStreamReadingMessageSource.java index 2a2cc8de64..ffccdc47dd 100644 --- a/spring-integration-stream/src/main/java/org/springframework/integration/stream/ByteStreamReadingMessageSource.java +++ b/spring-integration-stream/src/main/java/org/springframework/integration/stream/ByteStreamReadingMessageSource.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2008 the original author or authors. + * Copyright 2002-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. diff --git a/spring-integration-stream/src/main/java/org/springframework/integration/stream/ByteStreamWritingMessageHandler.java b/spring-integration-stream/src/main/java/org/springframework/integration/stream/ByteStreamWritingMessageHandler.java index 6a5845bd0c..723591d35f 100644 --- a/spring-integration-stream/src/main/java/org/springframework/integration/stream/ByteStreamWritingMessageHandler.java +++ b/spring-integration-stream/src/main/java/org/springframework/integration/stream/ByteStreamWritingMessageHandler.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2008 the original author or authors. + * Copyright 2002-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. diff --git a/spring-integration-stream/src/main/java/org/springframework/integration/stream/CharacterStreamReadingMessageSource.java b/spring-integration-stream/src/main/java/org/springframework/integration/stream/CharacterStreamReadingMessageSource.java index 2ec4a71122..490339678b 100644 --- a/spring-integration-stream/src/main/java/org/springframework/integration/stream/CharacterStreamReadingMessageSource.java +++ b/spring-integration-stream/src/main/java/org/springframework/integration/stream/CharacterStreamReadingMessageSource.java @@ -60,6 +60,10 @@ public class CharacterStreamReadingMessageSource extends IntegrationObjectSuppor } + public String getComponentType() { + return "stream:stdin-channel-adapter"; + } + public Message receive() { try { synchronized (this.monitor) { @@ -88,8 +92,5 @@ public class CharacterStreamReadingMessageSource extends IntegrationObjectSuppor throw new IllegalArgumentException("unsupported encoding: " + charsetName, e); } } - - public String getComponentType(){ - return "stream:stdin-channel-adapter"; - } + } diff --git a/spring-integration-stream/src/main/java/org/springframework/integration/stream/CharacterStreamWritingMessageHandler.java b/spring-integration-stream/src/main/java/org/springframework/integration/stream/CharacterStreamWritingMessageHandler.java index 70755caee1..3385606d78 100644 --- a/spring-integration-stream/src/main/java/org/springframework/integration/stream/CharacterStreamWritingMessageHandler.java +++ b/spring-integration-stream/src/main/java/org/springframework/integration/stream/CharacterStreamWritingMessageHandler.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2008 the original author or authors. + * Copyright 2002-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. diff --git a/spring-integration-stream/src/main/java/org/springframework/integration/stream/config/ConsoleOutboundChannelAdapterParser.java b/spring-integration-stream/src/main/java/org/springframework/integration/stream/config/ConsoleOutboundChannelAdapterParser.java index c49338c4d9..ae798446c1 100644 --- a/spring-integration-stream/src/main/java/org/springframework/integration/stream/config/ConsoleOutboundChannelAdapterParser.java +++ b/spring-integration-stream/src/main/java/org/springframework/integration/stream/config/ConsoleOutboundChannelAdapterParser.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2008 the original author or authors. + * Copyright 2002-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. diff --git a/spring-integration-stream/src/main/java/org/springframework/integration/stream/config/StreamNamespaceHandler.java b/spring-integration-stream/src/main/java/org/springframework/integration/stream/config/StreamNamespaceHandler.java index 1adbcacdd3..eae0f4c526 100644 --- a/spring-integration-stream/src/main/java/org/springframework/integration/stream/config/StreamNamespaceHandler.java +++ b/spring-integration-stream/src/main/java/org/springframework/integration/stream/config/StreamNamespaceHandler.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2009 the original author or authors. + * Copyright 2002-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. From c1c38db8c42c07e7c877d6c2f9f4c6be7f7ce8c3 Mon Sep 17 00:00:00 2001 From: Oleg Zhurakousky Date: Wed, 3 Nov 2010 19:08:16 -0400 Subject: [PATCH 28/82] INT-1580, more polishing, added Lifecycle to XmppConnectionFactoryBean, added tests --- .../xmpp/XmppConnectionFactoryBean.java | 97 ++++++++++++------- .../xmpp/config/XmppConnectionParser.java | 23 ++++- .../xmpp/config/XmppNamespaceHandler.java | 11 +-- .../config/spring-integration-xmpp-2.0.xsd | 1 + ...InboundXmppEndpointParserTests-context.xml | 0 .../InboundXmppEndpointParserTests.java | 23 +++-- .../XmppConnectionParserTest-simple.xml | 4 +- .../config/XmppConnectionParserTests.java | 37 +++++-- 8 files changed, 137 insertions(+), 59 deletions(-) rename spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/{messages => config}/InboundXmppEndpointParserTests-context.xml (100%) rename spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/{messages => config}/InboundXmppEndpointParserTests.java (59%) diff --git a/spring-integration-xmpp/src/main/java/org/springframework/integration/xmpp/XmppConnectionFactoryBean.java b/spring-integration-xmpp/src/main/java/org/springframework/integration/xmpp/XmppConnectionFactoryBean.java index a61d40b946..3c6f263d93 100644 --- a/spring-integration-xmpp/src/main/java/org/springframework/integration/xmpp/XmppConnectionFactoryBean.java +++ b/spring-integration-xmpp/src/main/java/org/springframework/integration/xmpp/XmppConnectionFactoryBean.java @@ -18,7 +18,9 @@ package org.springframework.integration.xmpp; import org.jivesoftware.smack.ConnectionConfiguration; import org.jivesoftware.smack.Roster; import org.jivesoftware.smack.XMPPConnection; +import org.springframework.beans.factory.BeanInitializationException; import org.springframework.beans.factory.config.AbstractFactoryBean; +import org.springframework.context.SmartLifecycle; import org.springframework.util.Assert; import org.springframework.util.StringUtils; @@ -32,9 +34,9 @@ import org.springframework.util.StringUtils; * @see org.jivesoftware.smack.XMPPConnection * @since 2.0 */ -public class XmppConnectionFactoryBean extends AbstractFactoryBean { +public class XmppConnectionFactoryBean extends AbstractFactoryBean implements SmartLifecycle{ - private volatile ConnectionConfiguration connectionConfiguration; + private final ConnectionConfiguration connectionConfiguration; private volatile String resource = "Smack"; // default value used by Smack @@ -43,32 +45,30 @@ public class XmppConnectionFactoryBean extends AbstractFactoryBean getObjectType() { return XMPPConnection.class; @@ -88,24 +84,59 @@ public class XmppConnectionFactoryBean extends AbstractFactoryBean + diff --git a/spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/messages/InboundXmppEndpointParserTests-context.xml b/spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/config/InboundXmppEndpointParserTests-context.xml similarity index 100% rename from spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/messages/InboundXmppEndpointParserTests-context.xml rename to spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/config/InboundXmppEndpointParserTests-context.xml diff --git a/spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/messages/InboundXmppEndpointParserTests.java b/spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/config/InboundXmppEndpointParserTests.java similarity index 59% rename from spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/messages/InboundXmppEndpointParserTests.java rename to spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/config/InboundXmppEndpointParserTests.java index 07b2fb2baa..d5f8235152 100644 --- a/spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/messages/InboundXmppEndpointParserTests.java +++ b/spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/config/InboundXmppEndpointParserTests.java @@ -1,27 +1,38 @@ -/** - * +/* + * Copyright 2002-2010 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ -package org.springframework.integration.xmpp.messages; +package org.springframework.integration.xmpp.config; import static junit.framework.Assert.assertEquals; import static junit.framework.Assert.assertFalse; import org.jivesoftware.smack.XMPPConnection; -import org.junit.Ignore; import org.junit.Test; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import org.springframework.integration.channel.DirectChannel; import org.springframework.integration.test.util.TestUtils; +import org.springframework.integration.xmpp.messages.XmppMessageDrivenEndpoint; /** - * @author ozhurakousky + * @author Oleg Zhurakousky * */ public class InboundXmppEndpointParserTests { @Test - @Ignore // temporary public void testInboundAdapter(){ ApplicationContext context = new ClassPathXmlApplicationContext("InboundXmppEndpointParserTests-context.xml", this.getClass()); diff --git a/spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/config/XmppConnectionParserTest-simple.xml b/spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/config/XmppConnectionParserTest-simple.xml index 58ced8175e..0a25528a65 100644 --- a/spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/config/XmppConnectionParserTest-simple.xml +++ b/spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/config/XmppConnectionParserTest-simple.xml @@ -7,7 +7,7 @@ xmlns:int="http://www.springframework.org/schema/integration" xmlns:int-xmpp="http://www.springframework.org/schema/integration/xmpp"> - + - diff --git a/spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/config/XmppConnectionParserTests.java b/spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/config/XmppConnectionParserTests.java index 673fbaa1b8..602b7fe2dd 100644 --- a/spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/config/XmppConnectionParserTests.java +++ b/spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/config/XmppConnectionParserTests.java @@ -1,24 +1,49 @@ -/** - * +/* + * Copyright 2002-2010 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ package org.springframework.integration.xmpp.config; -import static org.mockito.Mockito.when; +import static junit.framework.Assert.assertEquals; +import static junit.framework.Assert.assertFalse; +import static junit.framework.Assert.assertNull; -import org.junit.Ignore; +import org.jivesoftware.smack.ConnectionConfiguration; +import org.jivesoftware.smack.XMPPConnection; import org.junit.Test; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; +import org.springframework.integration.test.util.TestUtils; +import org.springframework.integration.xmpp.XmppConnectionFactoryBean; /** - * @author ozhurakousky + * @author Oleg Zhurakousky * */ public class XmppConnectionParserTests { @Test - @Ignore // temporary public void testSimpleConfiguration(){ ApplicationContext ac = new ClassPathXmlApplicationContext("XmppConnectionParserTest-simple.xml", this.getClass()); + XMPPConnection connection = ac.getBean("connection", XMPPConnection.class); + assertNull(connection.getServiceName()); + assertFalse(connection.isConnected()); + XmppConnectionFactoryBean xmppFb = ac.getBean("&connection", XmppConnectionFactoryBean.class); + assertEquals("happy.user", TestUtils.getPropertyValue(xmppFb, "user")); + assertEquals("blah", TestUtils.getPropertyValue(xmppFb, "password")); + ConnectionConfiguration configuration = (ConnectionConfiguration) TestUtils.getPropertyValue(connection, "configuration"); + assertEquals("localhost", configuration.getHost()); + assertEquals(5222, configuration.getPort()); } } From ad378471622cf18c73caaf97b4b4ae4b4039c3a7 Mon Sep 17 00:00:00 2001 From: Oleg Zhurakousky Date: Wed, 3 Nov 2010 19:19:20 -0400 Subject: [PATCH 29/82] INT-1580, more polishing, more tests --- .../xmpp/config/XmppConnectionParser.java | 2 +- .../config/spring-integration-xmpp-2.0.xsd | 4 ++-- .../XmppConnectionParserTest-complete.xml | 20 +++++++++++++++++++ .../config/XmppConnectionParserTests.java | 18 +++++++++++++++++ 4 files changed, 41 insertions(+), 3 deletions(-) create mode 100644 spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/config/XmppConnectionParserTest-complete.xml diff --git a/spring-integration-xmpp/src/main/java/org/springframework/integration/xmpp/config/XmppConnectionParser.java b/spring-integration-xmpp/src/main/java/org/springframework/integration/xmpp/config/XmppConnectionParser.java index 5057317f44..634c20e44a 100644 --- a/spring-integration-xmpp/src/main/java/org/springframework/integration/xmpp/config/XmppConnectionParser.java +++ b/spring-integration-xmpp/src/main/java/org/springframework/integration/xmpp/config/XmppConnectionParser.java @@ -57,7 +57,7 @@ public class XmppConnectionParser extends AbstractSingleBeanDefinitionParser { Assert.hasText(serviceName, "'serviceName' is requuired if 'host' is not provided"); } if (StringUtils.hasText(serviceName)){ - connectionConfigurationBuilder.addConstructorArgValue(port); + connectionConfigurationBuilder.addConstructorArgValue(serviceName); } for (String attribute : connectionFactoryAttributes) { IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, attribute); diff --git a/spring-integration-xmpp/src/main/resources/org/springframework/integration/xmpp/config/spring-integration-xmpp-2.0.xsd b/spring-integration-xmpp/src/main/resources/org/springframework/integration/xmpp/config/spring-integration-xmpp-2.0.xsd index fd0decd895..675bc63d63 100644 --- a/spring-integration-xmpp/src/main/resources/org/springframework/integration/xmpp/config/spring-integration-xmpp-2.0.xsd +++ b/spring-integration-xmpp/src/main/resources/org/springframework/integration/xmpp/config/spring-integration-xmpp-2.0.xsd @@ -42,8 +42,8 @@ - - + + diff --git a/spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/config/XmppConnectionParserTest-complete.xml b/spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/config/XmppConnectionParserTest-complete.xml new file mode 100644 index 0000000000..58b091ed2c --- /dev/null +++ b/spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/config/XmppConnectionParserTest-complete.xml @@ -0,0 +1,20 @@ + + + + + + diff --git a/spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/config/XmppConnectionParserTests.java b/spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/config/XmppConnectionParserTests.java index 602b7fe2dd..77424eded9 100644 --- a/spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/config/XmppConnectionParserTests.java +++ b/spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/config/XmppConnectionParserTests.java @@ -42,8 +42,26 @@ public class XmppConnectionParserTests { XmppConnectionFactoryBean xmppFb = ac.getBean("&connection", XmppConnectionFactoryBean.class); assertEquals("happy.user", TestUtils.getPropertyValue(xmppFb, "user")); assertEquals("blah", TestUtils.getPropertyValue(xmppFb, "password")); + assertEquals("Smack", TestUtils.getPropertyValue(xmppFb, "resource")); + assertEquals("accept_all", TestUtils.getPropertyValue(xmppFb, "subscriptionMode")); ConnectionConfiguration configuration = (ConnectionConfiguration) TestUtils.getPropertyValue(connection, "configuration"); assertEquals("localhost", configuration.getHost()); assertEquals(5222, configuration.getPort()); } + @Test + public void testCompleteConfiguration(){ + ApplicationContext ac = new ClassPathXmlApplicationContext("XmppConnectionParserTest-complete.xml", this.getClass()); + XMPPConnection connection = ac.getBean("connection", XMPPConnection.class); + assertNull(connection.getServiceName()); + assertFalse(connection.isConnected()); + XmppConnectionFactoryBean xmppFb = ac.getBean("&connection", XmppConnectionFactoryBean.class); + assertEquals("happy.user", TestUtils.getPropertyValue(xmppFb, "user")); + assertEquals("blah", TestUtils.getPropertyValue(xmppFb, "password")); + assertEquals("SpringSource", TestUtils.getPropertyValue(xmppFb, "resource")); + assertEquals("reject_all", TestUtils.getPropertyValue(xmppFb, "subscriptionMode")); + ConnectionConfiguration configuration = (ConnectionConfiguration) TestUtils.getPropertyValue(connection, "configuration"); + assertEquals("localhost", configuration.getHost()); + assertEquals(6222, configuration.getPort()); + assertEquals("foogle.com", configuration.getServiceName()); + } } From c387f47dd4f0cc3d30d77c61df17b65e2956fe5b Mon Sep 17 00:00:00 2001 From: Oleg Zhurakousky Date: Wed, 3 Nov 2010 19:37:16 -0400 Subject: [PATCH 30/82] INT-1580, more polishing, moved PacketListener registration to a statr() method of an inbound endpoint --- .../integration/xmpp/XmppConnectionFactoryBean.java | 2 +- .../xmpp/messages/XmppMessageDrivenEndpoint.java | 12 ++++++------ .../messages/InboundXmppEndpointTests-context.xml | 7 ++----- .../xmpp/messages/InboundXmppEndpointTests.java | 2 +- .../src/test/java/test.properties | 12 ++++++------ 5 files changed, 16 insertions(+), 19 deletions(-) diff --git a/spring-integration-xmpp/src/main/java/org/springframework/integration/xmpp/XmppConnectionFactoryBean.java b/spring-integration-xmpp/src/main/java/org/springframework/integration/xmpp/XmppConnectionFactoryBean.java index 3c6f263d93..2bf0414782 100644 --- a/spring-integration-xmpp/src/main/java/org/springframework/integration/xmpp/XmppConnectionFactoryBean.java +++ b/spring-integration-xmpp/src/main/java/org/springframework/integration/xmpp/XmppConnectionFactoryBean.java @@ -127,7 +127,7 @@ public class XmppConnectionFactoryBean extends AbstractFactoryBean - + diff --git a/spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/messages/InboundXmppEndpointTests.java b/spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/messages/InboundXmppEndpointTests.java index 4867a56ff5..cc65cc5bac 100644 --- a/spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/messages/InboundXmppEndpointTests.java +++ b/spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/messages/InboundXmppEndpointTests.java @@ -33,7 +33,7 @@ public class InboundXmppEndpointTests { @Test @Ignore public void run() throws Exception { - Thread.sleep(10 * 1000); + Thread.sleep(10 * 1000 * 1000); } } diff --git a/spring-integration-xmpp/src/test/java/test.properties b/spring-integration-xmpp/src/test/java/test.properties index 843eefdf52..3809f9d8ca 100644 --- a/spring-integration-xmpp/src/test/java/test.properties +++ b/spring-integration-xmpp/src/test/java/test.properties @@ -22,11 +22,11 @@ user.1.sasl.mechanism=PLAIN user.1.sasl.index=0 user.1.resource=resource user.1.port=5222 -user.2.login=user2@gmail.com -user.2.password=password +user.2.login=springintegration.eip@gmail.com +user.2.password=spr1ng1p user.2.host=talk.google.com user.2.service=gmail.com -user.2.sasl.mechanism=PLAIN -user.2.sasl.index=0 -user.2.resource=resource -user.2.port=5222 +#user.2.sasl.mechanism=PLAIN +#user.2.sasl.index=0 +#user.2.resource=resource +#user.2.port=5222 From 154c2504c3fd200ee76e1477bf807ebeec0b18f4 Mon Sep 17 00:00:00 2001 From: Oleg Zhurakousky Date: Wed, 3 Nov 2010 20:08:48 -0400 Subject: [PATCH 31/82] INT-1580, more polishing, made PacketListener instance variable of an Inbound endpoint, add/remove is now part of the start/stop, added tests to validate --- .../messages/XmppMessageDrivenEndpoint.java | 26 +++--- .../XmppMessageDrivenEndpointTests.java | 79 +++++++++++++++++++ 2 files changed, 94 insertions(+), 11 deletions(-) create mode 100644 spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/messages/XmppMessageDrivenEndpointTests.java diff --git a/spring-integration-xmpp/src/main/java/org/springframework/integration/xmpp/messages/XmppMessageDrivenEndpoint.java b/spring-integration-xmpp/src/main/java/org/springframework/integration/xmpp/messages/XmppMessageDrivenEndpoint.java index 0f2ac98a55..fda5e3989d 100644 --- a/spring-integration-xmpp/src/main/java/org/springframework/integration/xmpp/messages/XmppMessageDrivenEndpoint.java +++ b/spring-integration-xmpp/src/main/java/org/springframework/integration/xmpp/messages/XmppMessageDrivenEndpoint.java @@ -29,6 +29,7 @@ import org.springframework.integration.core.MessagingTemplate; import org.springframework.integration.endpoint.AbstractEndpoint; import org.springframework.integration.support.MessageBuilder; import org.springframework.integration.xmpp.XmppHeaders; +import org.springframework.util.Assert; /** * This component logs in as a user and forwards any messages to that @@ -76,7 +77,10 @@ public class XmppMessageDrivenEndpoint extends AbstractEndpoint { private volatile XMPPConnection xmppConnection; private volatile boolean extractPayload = true; - + + private volatile PacketListener packetListener; + + private volatile boolean initialized; /** * This will be injected or configured via a xmpp-connection-factory element. @@ -107,26 +111,26 @@ public class XmppMessageDrivenEndpoint extends AbstractEndpoint { @Override protected void doStart() { + Assert.isTrue(this.initialized, this.getComponentType() + " must be initialized"); logger.debug("start: " + xmppConnection.isConnected() + ":" + xmppConnection.isAuthenticated()); - xmppConnection.addPacketListener(new PacketListener() { - public void processPacket(final Packet packet) { - org.jivesoftware.smack.packet.Message message = (org.jivesoftware.smack.packet.Message) packet; - forwardXmppMessage(xmppConnection.getChatManager().getThreadChat(message.getThread()), message); - } - }, null); + xmppConnection.addPacketListener(this.packetListener, null); } @Override protected void doStop() { - if (xmppConnection.isConnected()) { - logger.debug("shutting down " + XmppMessageDrivenEndpoint.class.getName() + "."); - xmppConnection.disconnect(); - } + xmppConnection.removePacketListener(this.packetListener); } @Override protected void onInit() throws Exception { messagingTemplate.afterPropertiesSet(); + this.packetListener = new PacketListener() { + public void processPacket(final Packet packet) { + org.jivesoftware.smack.packet.Message message = (org.jivesoftware.smack.packet.Message) packet; + forwardXmppMessage(xmppConnection.getChatManager().getThreadChat(message.getThread()), message); + } + }; + this.initialized = true; } private void forwardXmppMessage(Chat chat, Message xmppMessage) { diff --git a/spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/messages/XmppMessageDrivenEndpointTests.java b/spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/messages/XmppMessageDrivenEndpointTests.java new file mode 100644 index 0000000000..c19a496405 --- /dev/null +++ b/spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/messages/XmppMessageDrivenEndpointTests.java @@ -0,0 +1,79 @@ +/* + * Copyright 2002-2010 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.integration.xmpp.messages; + +import static junit.framework.Assert.assertEquals; +import static org.mockito.Mockito.doAnswer; +import static org.mockito.Mockito.mock; + +import java.util.HashSet; +import java.util.Set; + +import org.jivesoftware.smack.PacketListener; +import org.jivesoftware.smack.XMPPConnection; +import org.jivesoftware.smack.filter.PacketFilter; +import org.junit.Test; +import org.mockito.Mockito; +import org.mockito.invocation.InvocationOnMock; +import org.mockito.stubbing.Answer; + +/** + * @author Oleg Zhurakousky + * + */ +public class XmppMessageDrivenEndpointTests { + + + @Test + /** + * Should add/remove PacketListener when endpoint started/stopped + */ + public void testLifecycle(){ + final Set packetListSet = new HashSet(); + XmppMessageDrivenEndpoint endpoint = new XmppMessageDrivenEndpoint(); + + XMPPConnection connection = mock(XMPPConnection.class); + doAnswer(new Answer() { + @Override + public Object answer(InvocationOnMock invocation) throws Throwable { + packetListSet.add((PacketListener) invocation.getArguments()[0]); + return null; + } + }).when(connection).addPacketListener(Mockito.any(PacketListener.class), (PacketFilter) Mockito.any()); + + doAnswer(new Answer() { + @Override + public Object answer(InvocationOnMock invocation) throws Throwable { + packetListSet.remove((PacketListener) invocation.getArguments()[0]); + return null; + } + }).when(connection).removePacketListener(Mockito.any(PacketListener.class)); + + endpoint.setXmppConnection(connection); + assertEquals(0, packetListSet.size()); + endpoint.afterPropertiesSet(); + endpoint.start(); + assertEquals(1, packetListSet.size()); + endpoint.stop(); + assertEquals(0, packetListSet.size()); + } + + @Test(expected=IllegalArgumentException.class) + public void testNonInitializationFailure(){ + XmppMessageDrivenEndpoint endpoint = new XmppMessageDrivenEndpoint(); + endpoint.start(); + } +} From ee1357d8549807aad81e083d5b5e54bb5416b161 Mon Sep 17 00:00:00 2001 From: Oleg Zhurakousky Date: Wed, 3 Nov 2010 20:15:11 -0400 Subject: [PATCH 32/82] INT-1580 polishing, removed SASL attributes from the namesapce, will add paragraph to the docs how to configure it the native Smack way via config file in teh META-INF --- .../xmpp/config/spring-integration-xmpp-2.0.xsd | 17 ----------------- 1 file changed, 17 deletions(-) diff --git a/spring-integration-xmpp/src/main/resources/org/springframework/integration/xmpp/config/spring-integration-xmpp-2.0.xsd b/spring-integration-xmpp/src/main/resources/org/springframework/integration/xmpp/config/spring-integration-xmpp-2.0.xsd index 675bc63d63..0da2252357 100644 --- a/spring-integration-xmpp/src/main/resources/org/springframework/integration/xmpp/config/spring-integration-xmpp-2.0.xsd +++ b/spring-integration-xmpp/src/main/resources/org/springframework/integration/xmpp/config/spring-integration-xmpp-2.0.xsd @@ -1,19 +1,4 @@ - - - From 50d97f12cc23a53527b7c763fd8530a1e4d3f639 Mon Sep 17 00:00:00 2001 From: Oleg Zhurakousky Date: Wed, 3 Nov 2010 20:24:28 -0400 Subject: [PATCH 33/82] INT-1580 code cleanup --- .../xmpp/config/XmppConnectionParser.java | 2 +- .../xmpp/config/XmppNamespaceHandler.java | 46 ++++--------------- .../messages/ConsoleChatTests-context.xml | 13 ------ .../OutboundXmppEndpointTests-context.xml | 14 ------ .../src/test/java/test.properties | 8 ---- 5 files changed, 10 insertions(+), 73 deletions(-) diff --git a/spring-integration-xmpp/src/main/java/org/springframework/integration/xmpp/config/XmppConnectionParser.java b/spring-integration-xmpp/src/main/java/org/springframework/integration/xmpp/config/XmppConnectionParser.java index 634c20e44a..8c3f66cb52 100644 --- a/spring-integration-xmpp/src/main/java/org/springframework/integration/xmpp/config/XmppConnectionParser.java +++ b/spring-integration-xmpp/src/main/java/org/springframework/integration/xmpp/config/XmppConnectionParser.java @@ -33,7 +33,7 @@ public class XmppConnectionParser extends AbstractSingleBeanDefinitionParser { @Override protected String getBeanClassName(Element element) { - return "org.springframework.integration.xmpp" + ".XmppConnectionFactoryBean"; + return "org.springframework.integration.xmpp.XmppConnectionFactoryBean"; } @Override diff --git a/spring-integration-xmpp/src/main/java/org/springframework/integration/xmpp/config/XmppNamespaceHandler.java b/spring-integration-xmpp/src/main/java/org/springframework/integration/xmpp/config/XmppNamespaceHandler.java index af39d46b26..888e16e782 100644 --- a/spring-integration-xmpp/src/main/java/org/springframework/integration/xmpp/config/XmppNamespaceHandler.java +++ b/spring-integration-xmpp/src/main/java/org/springframework/integration/xmpp/config/XmppNamespaceHandler.java @@ -54,40 +54,6 @@ public class XmppNamespaceHandler extends NamespaceHandlerSupport { registerBeanDefinitionParser("header-enricher", new XmppHeaderEnricherParser()); } - - -// private static void configureXMPPConnection(Element element, BeanDefinitionBuilder builder, ParserContext parserContext) { -// String ref = element.getAttribute("xmpp-connection"); -// if (StringUtils.hasText(ref)) { -// builder.addPropertyReference("xmppConnection", ref); -// } else { -// for (String attribute : attributes) { -// IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, attribute); -// } -// } -// } - - - // connection management - -// private static class XmppConnectionParser extends AbstractSingleBeanDefinitionParser { -// -// @Override -// protected String getBeanClassName(Element element) { -// return PACKAGE_NAME + ".XmppConnectionFactory"; -// } -// -// @Override -// protected boolean shouldGenerateIdAsFallback() { -// return true; -// } -// -// @Override -// protected void doParse(Element element, ParserContext parserContext, BeanDefinitionBuilder builder) { -// configureXMPPConnection(element, builder, parserContext); -// } -// } - // messages private static class XmppMessageOutboundEndpointParser extends AbstractOutboundChannelAdapterParser { @@ -96,7 +62,9 @@ public class XmppNamespaceHandler extends NamespaceHandlerSupport { protected AbstractBeanDefinition parseConsumer(Element element, ParserContext parserContext) { BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition( PACKAGE_NAME + ".messages.XmppMessageSendingMessageHandler"); - //configureXMPPConnection(element, builder, parserContext); + String connectionName = element.getAttribute("xmpp-connection"); + Assert.hasText(connectionName, "'xmpp-connection' must be defined"); + builder.addPropertyReference("xmppConnection", connectionName); return builder.getBeanDefinition(); } } @@ -130,7 +98,9 @@ public class XmppNamespaceHandler extends NamespaceHandlerSupport { protected AbstractBeanDefinition parseConsumer(Element element, ParserContext parserContext) { BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition( PACKAGE_NAME + ".presence.XmppRosterEventMessageSendingHandler"); - //configureXMPPConnection(element, builder, parserContext); + String connectionName = element.getAttribute("xmpp-connection"); + Assert.hasText(connectionName, "'xmpp-connection' must be defined"); + builder.addPropertyReference("xmppConnection", connectionName); return builder.getBeanDefinition(); } } @@ -149,7 +119,9 @@ public class XmppNamespaceHandler extends NamespaceHandlerSupport { @Override protected void doParse(Element element, ParserContext parserContext, BeanDefinitionBuilder builder) { - //configureXMPPConnection(element, builder, parserContext); + String connectionName = element.getAttribute("xmpp-connection"); + Assert.hasText(connectionName, "'xmpp-connection' must be defined"); + builder.addPropertyReference("xmppConnection", connectionName); IntegrationNamespaceUtils.setReferenceIfAttributeDefined(builder, element, "channel", "requestChannel"); IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, "extract-payload"); IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, "auto-startup"); diff --git a/spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/messages/ConsoleChatTests-context.xml b/spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/messages/ConsoleChatTests-context.xml index 0539c75c35..ca93cc36ee 100644 --- a/spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/messages/ConsoleChatTests-context.xml +++ b/spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/messages/ConsoleChatTests-context.xml @@ -1,15 +1,4 @@ - diff --git a/spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/messages/OutboundXmppEndpointTests-context.xml b/spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/messages/OutboundXmppEndpointTests-context.xml index 57e7fbf9f4..225fd1a909 100644 --- a/spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/messages/OutboundXmppEndpointTests-context.xml +++ b/spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/messages/OutboundXmppEndpointTests-context.xml @@ -1,16 +1,4 @@ - - diff --git a/spring-integration-xmpp/src/test/java/test.properties b/spring-integration-xmpp/src/test/java/test.properties index 3809f9d8ca..d2447e3cb2 100644 --- a/spring-integration-xmpp/src/test/java/test.properties +++ b/spring-integration-xmpp/src/test/java/test.properties @@ -14,14 +14,6 @@ # limitations under the License. # # to be able to run these tests, put this file on your desktop and configure as appropriate -user.1.login=user1@gmail.com -user.1.password=password -user.1.host=talk.google.com -user.1.service=gmail.com -user.1.sasl.mechanism=PLAIN -user.1.sasl.index=0 -user.1.resource=resource -user.1.port=5222 user.2.login=springintegration.eip@gmail.com user.2.password=spr1ng1p user.2.host=talk.google.com From b1e1aa24609a80cec87768a8cc0bb93ebad1dbe7 Mon Sep 17 00:00:00 2001 From: Oleg Zhurakousky Date: Wed, 3 Nov 2010 23:20:05 -0400 Subject: [PATCH 34/82] INT-1580 cleaned up Roster endpoint, added tests --- .../xmpp/config/XmppNamespaceHandler.java | 2 +- .../messages/XmppMessageDrivenEndpoint.java | 1 - .../XmppRosterEventMessageDrivenEndpoint.java | 35 ++++----- .../XmppHeaderEnricherParserTests-context.xml | 18 +---- .../ConsoleChatTests-context.xml | 0 .../ConsoleChatTests.java | 2 +- .../InboundXmppEndpointTests-context.xml | 0 .../InboundXmppEndpointTests.java | 2 +- ...dXmppRosterEventsEndpointTests-context.xml | 23 +----- .../InboundXmppRosterEventsEndpointTests.java | 2 +- .../OutboundXmppEndpointTests-context.xml | 0 .../OutboundXmppEndpointTests.java | 2 +- ...dXmppRosterEventsEndpointTests-context.xml | 0 ...OutboundXmppRosterEventsEndpointTests.java | 3 +- .../PresenceMessageComboTests.java | 2 +- .../XmppMessageConsumer.java | 2 +- .../XmppMessageProducer.java | 2 +- .../XmppRosterEventConsumer.java | 2 +- .../XmppRosterEventProducer.java | 4 +- ...RosterEventMessageDrivenEndpointTests.java | 77 +++++++++++++++++++ .../src/test/java/test.properties | 16 ++-- 21 files changed, 117 insertions(+), 78 deletions(-) rename spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/{messages => ignore}/ConsoleChatTests-context.xml (100%) rename spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/{messages => ignore}/ConsoleChatTests.java (95%) rename spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/{messages => ignore}/InboundXmppEndpointTests-context.xml (100%) rename spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/{messages => ignore}/InboundXmppEndpointTests.java (95%) rename spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/{presence => ignore}/InboundXmppRosterEventsEndpointTests-context.xml (67%) rename spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/{presence => ignore}/InboundXmppRosterEventsEndpointTests.java (95%) rename spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/{messages => ignore}/OutboundXmppEndpointTests-context.xml (100%) rename spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/{messages => ignore}/OutboundXmppEndpointTests.java (95%) rename spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/{presence => ignore}/OutboundXmppRosterEventsEndpointTests-context.xml (100%) rename spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/{presence => ignore}/OutboundXmppRosterEventsEndpointTests.java (89%) rename spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/{presence => ignore}/PresenceMessageComboTests.java (96%) rename spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/{messages => ignore}/XmppMessageConsumer.java (96%) rename spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/{messages => ignore}/XmppMessageProducer.java (97%) rename spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/{presence => ignore}/XmppRosterEventConsumer.java (96%) rename spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/{presence => ignore}/XmppRosterEventProducer.java (92%) create mode 100644 spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/presence/XmppRosterEventMessageDrivenEndpointTests.java diff --git a/spring-integration-xmpp/src/main/java/org/springframework/integration/xmpp/config/XmppNamespaceHandler.java b/spring-integration-xmpp/src/main/java/org/springframework/integration/xmpp/config/XmppNamespaceHandler.java index 888e16e782..ce7f21aeac 100644 --- a/spring-integration-xmpp/src/main/java/org/springframework/integration/xmpp/config/XmppNamespaceHandler.java +++ b/spring-integration-xmpp/src/main/java/org/springframework/integration/xmpp/config/XmppNamespaceHandler.java @@ -123,7 +123,7 @@ public class XmppNamespaceHandler extends NamespaceHandlerSupport { Assert.hasText(connectionName, "'xmpp-connection' must be defined"); builder.addPropertyReference("xmppConnection", connectionName); IntegrationNamespaceUtils.setReferenceIfAttributeDefined(builder, element, "channel", "requestChannel"); - IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, "extract-payload"); + //IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, "extract-payload"); IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, "auto-startup"); } } diff --git a/spring-integration-xmpp/src/main/java/org/springframework/integration/xmpp/messages/XmppMessageDrivenEndpoint.java b/spring-integration-xmpp/src/main/java/org/springframework/integration/xmpp/messages/XmppMessageDrivenEndpoint.java index fda5e3989d..5c435eba7d 100644 --- a/spring-integration-xmpp/src/main/java/org/springframework/integration/xmpp/messages/XmppMessageDrivenEndpoint.java +++ b/spring-integration-xmpp/src/main/java/org/springframework/integration/xmpp/messages/XmppMessageDrivenEndpoint.java @@ -112,7 +112,6 @@ public class XmppMessageDrivenEndpoint extends AbstractEndpoint { @Override protected void doStart() { Assert.isTrue(this.initialized, this.getComponentType() + " must be initialized"); - logger.debug("start: " + xmppConnection.isConnected() + ":" + xmppConnection.isAuthenticated()); xmppConnection.addPacketListener(this.packetListener, null); } diff --git a/spring-integration-xmpp/src/main/java/org/springframework/integration/xmpp/presence/XmppRosterEventMessageDrivenEndpoint.java b/spring-integration-xmpp/src/main/java/org/springframework/integration/xmpp/presence/XmppRosterEventMessageDrivenEndpoint.java index 77a3bfbd86..2bcd884f94 100644 --- a/spring-integration-xmpp/src/main/java/org/springframework/integration/xmpp/presence/XmppRosterEventMessageDrivenEndpoint.java +++ b/spring-integration-xmpp/src/main/java/org/springframework/integration/xmpp/presence/XmppRosterEventMessageDrivenEndpoint.java @@ -13,9 +13,10 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package org.springframework.integration.xmpp.presence; +import java.util.Collection; + import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.builder.ToStringBuilder; import org.apache.commons.logging.Log; @@ -23,14 +24,12 @@ import org.apache.commons.logging.LogFactory; import org.jivesoftware.smack.RosterListener; import org.jivesoftware.smack.XMPPConnection; import org.jivesoftware.smack.packet.Presence; -import org.springframework.context.Lifecycle; import org.springframework.integration.Message; import org.springframework.integration.MessageChannel; import org.springframework.integration.core.MessagingTemplate; import org.springframework.integration.endpoint.AbstractEndpoint; import org.springframework.integration.mapping.InboundMessageMapper; - -import java.util.Collection; +import org.springframework.util.Assert; /** @@ -41,11 +40,10 @@ import java.util.Collection; * @author Josh Long * @since 2.0 */ -public class XmppRosterEventMessageDrivenEndpoint extends AbstractEndpoint implements Lifecycle { +public class XmppRosterEventMessageDrivenEndpoint extends AbstractEndpoint { private static final Log logger = LogFactory.getLog(XmppRosterEventMessageDrivenEndpoint.class); - private volatile MessageChannel requestChannel; private volatile XMPPConnection xmppConnection; @@ -53,14 +51,17 @@ public class XmppRosterEventMessageDrivenEndpoint extends AbstractEndpoint imple private InboundMessageMapper messageMapper; private final MessagingTemplate messagingTemplate = new MessagingTemplate(); + + private final EventForwardingRosterListener rosterListener = new EventForwardingRosterListener(); + private volatile boolean initialized; /** * This will be injected or configured via a xmpp-connection-factory element. * * @param xmppConnection the connection */ - public void setXmppConnection(final XMPPConnection xmppConnection) { + public void setXmppConnection(XMPPConnection xmppConnection) { this.xmppConnection = xmppConnection; } @@ -71,20 +72,20 @@ public class XmppRosterEventMessageDrivenEndpoint extends AbstractEndpoint imple this.messagingTemplate.setDefaultChannel(requestChannel); this.requestChannel = requestChannel; } + + public void setMessageMapper(InboundMessageMapper messageMapper) { + this.messageMapper = messageMapper; + } @Override protected void doStart() { - logger.debug("start: " + xmppConnection.isConnected() + ":" + - xmppConnection.isAuthenticated()); + Assert.isTrue(this.initialized, this.getComponentType() + " must be initialized"); + this.xmppConnection.getRoster().addRosterListener(rosterListener); } @Override protected void doStop() { - if (this.xmppConnection.isConnected()) { - logger.debug("shutting down " + XmppRosterEventMessageDrivenEndpoint.class.getName() + - "."); - this.xmppConnection.disconnect(); - } + this.xmppConnection.getRoster().removeRosterListener(rosterListener); } @Override @@ -94,7 +95,7 @@ public class XmppRosterEventMessageDrivenEndpoint extends AbstractEndpoint imple } this.messagingTemplate.afterPropertiesSet(); - this.xmppConnection.getRoster().addRosterListener(new EventForwardingRosterListener()); + this.initialized = true; } /** @@ -112,10 +113,6 @@ public class XmppRosterEventMessageDrivenEndpoint extends AbstractEndpoint imple } } - public void setMessageMapper(InboundMessageMapper messageMapper) { - this.messageMapper = messageMapper; - } - /** * Subscribes to a given {@link org.jivesoftware.smack.Roster}s events and forwards them to components on the bus. */ diff --git a/spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/config/XmppHeaderEnricherParserTests-context.xml b/spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/config/XmppHeaderEnricherParserTests-context.xml index 2ea13eccec..0ffe11c8c6 100644 --- a/spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/config/XmppHeaderEnricherParserTests-context.xml +++ b/spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/config/XmppHeaderEnricherParserTests-context.xml @@ -1,19 +1,4 @@ - - - + diff --git a/spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/messages/ConsoleChatTests-context.xml b/spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/ignore/ConsoleChatTests-context.xml similarity index 100% rename from spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/messages/ConsoleChatTests-context.xml rename to spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/ignore/ConsoleChatTests-context.xml diff --git a/spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/messages/ConsoleChatTests.java b/spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/ignore/ConsoleChatTests.java similarity index 95% rename from spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/messages/ConsoleChatTests.java rename to spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/ignore/ConsoleChatTests.java index 643e82aaf3..cdf972aee0 100644 --- a/spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/messages/ConsoleChatTests.java +++ b/spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/ignore/ConsoleChatTests.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.springframework.integration.xmpp.messages; +package org.springframework.integration.xmpp.ignore; import org.junit.Ignore; import org.junit.Test; diff --git a/spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/messages/InboundXmppEndpointTests-context.xml b/spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/ignore/InboundXmppEndpointTests-context.xml similarity index 100% rename from spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/messages/InboundXmppEndpointTests-context.xml rename to spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/ignore/InboundXmppEndpointTests-context.xml diff --git a/spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/messages/InboundXmppEndpointTests.java b/spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/ignore/InboundXmppEndpointTests.java similarity index 95% rename from spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/messages/InboundXmppEndpointTests.java rename to spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/ignore/InboundXmppEndpointTests.java index cc65cc5bac..cdaa561a1e 100644 --- a/spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/messages/InboundXmppEndpointTests.java +++ b/spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/ignore/InboundXmppEndpointTests.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.springframework.integration.xmpp.messages; +package org.springframework.integration.xmpp.ignore; import org.junit.Ignore; import org.junit.Test; diff --git a/spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/presence/InboundXmppRosterEventsEndpointTests-context.xml b/spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/ignore/InboundXmppRosterEventsEndpointTests-context.xml similarity index 67% rename from spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/presence/InboundXmppRosterEventsEndpointTests-context.xml rename to spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/ignore/InboundXmppRosterEventsEndpointTests-context.xml index 7ddd60c8e6..3a02802460 100644 --- a/spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/presence/InboundXmppRosterEventsEndpointTests-context.xml +++ b/spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/ignore/InboundXmppRosterEventsEndpointTests-context.xml @@ -1,15 +1,4 @@ - - - - - - - + + @@ -41,10 +26,6 @@ user="${user.1.login}" password="${user.1.password}" host="${user.1.host}" - port="${user.1.port}" - resource="${user.1.resource}" - sasl-mechanism-supported="${user.1.sasl.mechanism}" - sasl-mechanism-supported-index="${user.1.sasl.index}" service-name="${user.1.service}" /> diff --git a/spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/presence/InboundXmppRosterEventsEndpointTests.java b/spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/ignore/InboundXmppRosterEventsEndpointTests.java similarity index 95% rename from spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/presence/InboundXmppRosterEventsEndpointTests.java rename to spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/ignore/InboundXmppRosterEventsEndpointTests.java index 02f4e5db4f..497b2c46f9 100644 --- a/spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/presence/InboundXmppRosterEventsEndpointTests.java +++ b/spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/ignore/InboundXmppRosterEventsEndpointTests.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.springframework.integration.xmpp.presence; +package org.springframework.integration.xmpp.ignore; import org.junit.Ignore; import org.junit.Test; diff --git a/spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/messages/OutboundXmppEndpointTests-context.xml b/spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/ignore/OutboundXmppEndpointTests-context.xml similarity index 100% rename from spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/messages/OutboundXmppEndpointTests-context.xml rename to spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/ignore/OutboundXmppEndpointTests-context.xml diff --git a/spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/messages/OutboundXmppEndpointTests.java b/spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/ignore/OutboundXmppEndpointTests.java similarity index 95% rename from spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/messages/OutboundXmppEndpointTests.java rename to spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/ignore/OutboundXmppEndpointTests.java index 1b9e094517..e631f0a8a6 100644 --- a/spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/messages/OutboundXmppEndpointTests.java +++ b/spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/ignore/OutboundXmppEndpointTests.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.springframework.integration.xmpp.messages; +package org.springframework.integration.xmpp.ignore; import org.junit.Ignore; import org.junit.Test; diff --git a/spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/presence/OutboundXmppRosterEventsEndpointTests-context.xml b/spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/ignore/OutboundXmppRosterEventsEndpointTests-context.xml similarity index 100% rename from spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/presence/OutboundXmppRosterEventsEndpointTests-context.xml rename to spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/ignore/OutboundXmppRosterEventsEndpointTests-context.xml diff --git a/spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/presence/OutboundXmppRosterEventsEndpointTests.java b/spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/ignore/OutboundXmppRosterEventsEndpointTests.java similarity index 89% rename from spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/presence/OutboundXmppRosterEventsEndpointTests.java rename to spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/ignore/OutboundXmppRosterEventsEndpointTests.java index 61c5fe3a10..349670e21e 100644 --- a/spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/presence/OutboundXmppRosterEventsEndpointTests.java +++ b/spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/ignore/OutboundXmppRosterEventsEndpointTests.java @@ -14,11 +14,12 @@ * limitations under the License. */ -package org.springframework.integration.xmpp.presence; +package org.springframework.integration.xmpp.ignore; import org.junit.Ignore; import org.junit.Test; import org.junit.runner.RunWith; +import org.springframework.integration.xmpp.presence.XmppRosterEventMessageSendingHandler; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; diff --git a/spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/presence/PresenceMessageComboTests.java b/spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/ignore/PresenceMessageComboTests.java similarity index 96% rename from spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/presence/PresenceMessageComboTests.java rename to spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/ignore/PresenceMessageComboTests.java index 9547a8ca33..221d4e2c42 100644 --- a/spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/presence/PresenceMessageComboTests.java +++ b/spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/ignore/PresenceMessageComboTests.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.springframework.integration.xmpp.presence; +package org.springframework.integration.xmpp.ignore; import org.junit.Ignore; import org.junit.Test; diff --git a/spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/messages/XmppMessageConsumer.java b/spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/ignore/XmppMessageConsumer.java similarity index 96% rename from spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/messages/XmppMessageConsumer.java rename to spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/ignore/XmppMessageConsumer.java index 2f44267563..3aab8fe3a1 100644 --- a/spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/messages/XmppMessageConsumer.java +++ b/spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/ignore/XmppMessageConsumer.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.springframework.integration.xmpp.messages; +package org.springframework.integration.xmpp.ignore; import org.jivesoftware.smack.packet.Message; import org.springframework.integration.annotation.ServiceActivator; diff --git a/spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/messages/XmppMessageProducer.java b/spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/ignore/XmppMessageProducer.java similarity index 97% rename from spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/messages/XmppMessageProducer.java rename to spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/ignore/XmppMessageProducer.java index bf4b440c24..bde5dd4923 100644 --- a/spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/messages/XmppMessageProducer.java +++ b/spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/ignore/XmppMessageProducer.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.springframework.integration.xmpp.messages; +package org.springframework.integration.xmpp.ignore; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; diff --git a/spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/presence/XmppRosterEventConsumer.java b/spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/ignore/XmppRosterEventConsumer.java similarity index 96% rename from spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/presence/XmppRosterEventConsumer.java rename to spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/ignore/XmppRosterEventConsumer.java index f75da61f3f..7049af120d 100644 --- a/spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/presence/XmppRosterEventConsumer.java +++ b/spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/ignore/XmppRosterEventConsumer.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.springframework.integration.xmpp.presence; +package org.springframework.integration.xmpp.ignore; import org.apache.commons.lang.StringUtils; import org.springframework.integration.Message; diff --git a/spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/presence/XmppRosterEventProducer.java b/spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/ignore/XmppRosterEventProducer.java similarity index 92% rename from spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/presence/XmppRosterEventProducer.java rename to spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/ignore/XmppRosterEventProducer.java index fbe97a2743..60cc7dfc61 100644 --- a/spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/presence/XmppRosterEventProducer.java +++ b/spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/ignore/XmppRosterEventProducer.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.springframework.integration.xmpp.presence; +package org.springframework.integration.xmpp.ignore; import org.apache.commons.lang.StringUtils; import org.jivesoftware.smack.packet.Presence; @@ -25,7 +25,7 @@ import org.springframework.integration.xmpp.XmppHeaders; /** * This is used in - * {@link org.springframework.integration.xmpp.presence.OutboundXmppRosterEventsEndpointTests} + * {@link org.springframework.integration.xmpp.ignore.OutboundXmppRosterEventsEndpointTests} * to produce fake status / presence updates. * * @author Josh Long diff --git a/spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/presence/XmppRosterEventMessageDrivenEndpointTests.java b/spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/presence/XmppRosterEventMessageDrivenEndpointTests.java new file mode 100644 index 0000000000..57042e7c61 --- /dev/null +++ b/spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/presence/XmppRosterEventMessageDrivenEndpointTests.java @@ -0,0 +1,77 @@ +/* + * Copyright 2002-2010 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.integration.xmpp.presence; + +import static junit.framework.Assert.assertEquals; +import static org.mockito.Mockito.doAnswer; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import java.util.HashSet; +import java.util.Set; + +import org.jivesoftware.smack.Roster; +import org.jivesoftware.smack.RosterListener; +import org.jivesoftware.smack.XMPPConnection; +import org.junit.Test; +import org.mockito.Mockito; +import org.mockito.invocation.InvocationOnMock; +import org.mockito.stubbing.Answer; + +/** + * @author Oleg Zhurakousky + * + */ +public class XmppRosterEventMessageDrivenEndpointTests { + + @Test + public void testEndpointLifecycle(){ + final Set rosterSet = new HashSet(); + XMPPConnection connection = mock(XMPPConnection.class); + Roster roster = mock(Roster.class); + when(connection.getRoster()).thenReturn(roster); + + doAnswer(new Answer() { + @Override + public Object answer(InvocationOnMock invocation) throws Throwable { + rosterSet.add((RosterListener) invocation.getArguments()[0]); + return null; + } + }).when(roster).addRosterListener(Mockito.any(RosterListener.class)); + + doAnswer(new Answer() { + @Override + public Object answer(InvocationOnMock invocation) throws Throwable { + rosterSet.remove((RosterListener) invocation.getArguments()[0]); + return null; + } + }).when(roster).removeRosterListener(Mockito.any(RosterListener.class)); + XmppRosterEventMessageDrivenEndpoint rosterEndpoint = new XmppRosterEventMessageDrivenEndpoint(); + rosterEndpoint.setXmppConnection(connection); + rosterEndpoint.afterPropertiesSet(); + assertEquals(0, rosterSet.size()); + rosterEndpoint.start(); + assertEquals(1, rosterSet.size()); + rosterEndpoint.stop(); + assertEquals(0, rosterSet.size()); + } + + @Test(expected=IllegalArgumentException.class) + public void testNonInitializedFailure(){ + XmppRosterEventMessageDrivenEndpoint rosterEndpoint = new XmppRosterEventMessageDrivenEndpoint(); + rosterEndpoint.start(); + } +} diff --git a/spring-integration-xmpp/src/test/java/test.properties b/spring-integration-xmpp/src/test/java/test.properties index d2447e3cb2..02213f3b6d 100644 --- a/spring-integration-xmpp/src/test/java/test.properties +++ b/spring-integration-xmpp/src/test/java/test.properties @@ -14,11 +14,11 @@ # limitations under the License. # # to be able to run these tests, put this file on your desktop and configure as appropriate -user.2.login=springintegration.eip@gmail.com -user.2.password=spr1ng1p -user.2.host=talk.google.com -user.2.service=gmail.com -#user.2.sasl.mechanism=PLAIN -#user.2.sasl.index=0 -#user.2.resource=resource -#user.2.port=5222 +user.1.login=user@gmail.com +user.1.password=password +user.1.host=talk.google.com +user.1.service=gmail.com +#user.1.sasl.mechanism=PLAIN +#user.1.sasl.index=0 +#user.1.resource=resource +#user.1.port=5222 From 821437b54807b4b992634c2d5c7931e22cd1b98f Mon Sep 17 00:00:00 2001 From: Oleg Zhurakousky Date: Wed, 3 Nov 2010 23:55:02 -0400 Subject: [PATCH 35/82] INT-1580 added more test for Smack SASL config --- .../xmpp/config/XmppConnectionParserTests.java | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/config/XmppConnectionParserTests.java b/spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/config/XmppConnectionParserTests.java index 77424eded9..3911c4f48b 100644 --- a/spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/config/XmppConnectionParserTests.java +++ b/spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/config/XmppConnectionParserTests.java @@ -19,7 +19,10 @@ import static junit.framework.Assert.assertEquals; import static junit.framework.Assert.assertFalse; import static junit.framework.Assert.assertNull; +import java.util.List; + import org.jivesoftware.smack.ConnectionConfiguration; +import org.jivesoftware.smack.SmackConfiguration; import org.jivesoftware.smack.XMPPConnection; import org.junit.Test; import org.springframework.context.ApplicationContext; @@ -32,6 +35,18 @@ import org.springframework.integration.xmpp.XmppConnectionFactoryBean; * */ public class XmppConnectionParserTests { + + @Test + public void testSmackSasl(){ + /* + * Possible SASL mechanisms + * EXTERNAL, GSSAPI, DIGEST-MD5, CRAM-MD5, PLAIN, ANONYMOUS + */ + // values are set in META-INF/smack-config.xml + List saslMechNames = SmackConfiguration.getSaslMechs(); + assertEquals(2, saslMechNames.size()); + assertEquals("PLAIN", saslMechNames.get(0)); + } @Test public void testSimpleConfiguration(){ From b1e3f764175ef5d3adbf1a771d2abe68a2ecbf41 Mon Sep 17 00:00:00 2001 From: Oleg Zhurakousky Date: Thu, 4 Nov 2010 10:15:40 -0400 Subject: [PATCH 36/82] INT-1554 added tests and refactored/cleaned XmppPresenceMessageMapper --- .../presence/XmppPresenceMessageMapper.java | 69 ++++++------ .../XmppPresenceMessageMapperTests.java | 106 ++++++++++++++++++ 2 files changed, 142 insertions(+), 33 deletions(-) create mode 100644 spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/presence/XmppPresenceMessageMapperTests.java diff --git a/spring-integration-xmpp/src/main/java/org/springframework/integration/xmpp/presence/XmppPresenceMessageMapper.java b/spring-integration-xmpp/src/main/java/org/springframework/integration/xmpp/presence/XmppPresenceMessageMapper.java index 0ca9beb4cd..33a3bf9f45 100644 --- a/spring-integration-xmpp/src/main/java/org/springframework/integration/xmpp/presence/XmppPresenceMessageMapper.java +++ b/spring-integration-xmpp/src/main/java/org/springframework/integration/xmpp/presence/XmppPresenceMessageMapper.java @@ -15,12 +15,11 @@ */ package org.springframework.integration.xmpp.presence; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; import org.jivesoftware.smack.packet.Presence; import org.springframework.integration.Message; import org.springframework.integration.MessageHeaders; import org.springframework.integration.mapping.InboundMessageMapper; +import org.springframework.integration.mapping.MessageMappingException; import org.springframework.integration.mapping.OutboundMessageMapper; import org.springframework.integration.support.MessageBuilder; import org.springframework.integration.xmpp.XmppHeaders; @@ -28,21 +27,21 @@ import org.springframework.util.StringUtils; /** - * Implementation of the strategy interface {@link org.springframework.integration.mapping.OutboundMessageMapper}. This is the hook that lets the adapter receive various payloads from - * components inside Spring Integration and forward them correctly as {@link org.jivesoftware.smack.packet.Presence} instances. + * Implementation of the strategy interface {@link OutboundMessageMapper} + * which maps {@link Presence} to {@link Message} * * @author Josh Long + * @author Oleg Zhurakousky * @since 2.0 */ public class XmppPresenceMessageMapper implements OutboundMessageMapper, InboundMessageMapper { - private static final Log logger = LogFactory.getLog(XmppPresenceMessageMapper.class); - /** - * Returns a {@link org.springframework.integration.Message} with payload {@link org.jivesoftware.smack.packet.Presence} + * Builds {@link Message} with payload of {@link Presence} while also + * setting Presense attributes as {@link MessageHeaders} * - * @param presence the presence object that can be used to present the priority, status, mode, and type of a given roster entry. This will be decomposed into a series of headers, as well as a payload + * @param presence the presence object * @return the Message * @throws Exception thrown if conversion should fail */ @@ -72,46 +71,50 @@ public class XmppPresenceMessageMapper implements OutboundMessageMapper message = MessageBuilder.withPayload(presence).build(); + XmppPresenceMessageMapper mapper = new XmppPresenceMessageMapper(); + Presence mappedPresence = mapper.fromMessage(message); + assertEquals(Mode.chat, mappedPresence.getMode()); + assertEquals(Type.available, mappedPresence.getType()); + assertEquals("Hello", mappedPresence.getStatus()); + assertEquals(1, mappedPresence.getPriority()); + } + + @Test + public void testFromMessageWithPayloadPresenceType() throws Exception{ + Message message = MessageBuilder.withPayload(Type.available) + .setHeader(XmppHeaders.PRESENCE_FROM, "oleg") + .setHeader(XmppHeaders.PRESENCE_MODE, Mode.chat) + .setHeader(XmppHeaders.PRESENCE_STATUS, "hello") + .setHeader(XmppHeaders.PRESENCE_TYPE, Type.subscribed) + .setHeader(XmppHeaders.PRESENCE_PRIORITY, 1) + .build(); + XmppPresenceMessageMapper mapper = new XmppPresenceMessageMapper(); + Presence mappedPresence = mapper.fromMessage(message); + assertEquals(Mode.chat, mappedPresence.getMode()); + assertEquals(Type.available, mappedPresence.getType()); + assertEquals("hello", mappedPresence.getStatus()); + assertEquals(1, mappedPresence.getPriority()); + } + @Test + public void testFromMessageWithPayloadPresenceTypeAndStringModeType() throws Exception{ + Message message = MessageBuilder.withPayload(Type.available) + .setHeader(XmppHeaders.PRESENCE_FROM, "oleg") + .setHeader(XmppHeaders.PRESENCE_MODE, "chat") + .setHeader(XmppHeaders.PRESENCE_STATUS, "hello") + .setHeader(XmppHeaders.PRESENCE_TYPE, "subscribed") + .setHeader(XmppHeaders.PRESENCE_PRIORITY, 1) + .build(); + XmppPresenceMessageMapper mapper = new XmppPresenceMessageMapper(); + Presence mappedPresence = mapper.fromMessage(message); + assertEquals(Mode.chat, mappedPresence.getMode()); + assertEquals(Type.available, mappedPresence.getType()); + assertEquals("hello", mappedPresence.getStatus()); + assertEquals(1, mappedPresence.getPriority()); + } + + @Test(expected=MessageMappingException.class) + public void testFromMessageWithPayloadPresenceTypeUnsupportedMode() throws Exception{ + + Message message = MessageBuilder.withPayload(Type.available) + .setHeader(XmppHeaders.PRESENCE_MODE, 1) + .build(); + XmppPresenceMessageMapper mapper = new XmppPresenceMessageMapper(); + mapper.fromMessage(message); + } + + @Test(expected=MessageMappingException.class) + public void testFromMessageWithPayloadPresenceTypeUnsupportedType() throws Exception{ + + Message message = MessageBuilder.withPayload(Type.available) + .setHeader(XmppHeaders.PRESENCE_TYPE, 1) + .build(); + XmppPresenceMessageMapper mapper = new XmppPresenceMessageMapper(); + mapper.fromMessage(message); + } + + @Test(expected=MessageMappingException.class) + public void testFromMessageWithUnsupportedPayload() throws Exception{ + Message message = MessageBuilder.withPayload("hello").build(); + XmppPresenceMessageMapper mapper = new XmppPresenceMessageMapper(); + mapper.fromMessage(message); + } +} From 9e8f14b05b1ba751f5a170c7d66261b08c772b1c Mon Sep 17 00:00:00 2001 From: Oleg Zhurakousky Date: Thu, 4 Nov 2010 10:38:46 -0400 Subject: [PATCH 37/82] INT-1554 added more tests and refactored/cleaned XmppPresenceMapper. Removed Presence Type header as unneccessery, since the only two payloads that are supported is Presence itself or Presentce.Type --- .../integration/xmpp/XmppHeaders.java | 6 -- .../xmpp/config/XmppNamespaceHandler.java | 1 - .../presence/XmppPresenceMessageMapper.java | 76 +++++++------------ .../XmppRosterEventMessageDrivenEndpoint.java | 2 +- .../xmpp/ignore/XmppRosterEventProducer.java | 10 +-- .../XmppPresenceMessageMapperTests.java | 20 ++--- 6 files changed, 43 insertions(+), 72 deletions(-) diff --git a/spring-integration-xmpp/src/main/java/org/springframework/integration/xmpp/XmppHeaders.java b/spring-integration-xmpp/src/main/java/org/springframework/integration/xmpp/XmppHeaders.java index 993420a227..3d9426bbba 100644 --- a/spring-integration-xmpp/src/main/java/org/springframework/integration/xmpp/XmppHeaders.java +++ b/spring-integration-xmpp/src/main/java/org/springframework/integration/xmpp/XmppHeaders.java @@ -38,10 +38,6 @@ public class XmppHeaders { public static final String TYPE = PREFIX + "type"; -// public static final String ROSTER_CHANGE_TYPE = PREFIX + "roster_change_type"; - -// public static final String ROSTER = PREFIX + "roster"; - public static final String PRESENCE = PREFIX + "presence"; public static final String PRESENCE_LANGUAGE = PRESENCE + "language"; @@ -50,8 +46,6 @@ public class XmppHeaders { public static final String PRESENCE_MODE = PRESENCE + "mode"; - public static final String PRESENCE_TYPE = PRESENCE + "type"; - public static final String PRESENCE_STATUS = PRESENCE + "status"; public static final String PRESENCE_FROM = PRESENCE + "from"; diff --git a/spring-integration-xmpp/src/main/java/org/springframework/integration/xmpp/config/XmppNamespaceHandler.java b/spring-integration-xmpp/src/main/java/org/springframework/integration/xmpp/config/XmppNamespaceHandler.java index ce7f21aeac..9f862253bd 100644 --- a/spring-integration-xmpp/src/main/java/org/springframework/integration/xmpp/config/XmppNamespaceHandler.java +++ b/spring-integration-xmpp/src/main/java/org/springframework/integration/xmpp/config/XmppNamespaceHandler.java @@ -138,7 +138,6 @@ public class XmppNamespaceHandler extends NamespaceHandlerSupport { // presence headers this.addElementToHeaderMapping("presence-mode", XmppHeaders.PRESENCE_MODE, Presence.Mode.class); - this.addElementToHeaderMapping("presence-type", XmppHeaders.PRESENCE_TYPE, Presence.Type.class); this.addElementToHeaderMapping("presence-from", XmppHeaders.PRESENCE_FROM); this.addElementToHeaderMapping("presence-status", XmppHeaders.PRESENCE_STATUS); this.addElementToHeaderMapping("presence-priority", XmppHeaders.PRESENCE_PRIORITY, Integer.class); diff --git a/spring-integration-xmpp/src/main/java/org/springframework/integration/xmpp/presence/XmppPresenceMessageMapper.java b/spring-integration-xmpp/src/main/java/org/springframework/integration/xmpp/presence/XmppPresenceMessageMapper.java index 33a3bf9f45..6612887ec0 100644 --- a/spring-integration-xmpp/src/main/java/org/springframework/integration/xmpp/presence/XmppPresenceMessageMapper.java +++ b/spring-integration-xmpp/src/main/java/org/springframework/integration/xmpp/presence/XmppPresenceMessageMapper.java @@ -39,78 +39,60 @@ public class XmppPresenceMessageMapper implements OutboundMessageMapper toMessage(Presence presence) throws Exception { + @SuppressWarnings("unchecked") + public Message toMessage(Presence presence) throws Exception { MessageBuilder presenceMessageBuilder = MessageBuilder.withPayload(presence); presenceMessageBuilder.setHeader(XmppHeaders.PRESENCE_PRIORITY, presence.getPriority()); presenceMessageBuilder.setHeader(XmppHeaders.PRESENCE_STATUS, presence.getStatus()); presenceMessageBuilder.setHeader(XmppHeaders.PRESENCE_MODE, presence.getMode()); - presenceMessageBuilder.setHeader(XmppHeaders.PRESENCE_TYPE, presence.getType()); presenceMessageBuilder.setHeader(XmppHeaders.PRESENCE_FROM, presence.getFrom()); - return presenceMessageBuilder.build(); + return (Message) presenceMessageBuilder.build(); } /** - * Builds a {@link org.jivesoftware.smack.packet.Presence} object from the inbound Message headers, if possible. + * Builds a {@link Presence} object from the inbound Message headers, if possible. * * @param message the Message whose headers and payload willl b * @return the presence object as constructed from the {@link org.springframework.integration.Message} object * @throws Exception if there is a problem */ public Presence fromMessage(Message message) throws Exception { - MessageHeaders messageHeaders = message.getHeaders(); - - Integer priority = (Integer) messageHeaders.get(XmppHeaders.PRESENCE_PRIORITY); - String status = (String) messageHeaders.get(XmppHeaders.PRESENCE_STATUS); - String language = (String) messageHeaders.get(XmppHeaders.PRESENCE_LANGUAGE); - String from = (String) messageHeaders.get(XmppHeaders.PRESENCE_FROM); - - Object modeObj = messageHeaders.get(XmppHeaders.PRESENCE_MODE); - Presence.Mode mode = null; - - Object typeObj = messageHeaders.get(XmppHeaders.PRESENCE_TYPE); - Presence.Type type = null; - - if (typeObj != null){ - if (typeObj instanceof String) { - type = Presence.Type.valueOf((String) typeObj); - } - else if (typeObj instanceof Presence.Type) { - type = (Presence.Type) typeObj; - } - else { - throw new MessageMappingException("Unsupported type for Presence type. Only" + - " String or Presence.Type is allowed, but was: " + typeObj.getClass().getName()); - } - } - - - if (modeObj != null){ - if (modeObj instanceof String) { - mode = Presence.Mode.valueOf((String) modeObj); - } - else if (modeObj instanceof Presence.Mode) { - mode = (Presence.Mode) modeObj; - } - else { - throw new MessageMappingException("Unsupported type for Presence mode. Only" + - " String or Presence.Mode is allowed, but was: " + modeObj.getClass().getName()); - } - } - Object payload = message.getPayload(); if (payload instanceof Presence) { return (Presence) payload; } else if (payload instanceof Presence.Type) { - type = (Presence.Type) payload; - return this.factoryPresence(from, status, priority, type, mode, language); + Presence.Type presenceType = (Presence.Type) payload; + MessageHeaders messageHeaders = message.getHeaders(); + + Integer priority = (Integer) messageHeaders.get(XmppHeaders.PRESENCE_PRIORITY); + String status = (String) messageHeaders.get(XmppHeaders.PRESENCE_STATUS); + String language = (String) messageHeaders.get(XmppHeaders.PRESENCE_LANGUAGE); + String from = (String) messageHeaders.get(XmppHeaders.PRESENCE_FROM); + + Object modeObj = messageHeaders.get(XmppHeaders.PRESENCE_MODE); + Presence.Mode mode = null; + + if (modeObj != null){ + if (modeObj instanceof String) { + mode = Presence.Mode.valueOf((String) modeObj); + } + else if (modeObj instanceof Presence.Mode) { + mode = (Presence.Mode) modeObj; + } + else { + throw new MessageMappingException("Unsupported type for Presence mode. Only" + + " String or Presence.Mode is allowed, but was: " + modeObj.getClass().getName()); + } + } + return this.factoryPresence(from, status, priority, presenceType, mode, language); } else { throw new MessageMappingException("Unsupported Payload type: " + payload.getClass().getName()); diff --git a/spring-integration-xmpp/src/main/java/org/springframework/integration/xmpp/presence/XmppRosterEventMessageDrivenEndpoint.java b/spring-integration-xmpp/src/main/java/org/springframework/integration/xmpp/presence/XmppRosterEventMessageDrivenEndpoint.java index 2bcd884f94..1a953af327 100644 --- a/spring-integration-xmpp/src/main/java/org/springframework/integration/xmpp/presence/XmppRosterEventMessageDrivenEndpoint.java +++ b/spring-integration-xmpp/src/main/java/org/springframework/integration/xmpp/presence/XmppRosterEventMessageDrivenEndpoint.java @@ -103,7 +103,7 @@ public class XmppRosterEventMessageDrivenEndpoint extends AbstractEndpoint { * * @param presence the {@link org.jivesoftware.smack.packet.Presence} object representing the new state (optional) */ - protected void forwardRosterEventMessage(Presence presence) { + private void forwardRosterEventMessage(Presence presence) { try { Message msg = this.messageMapper.toMessage(presence); messagingTemplate.send(requestChannel, msg); diff --git a/spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/ignore/XmppRosterEventProducer.java b/spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/ignore/XmppRosterEventProducer.java index 60cc7dfc61..015b582ead 100644 --- a/spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/ignore/XmppRosterEventProducer.java +++ b/spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/ignore/XmppRosterEventProducer.java @@ -18,6 +18,7 @@ package org.springframework.integration.xmpp.ignore; import org.apache.commons.lang.StringUtils; import org.jivesoftware.smack.packet.Presence; +import org.jivesoftware.smack.packet.Presence.Type; import org.springframework.integration.Message; import org.springframework.integration.core.MessageSource; import org.springframework.integration.support.MessageBuilder; @@ -40,12 +41,11 @@ public class XmppRosterEventProducer implements MessageSource { catch (InterruptedException e) { // eat it } - return (Math.random() > .5) ? MessageBuilder.withPayload(StringUtils.EMPTY).setHeader( - XmppHeaders.PRESENCE_MODE, Presence.Mode.chat).setHeader(XmppHeaders.PRESENCE_TYPE, - Presence.Type.available).setHeader(XmppHeaders.PRESENCE_STATUS, "She Loves me").build() + return (Math.random() > .5) ? MessageBuilder.withPayload("available").setHeader( + XmppHeaders.PRESENCE_MODE, Presence.Mode.chat) + .setHeader(XmppHeaders.PRESENCE_STATUS, "She Loves me").build() : MessageBuilder.withPayload(StringUtils.EMPTY).setHeader(XmppHeaders.PRESENCE_MODE, Presence.Mode.dnd) - .setHeader(XmppHeaders.PRESENCE_TYPE, Presence.Type.available).setHeader( - XmppHeaders.PRESENCE_STATUS, "She Loves me not").build(); + .setHeader(XmppHeaders.PRESENCE_STATUS, "She Loves me not").build(); } } diff --git a/spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/presence/XmppPresenceMessageMapperTests.java b/spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/presence/XmppPresenceMessageMapperTests.java index 66895c8eb4..4b4bfa0b00 100644 --- a/spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/presence/XmppPresenceMessageMapperTests.java +++ b/spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/presence/XmppPresenceMessageMapperTests.java @@ -32,6 +32,14 @@ import org.springframework.integration.xmpp.XmppHeaders; */ public class XmppPresenceMessageMapperTests { + @Test + public void testToMessage() throws Exception{ + Presence presence = new Presence(Type.available, "Hello", 1, Mode.chat); + XmppPresenceMessageMapper mapper = new XmppPresenceMessageMapper(); + Message presenceMessage = mapper.toMessage(presence); + assertEquals(presence, presenceMessage.getPayload()); + // TODO look into why presence attributes are also duplicated as headers + } @Test public void testFromMessageWithPayloadPresence() throws Exception{ Presence presence = new Presence(Type.available, "Hello", 1, Mode.chat); @@ -50,7 +58,6 @@ public class XmppPresenceMessageMapperTests { .setHeader(XmppHeaders.PRESENCE_FROM, "oleg") .setHeader(XmppHeaders.PRESENCE_MODE, Mode.chat) .setHeader(XmppHeaders.PRESENCE_STATUS, "hello") - .setHeader(XmppHeaders.PRESENCE_TYPE, Type.subscribed) .setHeader(XmppHeaders.PRESENCE_PRIORITY, 1) .build(); XmppPresenceMessageMapper mapper = new XmppPresenceMessageMapper(); @@ -66,7 +73,6 @@ public class XmppPresenceMessageMapperTests { .setHeader(XmppHeaders.PRESENCE_FROM, "oleg") .setHeader(XmppHeaders.PRESENCE_MODE, "chat") .setHeader(XmppHeaders.PRESENCE_STATUS, "hello") - .setHeader(XmppHeaders.PRESENCE_TYPE, "subscribed") .setHeader(XmppHeaders.PRESENCE_PRIORITY, 1) .build(); XmppPresenceMessageMapper mapper = new XmppPresenceMessageMapper(); @@ -87,16 +93,6 @@ public class XmppPresenceMessageMapperTests { mapper.fromMessage(message); } - @Test(expected=MessageMappingException.class) - public void testFromMessageWithPayloadPresenceTypeUnsupportedType() throws Exception{ - - Message message = MessageBuilder.withPayload(Type.available) - .setHeader(XmppHeaders.PRESENCE_TYPE, 1) - .build(); - XmppPresenceMessageMapper mapper = new XmppPresenceMessageMapper(); - mapper.fromMessage(message); - } - @Test(expected=MessageMappingException.class) public void testFromMessageWithUnsupportedPayload() throws Exception{ Message message = MessageBuilder.withPayload("hello").build(); From e20a929d1da872478728d0bceaec9f37a5f06514 Mon Sep 17 00:00:00 2001 From: Oleg Zhurakousky Date: Thu, 4 Nov 2010 10:59:34 -0400 Subject: [PATCH 38/82] INT-1554 added more tests for presenceChangeEvent, more clean up in XmppRosterEventMessageDrivenEndpoint --- .../XmppRosterEventMessageDrivenEndpoint.java | 31 ++++++++++++------- ...RosterEventMessageDrivenEndpointTests.java | 24 ++++++++++++++ 2 files changed, 44 insertions(+), 11 deletions(-) diff --git a/spring-integration-xmpp/src/main/java/org/springframework/integration/xmpp/presence/XmppRosterEventMessageDrivenEndpoint.java b/spring-integration-xmpp/src/main/java/org/springframework/integration/xmpp/presence/XmppRosterEventMessageDrivenEndpoint.java index 1a953af327..a18310c673 100644 --- a/spring-integration-xmpp/src/main/java/org/springframework/integration/xmpp/presence/XmppRosterEventMessageDrivenEndpoint.java +++ b/spring-integration-xmpp/src/main/java/org/springframework/integration/xmpp/presence/XmppRosterEventMessageDrivenEndpoint.java @@ -21,23 +21,25 @@ import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.builder.ToStringBuilder; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import org.jivesoftware.smack.Roster; import org.jivesoftware.smack.RosterListener; import org.jivesoftware.smack.XMPPConnection; import org.jivesoftware.smack.packet.Presence; import org.springframework.integration.Message; import org.springframework.integration.MessageChannel; +import org.springframework.integration.MessageHandlingException; +import org.springframework.integration.MessagingException; import org.springframework.integration.core.MessagingTemplate; import org.springframework.integration.endpoint.AbstractEndpoint; import org.springframework.integration.mapping.InboundMessageMapper; import org.springframework.util.Assert; - /** - * Describes an endpoint that is able to login as usual with a {@link org.springframework.integration.xmpp.XmppConnectionFactoryBean} and then emit {@link org.springframework.integration.Message}s when a particular event happens to the logged in users {@link org.jivesoftware.smack.Roster}. We try - * and generically propagate these events. In practical terms, there are a few events worth being notified of:
  • the {@link org.jivesoftware.smack.packet.Presence} of a user in the {@link org.jivesoftware.smack.Roster} has changed.
  • the actual makeup of the logged-in user's {@link - * org.jivesoftware.smack.Roster} has changed: entries added, deleted, etc.
+ * Describes an inbound endpoint that is able to login and then emit {@link Message}s when a + * particular event happens to the logged in users {@link Roster} (e.g., logged in/out, changed status etc.) * * @author Josh Long + * @author Oleg Zhurakousky * @since 2.0 */ public class XmppRosterEventMessageDrivenEndpoint extends AbstractEndpoint { @@ -99,22 +101,29 @@ public class XmppRosterEventMessageDrivenEndpoint extends AbstractEndpoint { } /** - * Called whenever an event happesn related to the {@link org.jivesoftware.smack.Roster} + * Called whenever an event happens related to the {@link Roster} * - * @param presence the {@link org.jivesoftware.smack.packet.Presence} object representing the new state (optional) + * @param presence the {@link Presence} object representing the new state */ - private void forwardRosterEventMessage(Presence presence) { + private void forwardRosterEventMessage(Presence presence) { + Message message = null; try { - Message msg = this.messageMapper.toMessage(presence); - messagingTemplate.send(requestChannel, msg); + message = this.messageMapper.toMessage(presence); + messagingTemplate.send(requestChannel, message); } catch (Exception e) { - logger.error("Failed to map packet to message ", e); + if (e instanceof MessagingException){ + throw (MessagingException)e; + } + else { + throw new MessageHandlingException(message, "Failed to send message", e); + } } } /** - * Subscribes to a given {@link org.jivesoftware.smack.Roster}s events and forwards them to components on the bus. + * RosterListener that subscribes to a given {@link Roster}s events + * and forwards them to messaging bus */ class EventForwardingRosterListener implements RosterListener { public void entriesAdded(final Collection entries) { diff --git a/spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/presence/XmppRosterEventMessageDrivenEndpointTests.java b/spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/presence/XmppRosterEventMessageDrivenEndpointTests.java index 57042e7c61..f3c382672a 100644 --- a/spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/presence/XmppRosterEventMessageDrivenEndpointTests.java +++ b/spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/presence/XmppRosterEventMessageDrivenEndpointTests.java @@ -26,10 +26,16 @@ import java.util.Set; import org.jivesoftware.smack.Roster; import org.jivesoftware.smack.RosterListener; import org.jivesoftware.smack.XMPPConnection; +import org.jivesoftware.smack.packet.Presence; +import org.jivesoftware.smack.packet.Presence.Mode; +import org.jivesoftware.smack.packet.Presence.Type; import org.junit.Test; import org.mockito.Mockito; import org.mockito.invocation.InvocationOnMock; import org.mockito.stubbing.Answer; +import org.springframework.integration.Message; +import org.springframework.integration.channel.QueueChannel; +import org.springframework.integration.test.util.TestUtils; /** * @author Oleg Zhurakousky @@ -74,4 +80,22 @@ public class XmppRosterEventMessageDrivenEndpointTests { XmppRosterEventMessageDrivenEndpoint rosterEndpoint = new XmppRosterEventMessageDrivenEndpoint(); rosterEndpoint.start(); } + + @Test + public void testPresenceChangeEvent(){ + XMPPConnection connection = mock(XMPPConnection.class); + Roster roster = mock(Roster.class); + when(connection.getRoster()).thenReturn(roster); + XmppRosterEventMessageDrivenEndpoint rosterEndpoint = new XmppRosterEventMessageDrivenEndpoint(); + rosterEndpoint.setXmppConnection(connection); + QueueChannel channel = new QueueChannel(); + rosterEndpoint.setRequestChannel(channel); + rosterEndpoint.afterPropertiesSet(); + rosterEndpoint.start(); + RosterListener rosterListener = (RosterListener) TestUtils.getPropertyValue(rosterEndpoint, "rosterListener"); + Presence presence = new Presence(Type.available, "Hello", 1, Mode.chat); + rosterListener.presenceChanged(presence); + Message message = channel.receive(10); + assertEquals(presence, message.getPayload()); + } } From 8d1e5e3f1dad5a00b0013501aec9003501d465b4 Mon Sep 17 00:00:00 2001 From: Oleg Zhurakousky Date: Thu, 4 Nov 2010 12:31:45 -0400 Subject: [PATCH 39/82] INT-1554 refactored XmppRosterEventOutboundEndpointParser, cleaned up XmppRosterEventMessageSendingHandler, added tests --- .../xmpp/config/XmppNamespaceHandler.java | 14 ---- ...XmppRosterEventOutboundEndpointParser.java | 40 ++++++++++ .../XmppRosterEventMessageSendingHandler.java | 76 ++++++++----------- .../config/spring-integration-xmpp-2.0.xsd | 12 +++ ...boundChannelAdapterParserTests-context.xml | 37 +++++++++ ...ventOutboundChannelAdapterParserTests.java | 70 +++++++++++++++++ ...dXmppRosterEventsEndpointTests-context.xml | 2 - ...RosterEventMessageSendingHandlerTests.java | 24 ++++++ 8 files changed, 215 insertions(+), 60 deletions(-) create mode 100644 spring-integration-xmpp/src/main/java/org/springframework/integration/xmpp/config/XmppRosterEventOutboundEndpointParser.java create mode 100644 spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/config/XmppRosterEventOutboundChannelAdapterParserTests-context.xml create mode 100644 spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/config/XmppRosterEventOutboundChannelAdapterParserTests.java create mode 100644 spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/messages/XmppRosterEventMessageSendingHandlerTests.java diff --git a/spring-integration-xmpp/src/main/java/org/springframework/integration/xmpp/config/XmppNamespaceHandler.java b/spring-integration-xmpp/src/main/java/org/springframework/integration/xmpp/config/XmppNamespaceHandler.java index 9f862253bd..21007a4fe1 100644 --- a/spring-integration-xmpp/src/main/java/org/springframework/integration/xmpp/config/XmppNamespaceHandler.java +++ b/spring-integration-xmpp/src/main/java/org/springframework/integration/xmpp/config/XmppNamespaceHandler.java @@ -92,19 +92,6 @@ public class XmppNamespaceHandler extends NamespaceHandlerSupport { } } - private static class XmppRosterEventOutboundEndpointParser extends AbstractOutboundChannelAdapterParser { - - @Override - protected AbstractBeanDefinition parseConsumer(Element element, ParserContext parserContext) { - BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition( - PACKAGE_NAME + ".presence.XmppRosterEventMessageSendingHandler"); - String connectionName = element.getAttribute("xmpp-connection"); - Assert.hasText(connectionName, "'xmpp-connection' must be defined"); - builder.addPropertyReference("xmppConnection", connectionName); - return builder.getBeanDefinition(); - } - } - private static class XmppRosterEventInboundEndpointParser extends AbstractSingleBeanDefinitionParser { @Override @@ -123,7 +110,6 @@ public class XmppNamespaceHandler extends NamespaceHandlerSupport { Assert.hasText(connectionName, "'xmpp-connection' must be defined"); builder.addPropertyReference("xmppConnection", connectionName); IntegrationNamespaceUtils.setReferenceIfAttributeDefined(builder, element, "channel", "requestChannel"); - //IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, "extract-payload"); IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, "auto-startup"); } } diff --git a/spring-integration-xmpp/src/main/java/org/springframework/integration/xmpp/config/XmppRosterEventOutboundEndpointParser.java b/spring-integration-xmpp/src/main/java/org/springframework/integration/xmpp/config/XmppRosterEventOutboundEndpointParser.java new file mode 100644 index 0000000000..80d9f007f2 --- /dev/null +++ b/spring-integration-xmpp/src/main/java/org/springframework/integration/xmpp/config/XmppRosterEventOutboundEndpointParser.java @@ -0,0 +1,40 @@ +/* + * Copyright 2002-2010 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.integration.xmpp.config; + +import org.springframework.beans.factory.support.AbstractBeanDefinition; +import org.springframework.beans.factory.support.BeanDefinitionBuilder; +import org.springframework.beans.factory.xml.ParserContext; +import org.springframework.integration.config.xml.AbstractOutboundChannelAdapterParser; +import org.springframework.integration.config.xml.IntegrationNamespaceUtils; +import org.w3c.dom.Element; + +/** + * @author Oleg Zhurakousky + * @since 2.0 + */ +public class XmppRosterEventOutboundEndpointParser extends AbstractOutboundChannelAdapterParser { + + @Override + protected AbstractBeanDefinition parseConsumer(Element element, ParserContext parserContext) { + BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition( + "org.springframework.integration.xmpp.presence.XmppRosterEventMessageSendingHandler"); + String connectionName = element.getAttribute("xmpp-connection"); + builder.addConstructorArgReference(connectionName); + IntegrationNamespaceUtils.setReferenceIfAttributeDefined(builder, element, "message-mapper"); + return builder.getBeanDefinition(); + } +} diff --git a/spring-integration-xmpp/src/main/java/org/springframework/integration/xmpp/presence/XmppRosterEventMessageSendingHandler.java b/spring-integration-xmpp/src/main/java/org/springframework/integration/xmpp/presence/XmppRosterEventMessageSendingHandler.java index 2cb6f7aeec..9e356ec6ad 100644 --- a/spring-integration-xmpp/src/main/java/org/springframework/integration/xmpp/presence/XmppRosterEventMessageSendingHandler.java +++ b/spring-integration-xmpp/src/main/java/org/springframework/integration/xmpp/presence/XmppRosterEventMessageSendingHandler.java @@ -1,13 +1,26 @@ +/* + * Copyright 2002-2010 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package org.springframework.integration.xmpp.presence; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; import org.jivesoftware.smack.XMPPConnection; import org.jivesoftware.smack.packet.Presence; -import org.springframework.context.Lifecycle; import org.springframework.integration.Message; import org.springframework.integration.handler.AbstractMessageHandler; import org.springframework.integration.mapping.OutboundMessageMapper; +import org.springframework.util.Assert; /** * This class will facilitate publishing updated presence values for a given connection. This change happens on the @@ -21,43 +34,17 @@ import org.springframework.integration.mapping.OutboundMessageMapper; * {@link org.jivesoftware.smack.packet.Presence.Type#available} ) * @since 2.0 */ -public class XmppRosterEventMessageSendingHandler extends AbstractMessageHandler implements Lifecycle { - private static final Log logger = LogFactory.getLog(XmppRosterEventMessageDrivenEndpoint.class); - - private volatile boolean running; - +public class XmppRosterEventMessageSendingHandler extends AbstractMessageHandler { + private OutboundMessageMapper messageMapper; - private volatile XMPPConnection xmppConnection; - - public void setXmppConnection(final XMPPConnection xmppConnection) { + private final XMPPConnection xmppConnection; + + public XmppRosterEventMessageSendingHandler(XMPPConnection xmppConnection){ + Assert.notNull(xmppConnection, "'xmppConnection' must not be null"); this.xmppConnection = xmppConnection; } - - public boolean isRunning() { - return this.running; - } - - public void start() { - if (null == this.messageMapper) { - this.messageMapper = new XmppPresenceMessageMapper(); - } - - this.running = true; - } - - public void stop() { - this.running = false; - - if (xmppConnection.isConnected()) { - if (logger.isInfoEnabled()) { - logger.info("shutting down XMPP connection"); - } - - xmppConnection.disconnect(); - } - } - + /** * the MessageMapper is responsible for converting outbound Messages into status updates of type * {@link org.jivesoftware.smack.packet.Presence} @@ -68,14 +55,15 @@ public class XmppRosterEventMessageSendingHandler extends AbstractMessageHandler this.messageMapper = messageMapper; } - @Override - protected void handleMessageInternal(Message message) throws Exception { - try { - Presence presence = this.messageMapper.fromMessage(message); - this.xmppConnection.sendPacket(presence); - } - catch (Exception e) { - logger.error("Failed to map packet to message ", e); + protected void onInit() throws Exception { + if (this.messageMapper == null) { + this.messageMapper = new XmppPresenceMessageMapper(); } } + + @Override + protected void handleMessageInternal(Message message) throws Exception { + Presence presence = this.messageMapper.fromMessage(message); + this.xmppConnection.sendPacket(presence); + } } diff --git a/spring-integration-xmpp/src/main/resources/org/springframework/integration/xmpp/config/spring-integration-xmpp-2.0.xsd b/spring-integration-xmpp/src/main/resources/org/springframework/integration/xmpp/config/spring-integration-xmpp-2.0.xsd index 0da2252357..54c1d01c0a 100644 --- a/spring-integration-xmpp/src/main/resources/org/springframework/integration/xmpp/config/spring-integration-xmpp-2.0.xsd +++ b/spring-integration-xmpp/src/main/resources/org/springframework/integration/xmpp/config/spring-integration-xmpp-2.0.xsd @@ -55,7 +55,19 @@ + + + + + + + + + + + + diff --git a/spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/config/XmppRosterEventOutboundChannelAdapterParserTests-context.xml b/spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/config/XmppRosterEventOutboundChannelAdapterParserTests-context.xml new file mode 100644 index 0000000000..02a0d3f985 --- /dev/null +++ b/spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/config/XmppRosterEventOutboundChannelAdapterParserTests-context.xml @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/config/XmppRosterEventOutboundChannelAdapterParserTests.java b/spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/config/XmppRosterEventOutboundChannelAdapterParserTests.java new file mode 100644 index 0000000000..576a1c2407 --- /dev/null +++ b/spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/config/XmppRosterEventOutboundChannelAdapterParserTests.java @@ -0,0 +1,70 @@ +/* + * Copyright 2002-2010 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.integration.xmpp.config; + +import static junit.framework.Assert.assertFalse; +import static junit.framework.Assert.assertNotNull; +import static junit.framework.Assert.assertTrue; + +import org.junit.Test; +import org.springframework.context.ApplicationContext; +import org.springframework.context.support.ClassPathXmlApplicationContext; +import org.springframework.integration.endpoint.EventDrivenConsumer; +import org.springframework.integration.endpoint.PollingConsumer; +import org.springframework.integration.mapping.OutboundMessageMapper; +import org.springframework.integration.test.util.TestUtils; +import org.springframework.integration.xmpp.presence.XmppPresenceMessageMapper; +import org.springframework.integration.xmpp.presence.XmppRosterEventMessageSendingHandler; + +/** + * @author Oleg Zhurakousky + * + */ +public class XmppRosterEventOutboundChannelAdapterParserTests { + + @Test + public void testRosterEventOutboundChannelAdapterParserAsPollingConsumer(){ + ApplicationContext ac = + new ClassPathXmlApplicationContext("XmppRosterEventOutboundChannelAdapterParserTests-context.xml", this.getClass()); + Object pollingConsumer = ac.getBean("pollingOutboundRosterAdapter"); + assertTrue(pollingConsumer instanceof PollingConsumer); + } + @Test + @SuppressWarnings("rawtypes") + public void testRosterEventOutboundChannelAdapterParserDefaultMapper(){ + ApplicationContext ac = + new ClassPathXmlApplicationContext("XmppRosterEventOutboundChannelAdapterParserTests-context.xml", this.getClass()); + Object pollingConsumer = ac.getBean("pollingOutboundRosterAdapter"); + XmppRosterEventMessageSendingHandler handler = + TestUtils.getPropertyValue(pollingConsumer, "handler", XmppRosterEventMessageSendingHandler.class); + OutboundMessageMapper mapper = TestUtils.getPropertyValue(handler, "messageMapper", OutboundMessageMapper.class); + assertNotNull(mapper); + assertTrue(mapper instanceof XmppPresenceMessageMapper); + } + @SuppressWarnings("rawtypes") + @Test + public void testRosterEventOutboundChannelAdapterParserCustomMapperEventDriven(){ + ApplicationContext ac = + new ClassPathXmlApplicationContext("XmppRosterEventOutboundChannelAdapterParserTests-context.xml", this.getClass()); + Object eventConsumer = ac.getBean("eventOutboundRosterAdapter"); + assertTrue(eventConsumer instanceof EventDrivenConsumer); + XmppRosterEventMessageSendingHandler handler = + TestUtils.getPropertyValue(eventConsumer, "handler", XmppRosterEventMessageSendingHandler.class); + OutboundMessageMapper mapper = TestUtils.getPropertyValue(handler, "messageMapper", OutboundMessageMapper.class); + assertNotNull(mapper); + assertFalse(mapper instanceof XmppPresenceMessageMapper); + } +} diff --git a/spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/ignore/OutboundXmppRosterEventsEndpointTests-context.xml b/spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/ignore/OutboundXmppRosterEventsEndpointTests-context.xml index ea2c506146..a26994b502 100644 --- a/spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/ignore/OutboundXmppRosterEventsEndpointTests-context.xml +++ b/spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/ignore/OutboundXmppRosterEventsEndpointTests-context.xml @@ -42,8 +42,6 @@ host="${user.1.host}" port="${user.1.port}" resource="${user.1.resource}" - sasl-mechanism-supported="${user.1.sasl.mechanism}" - sasl-mechanism-supported-index="${user.1.sasl.index}" service-name="${user.1.service}" /> diff --git a/spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/messages/XmppRosterEventMessageSendingHandlerTests.java b/spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/messages/XmppRosterEventMessageSendingHandlerTests.java new file mode 100644 index 0000000000..288c8fb165 --- /dev/null +++ b/spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/messages/XmppRosterEventMessageSendingHandlerTests.java @@ -0,0 +1,24 @@ +/* + * Copyright 2002-2010 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.integration.xmpp.messages; + +/** + * @author Oleg Zhurakousky + * + */ +public class XmppRosterEventMessageSendingHandlerTests { + +} From 601d67bcf8b462adf94177090b68a29fd0e6d2c8 Mon Sep 17 00:00:00 2001 From: Oleg Zhurakousky Date: Thu, 4 Nov 2010 13:29:15 -0400 Subject: [PATCH 40/82] INT-1554 refactored XmppMessageOutboundEndpointParser and XmppMessageSendingMessageHandler, added tests --- .../XmppMessageOutboundEndpointParser.java | 40 ++++++++++ .../xmpp/config/XmppNamespaceHandler.java | 16 ---- .../XmppMessageSendingMessageHandler.java | 40 +++------- .../config/spring-integration-xmpp-2.0.xsd | 5 +- ...ageOutboundEndpointParserTests-context.xml | 30 +++++++ ...mppMessageOutboundEndpointParserTests.java | 78 +++++++++++++++++++ ...XmppMessageSendingMessageHandlerTests.java | 7 +- 7 files changed, 164 insertions(+), 52 deletions(-) create mode 100644 spring-integration-xmpp/src/main/java/org/springframework/integration/xmpp/config/XmppMessageOutboundEndpointParser.java create mode 100644 spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/config/XmppMessageOutboundEndpointParserTests-context.xml create mode 100644 spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/config/XmppMessageOutboundEndpointParserTests.java diff --git a/spring-integration-xmpp/src/main/java/org/springframework/integration/xmpp/config/XmppMessageOutboundEndpointParser.java b/spring-integration-xmpp/src/main/java/org/springframework/integration/xmpp/config/XmppMessageOutboundEndpointParser.java new file mode 100644 index 0000000000..7c19b8f1ff --- /dev/null +++ b/spring-integration-xmpp/src/main/java/org/springframework/integration/xmpp/config/XmppMessageOutboundEndpointParser.java @@ -0,0 +1,40 @@ +/* + * Copyright 2002-2010 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.integration.xmpp.config; + +import org.springframework.beans.factory.support.AbstractBeanDefinition; +import org.springframework.beans.factory.support.BeanDefinitionBuilder; +import org.springframework.beans.factory.xml.ParserContext; +import org.springframework.integration.config.xml.AbstractOutboundChannelAdapterParser; +import org.w3c.dom.Element; + +/** + * Parser for 'xmpp:message-outbound-channel-adapter' element + * + * @author Oleg Zhurakousky + * @since 2.0 + */ +public class XmppMessageOutboundEndpointParser extends AbstractOutboundChannelAdapterParser { + + @Override + protected AbstractBeanDefinition parseConsumer(Element element, ParserContext parserContext) { + BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition( + "org.springframework.integration.xmpp.messages.XmppMessageSendingMessageHandler"); + String connectionName = element.getAttribute("xmpp-connection"); + builder.addConstructorArgReference(connectionName); + return builder.getBeanDefinition(); + } +} \ No newline at end of file diff --git a/spring-integration-xmpp/src/main/java/org/springframework/integration/xmpp/config/XmppNamespaceHandler.java b/spring-integration-xmpp/src/main/java/org/springframework/integration/xmpp/config/XmppNamespaceHandler.java index 21007a4fe1..7f57e1b4ef 100644 --- a/spring-integration-xmpp/src/main/java/org/springframework/integration/xmpp/config/XmppNamespaceHandler.java +++ b/spring-integration-xmpp/src/main/java/org/springframework/integration/xmpp/config/XmppNamespaceHandler.java @@ -17,12 +17,10 @@ package org.springframework.integration.xmpp.config; import org.jivesoftware.smack.packet.Presence; -import org.springframework.beans.factory.support.AbstractBeanDefinition; import org.springframework.beans.factory.support.BeanDefinitionBuilder; import org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser; import org.springframework.beans.factory.xml.NamespaceHandlerSupport; import org.springframework.beans.factory.xml.ParserContext; -import org.springframework.integration.config.xml.AbstractOutboundChannelAdapterParser; import org.springframework.integration.config.xml.HeaderEnricherParserSupport; import org.springframework.integration.config.xml.IntegrationNamespaceUtils; import org.springframework.integration.xmpp.XmppHeaders; @@ -54,20 +52,6 @@ public class XmppNamespaceHandler extends NamespaceHandlerSupport { registerBeanDefinitionParser("header-enricher", new XmppHeaderEnricherParser()); } - // messages - - private static class XmppMessageOutboundEndpointParser extends AbstractOutboundChannelAdapterParser { - - @Override - protected AbstractBeanDefinition parseConsumer(Element element, ParserContext parserContext) { - BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition( - PACKAGE_NAME + ".messages.XmppMessageSendingMessageHandler"); - String connectionName = element.getAttribute("xmpp-connection"); - Assert.hasText(connectionName, "'xmpp-connection' must be defined"); - builder.addPropertyReference("xmppConnection", connectionName); - return builder.getBeanDefinition(); - } - } private static class XmppMessageInboundEndpointParser extends AbstractSingleBeanDefinitionParser { diff --git a/spring-integration-xmpp/src/main/java/org/springframework/integration/xmpp/messages/XmppMessageSendingMessageHandler.java b/spring-integration-xmpp/src/main/java/org/springframework/integration/xmpp/messages/XmppMessageSendingMessageHandler.java index d6917c8157..2ea26ac750 100644 --- a/spring-integration-xmpp/src/main/java/org/springframework/integration/xmpp/messages/XmppMessageSendingMessageHandler.java +++ b/spring-integration-xmpp/src/main/java/org/springframework/integration/xmpp/messages/XmppMessageSendingMessageHandler.java @@ -16,12 +16,10 @@ package org.springframework.integration.xmpp.messages; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; import org.jivesoftware.smack.Chat; import org.jivesoftware.smack.XMPPConnection; import org.jivesoftware.smack.XMPPException; -import org.springframework.context.Lifecycle; +import org.springframework.integration.Message; import org.springframework.integration.MessageHandlingException; import org.springframework.integration.handler.AbstractMessageHandler; import org.springframework.integration.xmpp.XmppHeaders; @@ -34,19 +32,18 @@ import org.springframework.util.StringUtils; * @author Oleg Zhurakousky * @since 2.0 */ -public class XmppMessageSendingMessageHandler extends AbstractMessageHandler implements Lifecycle { +public class XmppMessageSendingMessageHandler extends AbstractMessageHandler { - private static final Log logger = LogFactory.getLog(XmppMessageSendingMessageHandler.class); +//private static final Log logger = LogFactory.getLog(XmppMessageSendingMessageHandler.class); - private volatile boolean running; - private volatile XMPPConnection xmppConnection; - - public void setXmppConnection(final XMPPConnection xmppConnection) { + private final XMPPConnection xmppConnection; + + public XmppMessageSendingMessageHandler(XMPPConnection xmppConnection){ + Assert.notNull(xmppConnection, "'xmppConnection' must no be null"); this.xmppConnection = xmppConnection; } - protected void handleMessageInternal(final org.springframework.integration.Message message) { - // pre-reqs: user to send, string to send as msg body + protected void handleMessageInternal(Message message) { String messageBody = null; String destinationUser = null; Object payload = message.getPayload(); @@ -65,29 +62,12 @@ public class XmppMessageSendingMessageHandler extends AbstractMessageHandler imp } } - public boolean isRunning() { - return this.running; - } - - public void start() { - this.running = true; - } - - public void stop() { - this.running = false; - if (xmppConnection.isConnected()) { - if (logger.isInfoEnabled()) { - logger.info("shutting down XMPP connection"); - } - xmppConnection.disconnect(); - } - } - private Chat getOrCreateChatWithParticipant(String userId, String thread) { Chat chat = null; if (!StringUtils.hasText(thread)) { chat = xmppConnection.getChatManager().createChat(userId, null); - } else { + } + else { chat = xmppConnection.getChatManager().getThreadChat(thread); if (chat == null) { chat = xmppConnection.getChatManager().createChat(userId, thread, null); diff --git a/spring-integration-xmpp/src/main/resources/org/springframework/integration/xmpp/config/spring-integration-xmpp-2.0.xsd b/spring-integration-xmpp/src/main/resources/org/springframework/integration/xmpp/config/spring-integration-xmpp-2.0.xsd index 54c1d01c0a..9fddf0bb0e 100644 --- a/spring-integration-xmpp/src/main/resources/org/springframework/integration/xmpp/config/spring-integration-xmpp-2.0.xsd +++ b/spring-integration-xmpp/src/main/resources/org/springframework/integration/xmpp/config/spring-integration-xmpp-2.0.xsd @@ -43,8 +43,6 @@ - - @@ -158,6 +156,9 @@ + + + diff --git a/spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/config/XmppMessageOutboundEndpointParserTests-context.xml b/spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/config/XmppMessageOutboundEndpointParserTests-context.xml new file mode 100644 index 0000000000..6c24f132a1 --- /dev/null +++ b/spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/config/XmppMessageOutboundEndpointParserTests-context.xml @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/config/XmppMessageOutboundEndpointParserTests.java b/spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/config/XmppMessageOutboundEndpointParserTests.java new file mode 100644 index 0000000000..7aeaf0a34c --- /dev/null +++ b/spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/config/XmppMessageOutboundEndpointParserTests.java @@ -0,0 +1,78 @@ +/* + * Copyright 2002-2010 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.integration.xmpp.config; + +import static junit.framework.Assert.assertTrue; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import org.jivesoftware.smack.Chat; +import org.jivesoftware.smack.ChatManager; +import org.jivesoftware.smack.MessageListener; +import org.jivesoftware.smack.XMPPConnection; +import org.junit.Test; +import org.mockito.Mockito; +import org.springframework.context.ApplicationContext; +import org.springframework.context.support.ClassPathXmlApplicationContext; +import org.springframework.integration.Message; +import org.springframework.integration.MessageChannel; +import org.springframework.integration.endpoint.EventDrivenConsumer; +import org.springframework.integration.endpoint.PollingConsumer; +import org.springframework.integration.support.MessageBuilder; +import org.springframework.integration.xmpp.XmppHeaders; + +/** + * @author Oleg Zhurakousky + * + */ +public class XmppMessageOutboundEndpointParserTests { + + @Test + public void testPollingConsumer(){ + ApplicationContext context = + new ClassPathXmlApplicationContext("XmppMessageOutboundEndpointParserTests-context.xml", XmppMessageOutboundEndpointParserTests.class); + Object pollingConsumer = context.getBean("outboundPollingAdapter"); + assertTrue(pollingConsumer instanceof PollingConsumer); + } + + @Test + public void testEventConsumer(){ + ApplicationContext context = + new ClassPathXmlApplicationContext("XmppMessageOutboundEndpointParserTests-context.xml", XmppMessageOutboundEndpointParserTests.class); + Object pollingConsumer = context.getBean("outboundEventAdapter"); + assertTrue(pollingConsumer instanceof EventDrivenConsumer); + } + + @Test + public void testPollingConsumerUsage() throws Exception{ + ApplicationContext context = + new ClassPathXmlApplicationContext("XmppMessageOutboundEndpointParserTests-context.xml", XmppMessageOutboundEndpointParserTests.class); + Object pollingConsumer = context.getBean("outboundPollingAdapter"); + assertTrue(pollingConsumer instanceof PollingConsumer); + MessageChannel channel = context.getBean("outboundEventChannel", MessageChannel.class); + Message message = MessageBuilder.withPayload("hello").setHeader(XmppHeaders.CHAT_TO_USER, "oleg").build(); + + XMPPConnection connection = context.getBean("testConnection", XMPPConnection.class); + ChatManager chatManager = mock(ChatManager.class); + when(connection.getChatManager()).thenReturn(chatManager); + Chat chat = mock(Chat.class); + when(chatManager.createChat(Mockito.anyString(), Mockito.any(MessageListener.class))).thenReturn(chat); + channel.send(message); + verify(chat, times(1)).sendMessage("hello"); + } +} diff --git a/spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/messages/XmppMessageSendingMessageHandlerTests.java b/spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/messages/XmppMessageSendingMessageHandlerTests.java index 04527dd262..19dc9bec76 100644 --- a/spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/messages/XmppMessageSendingMessageHandlerTests.java +++ b/spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/messages/XmppMessageSendingMessageHandlerTests.java @@ -36,8 +36,7 @@ public class XmppMessageSendingMessageHandlerTests { Chat chat = mock(Chat.class); when(chantManager.createChat(Mockito.any(String.class), Mockito.any(MessageListener.class))).thenReturn(chat); - XmppMessageSendingMessageHandler handler = new XmppMessageSendingMessageHandler(); - handler.setXmppConnection(connection); + XmppMessageSendingMessageHandler handler = new XmppMessageSendingMessageHandler(connection); Message message = MessageBuilder.withPayload("Test Message"). setHeader(XmppHeaders.CHAT_TO_USER, "kermit@frog.com"). @@ -65,13 +64,13 @@ public class XmppMessageSendingMessageHandlerTests { @Test(expected=MessageHandlingException.class) public void validateFailureNoChatToUser() throws Exception{ - XmppMessageSendingMessageHandler handler = new XmppMessageSendingMessageHandler(); + XmppMessageSendingMessageHandler handler = new XmppMessageSendingMessageHandler(mock(XMPPConnection.class)); handler.handleMessage(new GenericMessage("hello")); } @Test(expected=MessageHandlingException.class) public void validateMessageWithUnsupportedPayload() throws Exception{ - XmppMessageSendingMessageHandler handler = new XmppMessageSendingMessageHandler(); + XmppMessageSendingMessageHandler handler = new XmppMessageSendingMessageHandler(mock(XMPPConnection.class)); handler.handleMessage(new GenericMessage(123)); } } From 5f5de2fe42c4bc3a048138d85a2006d9f3601784 Mon Sep 17 00:00:00 2001 From: Oleg Zhurakousky Date: Thu, 4 Nov 2010 13:32:35 -0400 Subject: [PATCH 41/82] INT-1554 polishing, further restructuring of XmppNamespaceHandler --- .../xmpp/config/XmppNamespaceHandler.java | 20 ------------------- .../XmppMessageSendingMessageHandler.java | 2 -- 2 files changed, 22 deletions(-) diff --git a/spring-integration-xmpp/src/main/java/org/springframework/integration/xmpp/config/XmppNamespaceHandler.java b/spring-integration-xmpp/src/main/java/org/springframework/integration/xmpp/config/XmppNamespaceHandler.java index 7f57e1b4ef..7492f2ae3c 100644 --- a/spring-integration-xmpp/src/main/java/org/springframework/integration/xmpp/config/XmppNamespaceHandler.java +++ b/spring-integration-xmpp/src/main/java/org/springframework/integration/xmpp/config/XmppNamespaceHandler.java @@ -16,14 +16,11 @@ package org.springframework.integration.xmpp.config; -import org.jivesoftware.smack.packet.Presence; import org.springframework.beans.factory.support.BeanDefinitionBuilder; import org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser; import org.springframework.beans.factory.xml.NamespaceHandlerSupport; import org.springframework.beans.factory.xml.ParserContext; -import org.springframework.integration.config.xml.HeaderEnricherParserSupport; import org.springframework.integration.config.xml.IntegrationNamespaceUtils; -import org.springframework.integration.xmpp.XmppHeaders; import org.springframework.util.Assert; import org.w3c.dom.Element; @@ -97,21 +94,4 @@ public class XmppNamespaceHandler extends NamespaceHandlerSupport { IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, "auto-startup"); } } - - private static class XmppHeaderEnricherParser extends HeaderEnricherParserSupport { - - public XmppHeaderEnricherParser() { - - // chat headers - this.addElementToHeaderMapping("message-to", XmppHeaders.CHAT_TO_USER); - this.addElementToHeaderMapping("message-thread-id", XmppHeaders.CHAT_THREAD_ID); - - // presence headers - this.addElementToHeaderMapping("presence-mode", XmppHeaders.PRESENCE_MODE, Presence.Mode.class); - this.addElementToHeaderMapping("presence-from", XmppHeaders.PRESENCE_FROM); - this.addElementToHeaderMapping("presence-status", XmppHeaders.PRESENCE_STATUS); - this.addElementToHeaderMapping("presence-priority", XmppHeaders.PRESENCE_PRIORITY, Integer.class); - } - } - } diff --git a/spring-integration-xmpp/src/main/java/org/springframework/integration/xmpp/messages/XmppMessageSendingMessageHandler.java b/spring-integration-xmpp/src/main/java/org/springframework/integration/xmpp/messages/XmppMessageSendingMessageHandler.java index 2ea26ac750..2c118af7c6 100644 --- a/spring-integration-xmpp/src/main/java/org/springframework/integration/xmpp/messages/XmppMessageSendingMessageHandler.java +++ b/spring-integration-xmpp/src/main/java/org/springframework/integration/xmpp/messages/XmppMessageSendingMessageHandler.java @@ -34,8 +34,6 @@ import org.springframework.util.StringUtils; */ public class XmppMessageSendingMessageHandler extends AbstractMessageHandler { -//private static final Log logger = LogFactory.getLog(XmppMessageSendingMessageHandler.class); - private final XMPPConnection xmppConnection; public XmppMessageSendingMessageHandler(XMPPConnection xmppConnection){ From b87cf6fa4a9177ffd9ec01844bf88cc4968303f0 Mon Sep 17 00:00:00 2001 From: Oleg Zhurakousky Date: Thu, 4 Nov 2010 13:34:06 -0400 Subject: [PATCH 42/82] INT-1554 polishing, actually pushing ;) further restructuring of XmppNamespaceHandler --- .../xmpp/config/XmppHeaderEnricherParser.java | 41 +++++++++++++++++++ 1 file changed, 41 insertions(+) create mode 100644 spring-integration-xmpp/src/main/java/org/springframework/integration/xmpp/config/XmppHeaderEnricherParser.java diff --git a/spring-integration-xmpp/src/main/java/org/springframework/integration/xmpp/config/XmppHeaderEnricherParser.java b/spring-integration-xmpp/src/main/java/org/springframework/integration/xmpp/config/XmppHeaderEnricherParser.java new file mode 100644 index 0000000000..144bcc4784 --- /dev/null +++ b/spring-integration-xmpp/src/main/java/org/springframework/integration/xmpp/config/XmppHeaderEnricherParser.java @@ -0,0 +1,41 @@ +/* + * Copyright 2002-2010 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.integration.xmpp.config; + +import org.jivesoftware.smack.packet.Presence; +import org.springframework.integration.config.xml.HeaderEnricherParserSupport; +import org.springframework.integration.xmpp.XmppHeaders; + +/** + * @author Josh Long + * @since 2.0 + * + */ +public class XmppHeaderEnricherParser extends HeaderEnricherParserSupport { + + public XmppHeaderEnricherParser() { + + // chat headers + this.addElementToHeaderMapping("message-to", XmppHeaders.CHAT_TO_USER); + this.addElementToHeaderMapping("message-thread-id", XmppHeaders.CHAT_THREAD_ID); + + // presence headers + this.addElementToHeaderMapping("presence-mode", XmppHeaders.PRESENCE_MODE, Presence.Mode.class); + this.addElementToHeaderMapping("presence-from", XmppHeaders.PRESENCE_FROM); + this.addElementToHeaderMapping("presence-status", XmppHeaders.PRESENCE_STATUS); + this.addElementToHeaderMapping("presence-priority", XmppHeaders.PRESENCE_PRIORITY, Integer.class); + } +} From acf9d2bc13c8982331493c84f296f5e1c84c3d6d Mon Sep 17 00:00:00 2001 From: Oleg Zhurakousky Date: Thu, 4 Nov 2010 13:40:45 -0400 Subject: [PATCH 43/82] INT-1554 polishing, finished restructuring of XmppNamespaceHandler --- .../XmppMessageInboundEndpointParser.java | 51 ++++++++++++++++++ .../xmpp/config/XmppNamespaceHandler.java | 54 +------------------ .../XmppRosterEventInboundEndpointParser.java | 51 ++++++++++++++++++ .../XmppRosterEventMessageDrivenEndpoint.java | 1 - 4 files changed, 103 insertions(+), 54 deletions(-) create mode 100644 spring-integration-xmpp/src/main/java/org/springframework/integration/xmpp/config/XmppMessageInboundEndpointParser.java create mode 100644 spring-integration-xmpp/src/main/java/org/springframework/integration/xmpp/config/XmppRosterEventInboundEndpointParser.java diff --git a/spring-integration-xmpp/src/main/java/org/springframework/integration/xmpp/config/XmppMessageInboundEndpointParser.java b/spring-integration-xmpp/src/main/java/org/springframework/integration/xmpp/config/XmppMessageInboundEndpointParser.java new file mode 100644 index 0000000000..49fbee0e9e --- /dev/null +++ b/spring-integration-xmpp/src/main/java/org/springframework/integration/xmpp/config/XmppMessageInboundEndpointParser.java @@ -0,0 +1,51 @@ +/* + * Copyright 2002-2010 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.integration.xmpp.config; + +import org.springframework.beans.factory.support.BeanDefinitionBuilder; +import org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser; +import org.springframework.beans.factory.xml.ParserContext; +import org.springframework.integration.config.xml.IntegrationNamespaceUtils; +import org.springframework.util.Assert; +import org.w3c.dom.Element; + +/** + * @author Josh Long + * @author Oleg Zhurakousky + * @since 2.0 + */ +public class XmppMessageInboundEndpointParser extends AbstractSingleBeanDefinitionParser { + + @Override + protected String getBeanClassName(Element element) { + return "org.springframework.integration.xmpp.messages.XmppMessageDrivenEndpoint"; + } + + @Override + protected boolean shouldGenerateIdAsFallback() { + return true; + } + + @Override + protected void doParse(Element element, ParserContext parserContext, BeanDefinitionBuilder builder) { + String connectionName = element.getAttribute("xmpp-connection"); + Assert.hasText(connectionName, "'xmpp-connection' must be defined"); + builder.addPropertyReference("xmppConnection", connectionName); + IntegrationNamespaceUtils.setReferenceIfAttributeDefined(builder, element, "channel", "requestChannel"); + IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, "extract-payload"); + IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, "auto-startup"); + } +} diff --git a/spring-integration-xmpp/src/main/java/org/springframework/integration/xmpp/config/XmppNamespaceHandler.java b/spring-integration-xmpp/src/main/java/org/springframework/integration/xmpp/config/XmppNamespaceHandler.java index 7492f2ae3c..d85114054f 100644 --- a/spring-integration-xmpp/src/main/java/org/springframework/integration/xmpp/config/XmppNamespaceHandler.java +++ b/spring-integration-xmpp/src/main/java/org/springframework/integration/xmpp/config/XmppNamespaceHandler.java @@ -16,25 +16,18 @@ package org.springframework.integration.xmpp.config; -import org.springframework.beans.factory.support.BeanDefinitionBuilder; -import org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser; import org.springframework.beans.factory.xml.NamespaceHandlerSupport; -import org.springframework.beans.factory.xml.ParserContext; -import org.springframework.integration.config.xml.IntegrationNamespaceUtils; -import org.springframework.util.Assert; -import org.w3c.dom.Element; /** * This class parses the schema for XMPP support. * * @author Josh Long * @author Mark Fisher + * @author Oleg Zhurakousky * @since 2.0 */ public class XmppNamespaceHandler extends NamespaceHandlerSupport { - private static final String PACKAGE_NAME = "org.springframework.integration.xmpp"; - public void init() { // connection registerBeanDefinitionParser("xmpp-connection", new XmppConnectionParser()); @@ -49,49 +42,4 @@ public class XmppNamespaceHandler extends NamespaceHandlerSupport { registerBeanDefinitionParser("header-enricher", new XmppHeaderEnricherParser()); } - - private static class XmppMessageInboundEndpointParser extends AbstractSingleBeanDefinitionParser { - - @Override - protected String getBeanClassName(Element element) { - return PACKAGE_NAME + ".messages.XmppMessageDrivenEndpoint"; - } - - @Override - protected boolean shouldGenerateIdAsFallback() { - return true; - } - - @Override - protected void doParse(Element element, ParserContext parserContext, BeanDefinitionBuilder builder) { - String connectionName = element.getAttribute("xmpp-connection"); - Assert.hasText(connectionName, "'xmpp-connection' must be defined"); - builder.addPropertyReference("xmppConnection", connectionName); - IntegrationNamespaceUtils.setReferenceIfAttributeDefined(builder, element, "channel", "requestChannel"); - IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, "extract-payload"); - IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, "auto-startup"); - } - } - - private static class XmppRosterEventInboundEndpointParser extends AbstractSingleBeanDefinitionParser { - - @Override - protected String getBeanClassName(Element element) { - return PACKAGE_NAME + ".presence.XmppRosterEventMessageDrivenEndpoint"; - } - - @Override - protected boolean shouldGenerateIdAsFallback() { - return true; - } - - @Override - protected void doParse(Element element, ParserContext parserContext, BeanDefinitionBuilder builder) { - String connectionName = element.getAttribute("xmpp-connection"); - Assert.hasText(connectionName, "'xmpp-connection' must be defined"); - builder.addPropertyReference("xmppConnection", connectionName); - IntegrationNamespaceUtils.setReferenceIfAttributeDefined(builder, element, "channel", "requestChannel"); - IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, "auto-startup"); - } - } } diff --git a/spring-integration-xmpp/src/main/java/org/springframework/integration/xmpp/config/XmppRosterEventInboundEndpointParser.java b/spring-integration-xmpp/src/main/java/org/springframework/integration/xmpp/config/XmppRosterEventInboundEndpointParser.java new file mode 100644 index 0000000000..72c2478692 --- /dev/null +++ b/spring-integration-xmpp/src/main/java/org/springframework/integration/xmpp/config/XmppRosterEventInboundEndpointParser.java @@ -0,0 +1,51 @@ +/* + * Copyright 2002-2010 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.integration.xmpp.config; + +import org.springframework.beans.factory.support.BeanDefinitionBuilder; +import org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser; +import org.springframework.beans.factory.xml.ParserContext; +import org.springframework.integration.config.xml.IntegrationNamespaceUtils; +import org.springframework.util.Assert; +import org.w3c.dom.Element; + +/** + * @author Josh Long + * @author Oleg Zhurakousky + * @since 2.0 + * + */ +public class XmppRosterEventInboundEndpointParser extends AbstractSingleBeanDefinitionParser { + + @Override + protected String getBeanClassName(Element element) { + return "org.springframework.integration.xmpp.presenceXmppRosterEventMessageDrivenEndpoint"; + } + + @Override + protected boolean shouldGenerateIdAsFallback() { + return true; + } + + @Override + protected void doParse(Element element, ParserContext parserContext, BeanDefinitionBuilder builder) { + String connectionName = element.getAttribute("xmpp-connection"); + Assert.hasText(connectionName, "'xmpp-connection' must be defined"); + builder.addPropertyReference("xmppConnection", connectionName); + IntegrationNamespaceUtils.setReferenceIfAttributeDefined(builder, element, "channel", "requestChannel"); + IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, "auto-startup"); + } +} \ No newline at end of file diff --git a/spring-integration-xmpp/src/main/java/org/springframework/integration/xmpp/presence/XmppRosterEventMessageDrivenEndpoint.java b/spring-integration-xmpp/src/main/java/org/springframework/integration/xmpp/presence/XmppRosterEventMessageDrivenEndpoint.java index a18310c673..0e376bbb45 100644 --- a/spring-integration-xmpp/src/main/java/org/springframework/integration/xmpp/presence/XmppRosterEventMessageDrivenEndpoint.java +++ b/spring-integration-xmpp/src/main/java/org/springframework/integration/xmpp/presence/XmppRosterEventMessageDrivenEndpoint.java @@ -143,5 +143,4 @@ public class XmppRosterEventMessageDrivenEndpoint extends AbstractEndpoint { forwardRosterEventMessage(presence); } } - } From f07dc4a68f5c72ddc465cb5447648f3dca78a8aa Mon Sep 17 00:00:00 2001 From: Oleg Zhurakousky Date: Thu, 4 Nov 2010 13:51:36 -0400 Subject: [PATCH 44/82] INT-1554 polishing XmppMessageDrivenEndpoint, uts parser and tests --- .../XmppMessageInboundEndpointParser.java | 6 +-- .../messages/XmppMessageDrivenEndpoint.java | 45 +++++-------------- .../XmppMessageDrivenEndpointTests.java | 8 ++-- 3 files changed, 19 insertions(+), 40 deletions(-) diff --git a/spring-integration-xmpp/src/main/java/org/springframework/integration/xmpp/config/XmppMessageInboundEndpointParser.java b/spring-integration-xmpp/src/main/java/org/springframework/integration/xmpp/config/XmppMessageInboundEndpointParser.java index 49fbee0e9e..2542ff53ae 100644 --- a/spring-integration-xmpp/src/main/java/org/springframework/integration/xmpp/config/XmppMessageInboundEndpointParser.java +++ b/spring-integration-xmpp/src/main/java/org/springframework/integration/xmpp/config/XmppMessageInboundEndpointParser.java @@ -19,10 +19,11 @@ import org.springframework.beans.factory.support.BeanDefinitionBuilder; import org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser; import org.springframework.beans.factory.xml.ParserContext; import org.springframework.integration.config.xml.IntegrationNamespaceUtils; -import org.springframework.util.Assert; import org.w3c.dom.Element; /** + * Parser for 'message-inbound-channel-adapter' element + * * @author Josh Long * @author Oleg Zhurakousky * @since 2.0 @@ -42,8 +43,7 @@ public class XmppMessageInboundEndpointParser extends AbstractSingleBeanDefiniti @Override protected void doParse(Element element, ParserContext parserContext, BeanDefinitionBuilder builder) { String connectionName = element.getAttribute("xmpp-connection"); - Assert.hasText(connectionName, "'xmpp-connection' must be defined"); - builder.addPropertyReference("xmppConnection", connectionName); + builder.addConstructorArgReference(connectionName); IntegrationNamespaceUtils.setReferenceIfAttributeDefined(builder, element, "channel", "requestChannel"); IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, "extract-payload"); IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, "auto-startup"); diff --git a/spring-integration-xmpp/src/main/java/org/springframework/integration/xmpp/messages/XmppMessageDrivenEndpoint.java b/spring-integration-xmpp/src/main/java/org/springframework/integration/xmpp/messages/XmppMessageDrivenEndpoint.java index 5c435eba7d..3e8a6c7267 100644 --- a/spring-integration-xmpp/src/main/java/org/springframework/integration/xmpp/messages/XmppMessageDrivenEndpoint.java +++ b/spring-integration-xmpp/src/main/java/org/springframework/integration/xmpp/messages/XmppMessageDrivenEndpoint.java @@ -16,8 +16,6 @@ package org.springframework.integration.xmpp.messages; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; import org.jivesoftware.smack.Chat; import org.jivesoftware.smack.ChatManager; import org.jivesoftware.smack.PacketListener; @@ -33,48 +31,35 @@ import org.springframework.util.Assert; /** * This component logs in as a user and forwards any messages to that - * user on to downstream components. The component is an endpoint that has its - * own lifecycle and does not need any poller - * to work. It takes any message from a given XMPP session (as established by + * user on to downstream components. + * It takes any message from a given XMPP session (as established by * the current {@link XMPPConnection}) and forwards the * {@link org.jivesoftware.smack.packet.Message} as the payload of the Spring - * Integration {@link org.springframework.integration.Message}. The - * {@link org.jivesoftware.smack.Chat} instance that's used is passed along as a - * header (under {@link org.springframework.integration.xmpp.XmppHeaders#CHAT}). - * Additionally, the {@link org.jivesoftware.smack.packet.Message.Type} is - * passed along under the header - * {@link org.springframework.integration.xmpp.XmppHeaders#TYPE}. Both of these - * pieces of metadata can be obtained directly from the payload, if required. - * They are here as a convenience. - *

+ * Integration {@link org.springframework.integration.Message}. * Note: the {@link org.jivesoftware.smack.ChatManager} * maintains a Map<String, Chat> for threads and users, where the threadID * ({@link String}) is the key or the userID {@link String} is the key. This * {@link java.util.Map} is a Smack-specific implementation called * {@link org.jivesoftware.smack.util.collections.ReferenceMap} that removes - * key/values as references are dereferenced. Take care to enable this garbage - * collection, taking what you need from the payload and the headers and - * discarding as soon as possible. + * key/values as references are dereferenced. * * @author Josh Long * @author Mark Fisher + * @author Oleg Zhurakousky + * * @see ChatManager the ChatManager class that * keeps watch over all Chats between the client and any other * participants. - * @see MessagingTemplate - * handles all interesing operations on any Spring Integration channels. * @see XMPPConnection the XMPPConnection (as * created by {@link XmppConnectionFactory} */ public class XmppMessageDrivenEndpoint extends AbstractEndpoint { - private static final Log logger = LogFactory.getLog(XmppMessageDrivenEndpoint.class); - private final MessagingTemplate messagingTemplate = new MessagingTemplate(); private volatile MessageChannel requestChannel; - private volatile XMPPConnection xmppConnection; + private final XMPPConnection xmppConnection; private volatile boolean extractPayload = true; @@ -82,24 +67,17 @@ public class XmppMessageDrivenEndpoint extends AbstractEndpoint { private volatile boolean initialized; - /** - * This will be injected or configured via a xmpp-connection-factory element. - * - * @param xmppConnection the connection - */ - public void setXmppConnection(final XMPPConnection xmppConnection) { + public XmppMessageDrivenEndpoint(XMPPConnection xmppConnection){ this.xmppConnection = xmppConnection; } - + /** * @param requestChannel the channel on which the inbound message should be sent */ - public void setRequestChannel(final MessageChannel requestChannel) { - this.messagingTemplate.setDefaultChannel(requestChannel); + public void setRequestChannel(MessageChannel requestChannel) { this.requestChannel = requestChannel; } - /** * Specify whether the text message body should be extracted when mapping to a * Spring Integration Message payload. Otherwise, the full XMPP Message will be @@ -122,7 +100,8 @@ public class XmppMessageDrivenEndpoint extends AbstractEndpoint { @Override protected void onInit() throws Exception { - messagingTemplate.afterPropertiesSet(); + this.messagingTemplate.setDefaultChannel(requestChannel); + this.messagingTemplate.afterPropertiesSet(); this.packetListener = new PacketListener() { public void processPacket(final Packet packet) { org.jivesoftware.smack.packet.Message message = (org.jivesoftware.smack.packet.Message) packet; diff --git a/spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/messages/XmppMessageDrivenEndpointTests.java b/spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/messages/XmppMessageDrivenEndpointTests.java index c19a496405..ea8919cdbe 100644 --- a/spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/messages/XmppMessageDrivenEndpointTests.java +++ b/spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/messages/XmppMessageDrivenEndpointTests.java @@ -43,9 +43,10 @@ public class XmppMessageDrivenEndpointTests { */ public void testLifecycle(){ final Set packetListSet = new HashSet(); - XmppMessageDrivenEndpoint endpoint = new XmppMessageDrivenEndpoint(); - XMPPConnection connection = mock(XMPPConnection.class); + XmppMessageDrivenEndpoint endpoint = new XmppMessageDrivenEndpoint(connection); + + doAnswer(new Answer() { @Override public Object answer(InvocationOnMock invocation) throws Throwable { @@ -62,7 +63,6 @@ public class XmppMessageDrivenEndpointTests { } }).when(connection).removePacketListener(Mockito.any(PacketListener.class)); - endpoint.setXmppConnection(connection); assertEquals(0, packetListSet.size()); endpoint.afterPropertiesSet(); endpoint.start(); @@ -73,7 +73,7 @@ public class XmppMessageDrivenEndpointTests { @Test(expected=IllegalArgumentException.class) public void testNonInitializationFailure(){ - XmppMessageDrivenEndpoint endpoint = new XmppMessageDrivenEndpoint(); + XmppMessageDrivenEndpoint endpoint = new XmppMessageDrivenEndpoint(mock(XMPPConnection.class)); endpoint.start(); } } From 2695566a8be76eac861a2cec4e49ed948f2f410b Mon Sep 17 00:00:00 2001 From: Oleg Zhurakousky Date: Thu, 4 Nov 2010 14:20:42 -0400 Subject: [PATCH 45/82] INT-1580 added tests and sample config for more complex configuration of the XmppConnection --- .../XmppRosterEventMessageDrivenEndpoint.java | 6 +-- ...XmppConnectionFactoryBeanTests-context.xml | 23 ++++++++++ .../xmpp/XmppConnectionFactoryBeanTests.java | 44 +++++++++++++++++++ 3 files changed, 70 insertions(+), 3 deletions(-) create mode 100644 spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/XmppConnectionFactoryBeanTests-context.xml create mode 100644 spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/XmppConnectionFactoryBeanTests.java diff --git a/spring-integration-xmpp/src/main/java/org/springframework/integration/xmpp/presence/XmppRosterEventMessageDrivenEndpoint.java b/spring-integration-xmpp/src/main/java/org/springframework/integration/xmpp/presence/XmppRosterEventMessageDrivenEndpoint.java index 0e376bbb45..bc15f7b31e 100644 --- a/spring-integration-xmpp/src/main/java/org/springframework/integration/xmpp/presence/XmppRosterEventMessageDrivenEndpoint.java +++ b/spring-integration-xmpp/src/main/java/org/springframework/integration/xmpp/presence/XmppRosterEventMessageDrivenEndpoint.java @@ -36,7 +36,8 @@ import org.springframework.util.Assert; /** * Describes an inbound endpoint that is able to login and then emit {@link Message}s when a - * particular event happens to the logged in users {@link Roster} (e.g., logged in/out, changed status etc.) + * particular Presence event happens to the logged in users {@link Roster} + * (e.g., logged in/out, changed status etc.) * * @author Josh Long * @author Oleg Zhurakousky @@ -71,7 +72,6 @@ public class XmppRosterEventMessageDrivenEndpoint extends AbstractEndpoint { * @param requestChannel the channel on which the inbound message should be sent */ public void setRequestChannel(final MessageChannel requestChannel) { - this.messagingTemplate.setDefaultChannel(requestChannel); this.requestChannel = requestChannel; } @@ -95,7 +95,7 @@ public class XmppRosterEventMessageDrivenEndpoint extends AbstractEndpoint { if (null == this.messageMapper) { this.messageMapper = new XmppPresenceMessageMapper(); } - + this.messagingTemplate.setDefaultChannel(requestChannel); this.messagingTemplate.afterPropertiesSet(); this.initialized = true; } diff --git a/spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/XmppConnectionFactoryBeanTests-context.xml b/spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/XmppConnectionFactoryBeanTests-context.xml new file mode 100644 index 0000000000..7ff2662de6 --- /dev/null +++ b/spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/XmppConnectionFactoryBeanTests-context.xml @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + + diff --git a/spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/XmppConnectionFactoryBeanTests.java b/spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/XmppConnectionFactoryBeanTests.java new file mode 100644 index 0000000000..555a3b791e --- /dev/null +++ b/spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/XmppConnectionFactoryBeanTests.java @@ -0,0 +1,44 @@ +/* + * Copyright 2002-2010 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.integration.xmpp; + +import static junit.framework.Assert.assertNotNull; +import static org.mockito.Mockito.mock; + +import org.jivesoftware.smack.ConnectionConfiguration; +import org.jivesoftware.smack.XMPPConnection; +import org.junit.Test; +import org.springframework.context.ApplicationContext; +import org.springframework.context.support.ClassPathXmlApplicationContext; + +/** + * @author Oleg Zhurakousky + * + */ +public class XmppConnectionFactoryBeanTests { + + @Test + public void testXmppConnectionFactoryBean() throws Exception{ + XmppConnectionFactoryBean xmppConnectionFactoryBean = new XmppConnectionFactoryBean(mock(ConnectionConfiguration.class)); + XMPPConnection connection = xmppConnectionFactoryBean.createInstance(); + assertNotNull(connection); + } + @Test + public void testXmppConnectionFactoryBeanViaConfig() throws Exception{ + ApplicationContext ac = new ClassPathXmlApplicationContext("XmppConnectionFactoryBeanTests-context.xml", this.getClass()); + // the fact that no exception was thrown satisfies this test + } +} From 24b08f2602ad424422357400c9fc2e66e0babb9b Mon Sep 17 00:00:00 2001 From: Mark Fisher Date: Thu, 4 Nov 2010 16:10:55 -0400 Subject: [PATCH 46/82] polishing --- ...stractScriptExecutingMessageProcessor.java | 4 ++- .../BeanFactoryContextBindingCustomizer.java | 18 ++++++++---- ...GroovyScriptExecutingMessageProcessor.java | 10 +++---- .../GroovyScriptPayloadMessageProcessor.java | 10 ++++--- .../groovy/MapContextBindingCustomizer.java | 13 ++++++--- .../MessageContextBindingCustomizer.java | 20 ++++++++----- .../config/GroovyControlBusFactoryBean.java | 9 ++++-- .../groovy/config/GroovyControlBusParser.java | 15 +++++----- .../groovy/config/GroovyScriptParser.java | 4 ++- .../RefreshableResourceScriptSource.java | 29 ++++++++++--------- 10 files changed, 79 insertions(+), 53 deletions(-) diff --git a/spring-integration-core/src/main/java/org/springframework/integration/handler/AbstractScriptExecutingMessageProcessor.java b/spring-integration-core/src/main/java/org/springframework/integration/handler/AbstractScriptExecutingMessageProcessor.java index e51a74ea40..4319d9d6c1 100644 --- a/spring-integration-core/src/main/java/org/springframework/integration/handler/AbstractScriptExecutingMessageProcessor.java +++ b/spring-integration-core/src/main/java/org/springframework/integration/handler/AbstractScriptExecutingMessageProcessor.java @@ -31,11 +31,13 @@ public abstract class AbstractScriptExecutingMessageProcessor implements Mess public final T processMessage(Message message) { try { return this.executeScript(getScriptSource(message), message); - } catch (Exception e) { + } + catch (Exception e) { throw new MessageHandlingException(message, "failed to execute script", e); } } + /** * Subclasses must implement this method to create a script source, optionally using the message to locate or * create the script. diff --git a/spring-integration-groovy/src/main/java/org/springframework/integration/groovy/BeanFactoryContextBindingCustomizer.java b/spring-integration-groovy/src/main/java/org/springframework/integration/groovy/BeanFactoryContextBindingCustomizer.java index efc0cbf85a..3486fe963c 100644 --- a/spring-integration-groovy/src/main/java/org/springframework/integration/groovy/BeanFactoryContextBindingCustomizer.java +++ b/spring-integration-groovy/src/main/java/org/springframework/integration/groovy/BeanFactoryContextBindingCustomizer.java @@ -22,10 +22,15 @@ import org.springframework.beans.factory.BeanFactoryAware; import org.springframework.beans.factory.ListableBeanFactory; import org.springframework.scripting.groovy.GroovyObjectCustomizer; +/** + * @author Dave Syer + * @since 2.0 + */ public class BeanFactoryContextBindingCustomizer implements GroovyObjectCustomizer, BeanFactoryAware { private ListableBeanFactory beanFactory; - + + public BeanFactoryContextBindingCustomizer() { this(null); } @@ -34,17 +39,18 @@ public class BeanFactoryContextBindingCustomizer implements GroovyObjectCustomiz setBeanFactory(beanFactory); } + public void setBeanFactory(BeanFactory beanFactory) { - this.beanFactory = beanFactory instanceof ListableBeanFactory ? (ListableBeanFactory) beanFactory : null; + this.beanFactory = (beanFactory instanceof ListableBeanFactory) ? (ListableBeanFactory) beanFactory : null; } public void customize(GroovyObject goo) { - if (beanFactory != null) { + if (this.beanFactory != null) { Binding binding = ((Script) goo).getBinding(); - for (String name : beanFactory.getBeanDefinitionNames()) { - binding.setVariable(name, beanFactory.getBean(name)); + for (String name : this.beanFactory.getBeanDefinitionNames()) { + binding.setVariable(name, this.beanFactory.getBean(name)); } } } -} \ No newline at end of file +} diff --git a/spring-integration-groovy/src/main/java/org/springframework/integration/groovy/GroovyScriptExecutingMessageProcessor.java b/spring-integration-groovy/src/main/java/org/springframework/integration/groovy/GroovyScriptExecutingMessageProcessor.java index ea447eaa7f..80a24c5cea 100644 --- a/spring-integration-groovy/src/main/java/org/springframework/integration/groovy/GroovyScriptExecutingMessageProcessor.java +++ b/spring-integration-groovy/src/main/java/org/springframework/integration/groovy/GroovyScriptExecutingMessageProcessor.java @@ -48,6 +48,11 @@ public class GroovyScriptExecutingMessageProcessor extends AbstractScriptExecuti } + @Override + protected ScriptSource getScriptSource(Message message) { + return this.scriptSource; + } + @Override protected Object executeScript(ScriptSource scriptSource, Message message) throws Exception { synchronized (this) { @@ -57,9 +62,4 @@ public class GroovyScriptExecutingMessageProcessor extends AbstractScriptExecuti } } - @Override - protected ScriptSource getScriptSource(Message message) { - return scriptSource; - } - } diff --git a/spring-integration-groovy/src/main/java/org/springframework/integration/groovy/GroovyScriptPayloadMessageProcessor.java b/spring-integration-groovy/src/main/java/org/springframework/integration/groovy/GroovyScriptPayloadMessageProcessor.java index 7241559442..8c3830897a 100644 --- a/spring-integration-groovy/src/main/java/org/springframework/integration/groovy/GroovyScriptPayloadMessageProcessor.java +++ b/spring-integration-groovy/src/main/java/org/springframework/integration/groovy/GroovyScriptPayloadMessageProcessor.java @@ -34,22 +34,24 @@ public class GroovyScriptPayloadMessageProcessor extends AbstractScriptExecuting private final GroovyObjectCustomizer customizer; + public GroovyScriptPayloadMessageProcessor() { - this((GroovyObjectCustomizer)null); + this((GroovyObjectCustomizer) null); } public GroovyScriptPayloadMessageProcessor(Map map) { this(new MapContextBindingCustomizer(map)); } - + public GroovyScriptPayloadMessageProcessor(GroovyObjectCustomizer customizer) { this.customizer = customizer; } + @Override protected ScriptSource getScriptSource(Message message) { Object payload = message.getPayload(); - Assert.isInstanceOf(String.class, payload, "Payload must be String containing Groovy script."); + Assert.isInstanceOf(String.class, payload, "Payload must be a String containing a Groovy script."); String className = generateScriptName(message); return new StaticScriptSource((String) payload, className); } @@ -63,7 +65,7 @@ public class GroovyScriptPayloadMessageProcessor extends AbstractScriptExecuting Object result = scriptFactory.getScriptedObject(scriptSource, null); return (result instanceof GString) ? result.toString() : result; } - + protected String generateScriptName(Message message) { // Don't use the same script (class) name for all invocations by default return getClass().getSimpleName() + message.getHeaders().getId().toString().replaceAll("-", ""); diff --git a/spring-integration-groovy/src/main/java/org/springframework/integration/groovy/MapContextBindingCustomizer.java b/spring-integration-groovy/src/main/java/org/springframework/integration/groovy/MapContextBindingCustomizer.java index a3a011feb4..21b26a510e 100644 --- a/spring-integration-groovy/src/main/java/org/springframework/integration/groovy/MapContextBindingCustomizer.java +++ b/spring-integration-groovy/src/main/java/org/springframework/integration/groovy/MapContextBindingCustomizer.java @@ -22,23 +22,28 @@ import java.util.Map; import org.springframework.scripting.groovy.GroovyObjectCustomizer; import org.springframework.util.Assert; +/** + * @author Dave Syer + * @since 2.0 + */ public class MapContextBindingCustomizer implements GroovyObjectCustomizer { private final Map map; + public MapContextBindingCustomizer(Map map) { this.map = map; } + public void customize(GroovyObject goo) { Assert.state(goo instanceof Script, "Expected a Script"); if (this.map != null) { Binding binding = ((Script) goo).getBinding(); - for (String key : map.keySet()) { - binding.setVariable(key, map.get(key)); + for (String key : this.map.keySet()) { + binding.setVariable(key, this.map.get(key)); } } - } -} \ No newline at end of file +} diff --git a/spring-integration-groovy/src/main/java/org/springframework/integration/groovy/MessageContextBindingCustomizer.java b/spring-integration-groovy/src/main/java/org/springframework/integration/groovy/MessageContextBindingCustomizer.java index 212c43becb..b1df0b5962 100644 --- a/spring-integration-groovy/src/main/java/org/springframework/integration/groovy/MessageContextBindingCustomizer.java +++ b/spring-integration-groovy/src/main/java/org/springframework/integration/groovy/MessageContextBindingCustomizer.java @@ -24,18 +24,20 @@ import org.springframework.scripting.groovy.GroovyObjectCustomizer; import org.springframework.util.Assert; /** - * A groovy object customizer used internally by the groovy message processors. Not public because the customizer is not - * the best API for groovy context binding, but it's what we have in Spring right now. - * - * @since 2.0 + * A groovy object customizer used internally by the groovy message processors. + * Not public because the customizer is not the best API for groovy context binding, + * but it's what we have in Spring right now. + * * @author Dave Syer - * + * @since 2.0 */ class MessageContextBindingCustomizer implements GroovyObjectCustomizer { private volatile Message message; + private final GroovyObjectCustomizer customizer; + public MessageContextBindingCustomizer() { this((GroovyObjectCustomizer) null); } @@ -48,14 +50,15 @@ class MessageContextBindingCustomizer implements GroovyObjectCustomizer { this.customizer = customizer; } + public void setMessage(Message message) { this.message = message; } public void customize(GroovyObject goo) { Assert.state(goo instanceof Script, "Expected a Script"); - if (customizer != null) { - customizer.customize(goo); + if (this.customizer != null) { + this.customizer.customize(goo); } if (this.message != null) { Binding binding = ((Script) goo).getBinding(); @@ -63,4 +66,5 @@ class MessageContextBindingCustomizer implements GroovyObjectCustomizer { binding.setVariable("headers", this.message.getHeaders()); } } -} \ No newline at end of file + +} diff --git a/spring-integration-groovy/src/main/java/org/springframework/integration/groovy/config/GroovyControlBusFactoryBean.java b/spring-integration-groovy/src/main/java/org/springframework/integration/groovy/config/GroovyControlBusFactoryBean.java index f362a6a55e..78373c1f51 100644 --- a/spring-integration-groovy/src/main/java/org/springframework/integration/groovy/config/GroovyControlBusFactoryBean.java +++ b/spring-integration-groovy/src/main/java/org/springframework/integration/groovy/config/GroovyControlBusFactoryBean.java @@ -22,24 +22,27 @@ import org.springframework.integration.handler.ServiceActivatingHandler; * FactoryBean for creating {@link MessageHandler} instances to handle a message as a Groovy Script. * * @author Dave Syer - * * @since 2.0 */ public class GroovyControlBusFactoryBean extends AbstractSimpleMessageHandlerFactoryBean { private volatile Long sendTimeout; + private final GroovyScriptPayloadMessageProcessor processor; - + + public GroovyControlBusFactoryBean(GroovyScriptPayloadMessageProcessor processor) { this.processor = processor; } + public void setSendTimeout(Long sendTimeout) { this.sendTimeout = sendTimeout; } + @Override protected MessageHandler createHandler() { - return this.configureHandler(new ServiceActivatingHandler(processor)); + return this.configureHandler(new ServiceActivatingHandler(this.processor)); } private ServiceActivatingHandler configureHandler(ServiceActivatingHandler handler) { diff --git a/spring-integration-groovy/src/main/java/org/springframework/integration/groovy/config/GroovyControlBusParser.java b/spring-integration-groovy/src/main/java/org/springframework/integration/groovy/config/GroovyControlBusParser.java index ad16732f4a..1ba9573408 100644 --- a/spring-integration-groovy/src/main/java/org/springframework/integration/groovy/config/GroovyControlBusParser.java +++ b/spring-integration-groovy/src/main/java/org/springframework/integration/groovy/config/GroovyControlBusParser.java @@ -13,16 +13,15 @@ package org.springframework.integration.groovy.config; +import org.w3c.dom.Element; + import org.springframework.beans.BeanMetadataElement; import org.springframework.beans.factory.support.BeanDefinitionBuilder; import org.springframework.beans.factory.support.RootBeanDefinition; import org.springframework.beans.factory.xml.ParserContext; import org.springframework.integration.config.xml.AbstractConsumerEndpointParser; import org.springframework.integration.config.xml.IntegrationNamespaceUtils; -import org.springframework.integration.groovy.BeanFactoryContextBindingCustomizer; -import org.springframework.integration.groovy.GroovyScriptPayloadMessageProcessor; import org.springframework.util.StringUtils; -import org.w3c.dom.Element; /** * @author Dave Syer @@ -42,13 +41,15 @@ public class GroovyControlBusParser extends AbstractConsumerEndpointParser { } protected BeanMetadataElement getMessageProcessorBeanDefinition(Element element, ParserContext parserContext) { - BeanDefinitionBuilder builder = BeanDefinitionBuilder - .genericBeanDefinition(GroovyScriptPayloadMessageProcessor.class); + BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition( + "org.springframework.integration.groovy.GroovyScriptPayloadMessageProcessor"); String customizerAttr = element.getAttribute(CUSTOMIZER_ATTRIBUTE); if (StringUtils.hasText(customizerAttr)) { builder.addConstructorArgReference(customizerAttr.trim()); - } else { - builder.addConstructorArgValue(new RootBeanDefinition(BeanFactoryContextBindingCustomizer.class)); + } + else { + builder.addConstructorArgValue(new RootBeanDefinition( + "org.springframework.integration.groovy.BeanFactoryContextBindingCustomizer")); } return builder.getBeanDefinition(); } diff --git a/spring-integration-groovy/src/main/java/org/springframework/integration/groovy/config/GroovyScriptParser.java b/spring-integration-groovy/src/main/java/org/springframework/integration/groovy/config/GroovyScriptParser.java index af6d656f09..8261a36600 100644 --- a/spring-integration-groovy/src/main/java/org/springframework/integration/groovy/config/GroovyScriptParser.java +++ b/spring-integration-groovy/src/main/java/org/springframework/integration/groovy/config/GroovyScriptParser.java @@ -33,6 +33,7 @@ import org.springframework.util.xml.DomUtils; public class GroovyScriptParser extends AbstractSingleBeanDefinitionParser { private static final String LOCATION_ATTRIBUTE = "location"; + private static final String REFRESH_CHECK_DELAY_ATTRIBUTE = "refresh-check-delay"; @@ -61,7 +62,8 @@ public class GroovyScriptParser extends AbstractSingleBeanDefinitionParser { resourceScriptSourceBuilder.addConstructorArgValue(element.getAttribute(LOCATION_ATTRIBUTE)); if (StringUtils.hasText(refreshDelayText)) { resourceScriptSourceBuilder.addConstructorArgValue(refreshDelayText); - } else { + } + else { resourceScriptSourceBuilder.addConstructorArgValue(-1L); } return resourceScriptSourceBuilder.getBeanDefinition(); diff --git a/spring-integration-groovy/src/main/java/org/springframework/integration/groovy/config/RefreshableResourceScriptSource.java b/spring-integration-groovy/src/main/java/org/springframework/integration/groovy/config/RefreshableResourceScriptSource.java index 42a576a2b2..0f2e2918c6 100644 --- a/spring-integration-groovy/src/main/java/org/springframework/integration/groovy/config/RefreshableResourceScriptSource.java +++ b/spring-integration-groovy/src/main/java/org/springframework/integration/groovy/config/RefreshableResourceScriptSource.java @@ -13,6 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.springframework.integration.groovy.config; import java.io.IOException; @@ -26,7 +27,6 @@ import org.springframework.scripting.support.ResourceScriptSource; * @author Dave Syer * @author Oleg Zhurakousky * @since 2.0 - * */ public class RefreshableResourceScriptSource implements ScriptSource { @@ -34,40 +34,41 @@ public class RefreshableResourceScriptSource implements ScriptSource { private final ResourceScriptSource source; - private AtomicLong lastModifiedChecked = new AtomicLong(System.currentTimeMillis()); + private final AtomicLong lastModifiedChecked = new AtomicLong(System.currentTimeMillis()); + + private volatile String script; - private String script; public RefreshableResourceScriptSource(Resource resource, long refreshDelay) { this.refreshDelay = refreshDelay; this.source = new ResourceScriptSource(resource); try { - this.script = source.getScriptAsString(); + this.script = this.source.getScriptAsString(); } catch (IOException e) { - lastModifiedChecked.set(0); + this.lastModifiedChecked.set(0); } } public String getScriptAsString() throws IOException { this.script = source.getScriptAsString(); - return script; + return this.script; + } + + public String suggestedClassName() { + return this.source.suggestedClassName(); } public boolean isModified() { - if (refreshDelay < 0) { + if (this.refreshDelay < 0) { return false; } long time = System.currentTimeMillis(); - if (refreshDelay == 0 || (time - lastModifiedChecked.get()) > refreshDelay) { - lastModifiedChecked.set(time); - return source.isModified(); + if (this.refreshDelay == 0 || (time - this.lastModifiedChecked.get()) > this.refreshDelay) { + this.lastModifiedChecked.set(time); + return this.source.isModified(); } return false; } - public String suggestedClassName() { - return source.suggestedClassName(); - } - } From b32fa4ac4b7fa7fd4d68710ccd20cb3eb0bb14de Mon Sep 17 00:00:00 2001 From: Oleg Zhurakousky Date: Thu, 4 Nov 2010 16:42:25 -0400 Subject: [PATCH 47/82] INT-1553 moved @Ignored test to a separate package in preparation for more tests --- .../{config => ignored}/TestReceivingUsingNamespace-context.xml | 0 .../{config => ignored}/TestReceivingUsingNamespace.java | 2 +- .../TestSendingDMsUsingNamespace-context.xml | 0 .../{config => ignored}/TestSendingDMsUsingNamespace.java | 2 +- .../TestSendingUpdatesUsingNamespace-context.xml | 0 .../{config => ignored}/TestSendingUpdatesUsingNamespace.java | 2 +- .../twitter/{config => ignored}/TwitterAnnouncer.java | 2 +- 7 files changed, 4 insertions(+), 4 deletions(-) rename spring-integration-twitter/src/test/java/org/springframework/integration/twitter/{config => ignored}/TestReceivingUsingNamespace-context.xml (100%) rename spring-integration-twitter/src/test/java/org/springframework/integration/twitter/{config => ignored}/TestReceivingUsingNamespace.java (95%) rename spring-integration-twitter/src/test/java/org/springframework/integration/twitter/{config => ignored}/TestSendingDMsUsingNamespace-context.xml (100%) rename spring-integration-twitter/src/test/java/org/springframework/integration/twitter/{config => ignored}/TestSendingDMsUsingNamespace.java (97%) rename spring-integration-twitter/src/test/java/org/springframework/integration/twitter/{config => ignored}/TestSendingUpdatesUsingNamespace-context.xml (100%) rename spring-integration-twitter/src/test/java/org/springframework/integration/twitter/{config => ignored}/TestSendingUpdatesUsingNamespace.java (97%) rename spring-integration-twitter/src/test/java/org/springframework/integration/twitter/{config => ignored}/TwitterAnnouncer.java (95%) diff --git a/spring-integration-twitter/src/test/java/org/springframework/integration/twitter/config/TestReceivingUsingNamespace-context.xml b/spring-integration-twitter/src/test/java/org/springframework/integration/twitter/ignored/TestReceivingUsingNamespace-context.xml similarity index 100% rename from spring-integration-twitter/src/test/java/org/springframework/integration/twitter/config/TestReceivingUsingNamespace-context.xml rename to spring-integration-twitter/src/test/java/org/springframework/integration/twitter/ignored/TestReceivingUsingNamespace-context.xml diff --git a/spring-integration-twitter/src/test/java/org/springframework/integration/twitter/config/TestReceivingUsingNamespace.java b/spring-integration-twitter/src/test/java/org/springframework/integration/twitter/ignored/TestReceivingUsingNamespace.java similarity index 95% rename from spring-integration-twitter/src/test/java/org/springframework/integration/twitter/config/TestReceivingUsingNamespace.java rename to spring-integration-twitter/src/test/java/org/springframework/integration/twitter/ignored/TestReceivingUsingNamespace.java index 39453be9fb..cfb80691a1 100644 --- a/spring-integration-twitter/src/test/java/org/springframework/integration/twitter/config/TestReceivingUsingNamespace.java +++ b/spring-integration-twitter/src/test/java/org/springframework/integration/twitter/ignored/TestReceivingUsingNamespace.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.springframework.integration.twitter.config; +package org.springframework.integration.twitter.ignored; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; diff --git a/spring-integration-twitter/src/test/java/org/springframework/integration/twitter/config/TestSendingDMsUsingNamespace-context.xml b/spring-integration-twitter/src/test/java/org/springframework/integration/twitter/ignored/TestSendingDMsUsingNamespace-context.xml similarity index 100% rename from spring-integration-twitter/src/test/java/org/springframework/integration/twitter/config/TestSendingDMsUsingNamespace-context.xml rename to spring-integration-twitter/src/test/java/org/springframework/integration/twitter/ignored/TestSendingDMsUsingNamespace-context.xml diff --git a/spring-integration-twitter/src/test/java/org/springframework/integration/twitter/config/TestSendingDMsUsingNamespace.java b/spring-integration-twitter/src/test/java/org/springframework/integration/twitter/ignored/TestSendingDMsUsingNamespace.java similarity index 97% rename from spring-integration-twitter/src/test/java/org/springframework/integration/twitter/config/TestSendingDMsUsingNamespace.java rename to spring-integration-twitter/src/test/java/org/springframework/integration/twitter/ignored/TestSendingDMsUsingNamespace.java index 7779966d4d..6235bc96f0 100644 --- a/spring-integration-twitter/src/test/java/org/springframework/integration/twitter/config/TestSendingDMsUsingNamespace.java +++ b/spring-integration-twitter/src/test/java/org/springframework/integration/twitter/ignored/TestSendingDMsUsingNamespace.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.springframework.integration.twitter.config; +package org.springframework.integration.twitter.ignored; import org.junit.Ignore; import org.junit.Test; diff --git a/spring-integration-twitter/src/test/java/org/springframework/integration/twitter/config/TestSendingUpdatesUsingNamespace-context.xml b/spring-integration-twitter/src/test/java/org/springframework/integration/twitter/ignored/TestSendingUpdatesUsingNamespace-context.xml similarity index 100% rename from spring-integration-twitter/src/test/java/org/springframework/integration/twitter/config/TestSendingUpdatesUsingNamespace-context.xml rename to spring-integration-twitter/src/test/java/org/springframework/integration/twitter/ignored/TestSendingUpdatesUsingNamespace-context.xml diff --git a/spring-integration-twitter/src/test/java/org/springframework/integration/twitter/config/TestSendingUpdatesUsingNamespace.java b/spring-integration-twitter/src/test/java/org/springframework/integration/twitter/ignored/TestSendingUpdatesUsingNamespace.java similarity index 97% rename from spring-integration-twitter/src/test/java/org/springframework/integration/twitter/config/TestSendingUpdatesUsingNamespace.java rename to spring-integration-twitter/src/test/java/org/springframework/integration/twitter/ignored/TestSendingUpdatesUsingNamespace.java index 1496eb92ec..841aa1924a 100644 --- a/spring-integration-twitter/src/test/java/org/springframework/integration/twitter/config/TestSendingUpdatesUsingNamespace.java +++ b/spring-integration-twitter/src/test/java/org/springframework/integration/twitter/ignored/TestSendingUpdatesUsingNamespace.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.springframework.integration.twitter.config; +package org.springframework.integration.twitter.ignored; import org.junit.Ignore; import org.junit.Test; diff --git a/spring-integration-twitter/src/test/java/org/springframework/integration/twitter/config/TwitterAnnouncer.java b/spring-integration-twitter/src/test/java/org/springframework/integration/twitter/ignored/TwitterAnnouncer.java similarity index 95% rename from spring-integration-twitter/src/test/java/org/springframework/integration/twitter/config/TwitterAnnouncer.java rename to spring-integration-twitter/src/test/java/org/springframework/integration/twitter/ignored/TwitterAnnouncer.java index db5591000b..585cb67104 100644 --- a/spring-integration-twitter/src/test/java/org/springframework/integration/twitter/config/TwitterAnnouncer.java +++ b/spring-integration-twitter/src/test/java/org/springframework/integration/twitter/ignored/TwitterAnnouncer.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.springframework.integration.twitter.config; +package org.springframework.integration.twitter.ignored; import org.springframework.stereotype.Component; From 2a215e778b3a85c5b46fb2fc07bfaf86a1b5407e Mon Sep 17 00:00:00 2001 From: Chris Beams Date: Wed, 3 Nov 2010 13:06:06 -0600 Subject: [PATCH 48/82] Remove illegal @Override annotations --- .../integration/jms/JmsMessageDrivenEndpoint.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/spring-integration-jms/src/main/java/org/springframework/integration/jms/JmsMessageDrivenEndpoint.java b/spring-integration-jms/src/main/java/org/springframework/integration/jms/JmsMessageDrivenEndpoint.java index 77c008a4ae..7cb5b91c5d 100644 --- a/spring-integration-jms/src/main/java/org/springframework/integration/jms/JmsMessageDrivenEndpoint.java +++ b/spring-integration-jms/src/main/java/org/springframework/integration/jms/JmsMessageDrivenEndpoint.java @@ -56,14 +56,12 @@ public class JmsMessageDrivenEndpoint extends AbstractEndpoint implements Dispos listener.setComponentName(this.getComponentName()); } - @Override protected void doStart() { if (!this.listenerContainer.isRunning()) { this.listenerContainer.start(); } } - @Override protected void doStop() { this.listenerContainer.stop(); } From 7ea55fdc71930b9b7f31c79afb5898e2df87c1a9 Mon Sep 17 00:00:00 2001 From: Chris Beams Date: Wed, 3 Nov 2010 12:59:33 -0600 Subject: [PATCH 49/82] Add ability to generate poms for use at build time Generate poms from Gradle metadata with `gradle generatePom` This will create a root pom with a section as well as a pom for every individual module. These poms are suitable for use with m2eclipse (e.g., File->Import-> Existing Maven project), or at the command line for basic build goals such as `mvn test`. These poms are not capable of producing distribution artifacts or deployment of artifacts. pom.xml and target will remain in .gitignore as these artifacts are transient and for developer convenience only. --- .gitignore | 1 + build.gradle | 3 + gradle/maven-deployment.gradle | 100 +++++++++++++++++++++++++++++++++ gradle/maven-root-pom.gradle | 62 ++++++++++++++++++++ 4 files changed, 166 insertions(+) create mode 100644 gradle/maven-root-pom.gradle diff --git a/.gitignore b/.gitignore index 66bb817bf3..0ba3856cb0 100644 --- a/.gitignore +++ b/.gitignore @@ -17,3 +17,4 @@ pom.xml si.java.hsp spring-integration-jms/activemq-data/ spring-integration-samples/loanshark/application.log* +target diff --git a/build.gradle b/build.gradle index 50171b85e7..73f221658b 100644 --- a/build.gradle +++ b/build.gradle @@ -263,6 +263,7 @@ project('spring-integration-jms') { description = 'Spring Integration JMS Support' dependencies { compile project(":spring-integration-core") + compile "org.springframework:spring-context:$springVersion" compile "org.springframework:spring-jms:$springVersion" compile "org.springframework:spring-tx:$springVersion" compile ("org.apache.geronimo.specs:geronimo-jms_1.1_spec:1.1") { provided = true } @@ -416,6 +417,8 @@ apply from: "$rootDir/gradle/dist.gradle" // add tasks like 'snapshotDependencyCheck' apply from: "${rootDir}/gradle/checks.gradle" +// add 'generatePom' task to generate root pom with section +apply from: "$rootDir/gradle/maven-root-pom.gradle" // ----------------------------------------------------------------------------- // Import tasks related to releasing and managing the project diff --git a/gradle/maven-deployment.gradle b/gradle/maven-deployment.gradle index 1da52540f6..d588d0ba56 100644 --- a/gradle/maven-deployment.gradle +++ b/gradle/maven-deployment.gradle @@ -123,6 +123,7 @@ uploadArchives { configurePom(deployer.pom) } + /** * Install gradle-built artifacts to the local m2 maven cache. * Further customizes the 'install' task contributed by the 'maven' plugin. @@ -134,6 +135,105 @@ install { configurePom(repositories.mavenInstaller.pom) } + +/** + * Generate a Maven pom.xml for use at build time. Dependency information will + * be based on Gradle metadata for the project, and other customizations such + * as licensing information and source compatibility settings are configured + * within. + * + * @author Chris Beams + * @see http://gradle.org/0.9-preview-3/docs/userguide/userguide_single.html#pomBuilder + */ +task generatePom { + group = 'Build' + description = 'Generates a Maven POM file suitable for use in building the project' + + generatedPomFileName = "pom.xml" + + // enable partial cleaning with `gradle cleanGeneratePom` + outputs.files(generatedPomFileName) + + doLast() { + // customize the pom creation process + p = pom { + project { + name = project.description + properties { + setProperty('project.build.sourceEncoding', 'UTF8') + } + build { + plugins { + plugin { + groupId = 'org.apache.maven.plugins' + artifactId = 'maven-compiler-plugin' + configuration { + source = '1.5' + target = '1.5' + } + } + plugin { + groupId = 'org.apache.maven.plugins' + artifactId = 'maven-surefire-plugin' + configuration { + includes { + include = '**/*Tests.java' + } + excludes { + exclude = '**/*Abstract*.java' + } + } + } + } + resources { + resource { + directory = 'src/main/java' + includes = ['**/*'] + excludes = ['**/*.java'] + } + resource { + directory = 'src/main/resources' + includes = ['**/*'] + } + } + testResources { + testResource { + directory = 'src/test/java' + includes = ['**/*'] + excludes = ['**/*.java'] + } + testResource { + directory = 'src/test/resources' + includes = ['**/*'] + } + } + } + } + } + + // customizing the artifact id is a special case that must be configured + // after the pom is fully configured, otherwise it'll be overwritten + p.whenConfigured { pom -> pom.artifactId = project.name } + + configurePom(p) + + // write the pom.xml file out to the filesystem + p.writeTo(generatedPomFileName) + } + + // ensure that pom generation happens every time resources are processed + // (which practically means any time a build happens). if the dependencies + // for the project have been updated (in $rootDir/build.gradle), the pom + // will have diffs in it and the developer will be reminded to check in + // the change during the next commit cycle. + //processResources.dependsOn generatePom +} + + +/** + * Read dynamic 'optional' and 'provided' properties from gradle dependencies + * and translate them to their maven POM equivalents. + */ def configurePom(def pom) { pom.whenConfigured { generatedPom -> def optionalDeps = configurations.testRuntime.allDependencies.findAll { gradleDep -> diff --git a/gradle/maven-root-pom.gradle b/gradle/maven-root-pom.gradle new file mode 100644 index 0000000000..d26f1402ec --- /dev/null +++ b/gradle/maven-root-pom.gradle @@ -0,0 +1,62 @@ + +/* + * Copyright 2002-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. + */ + +/** + * Generate a root Maven pom.xml for use at build time. Contains nothing other + * than a 'modules' section aggregating child projects. This pom will never be + * installed locally or deployed remotely. Child projects will not explicitly + * declare this pom as their parent, given than nothing need be inherited from + * it. + * + * @author Chris Beams + * @see maven-deployment.gradle for per-project generatePom task + */ +task generatePom { + apply plugin: 'maven' + group = 'Build' + description = 'Generates a root Maven pom for convenience.' + + generatedPomFileName = "pom.xml" + + // enable partial cleaning with `gradle cleanGeneratePom` + outputs.files(generatedPomFileName) + + doLast() { + // customize the pom creation process + p = pom { + project { + name = project.description + packaging = 'pom' + modules = javaprojects.collect { project -> project.name } + } + } + + // customizing the artifact id is a special case that must be configured + // after the pom is fully configured, otherwise it'll be overwritten + p.whenConfigured { pom -> pom.artifactId = project.name } + + // write the pom.xml file out to the filesystem + p.writeTo(generatedPomFileName) + } + + // ensure that pom generation happens every time resources are processed + // (which practically means any time a build happens). if the dependencies + // for the project have been updated (in $rootDir/build.gradle), the pom + // will have diffs in it and the developer will be reminded to check in + // the change during the next commit cycle. + //processResources.dependsOn generatePom +} From 5ab003d47ebb67f41c07c4b9014e8351903d864b Mon Sep 17 00:00:00 2001 From: Chris Beams Date: Thu, 4 Nov 2010 17:49:32 -0600 Subject: [PATCH 50/82] Explictly set root project name in settings.gradle Bamboo CI server checks out into a directory named 'checkout', instead of a directory named 'spring-integration' as would be expected. Root project naming defaults to the name of the containing directory, so it becomes important to be explicit. --- settings.gradle | 2 ++ 1 file changed, 2 insertions(+) diff --git a/settings.gradle b/settings.gradle index cbb72884fa..2a7bda9779 100644 --- a/settings.gradle +++ b/settings.gradle @@ -14,6 +14,8 @@ * limitations under the License. */ +rootProject.name = 'spring-integration' + include 'docs' include 'spring-integration-core' include 'spring-integration-event' From 2b0e34b3bcde536f7ebdff016d55974605da13fa Mon Sep 17 00:00:00 2001 From: Oleg Zhurakousky Date: Fri, 5 Nov 2010 08:43:04 -0400 Subject: [PATCH 51/82] INT-1554 polishing 1st iteration on the way to removing unnessessery Xmpp headers, removed InboundMapper dependency --- .../XmppRosterEventInboundEndpointParser.java | 2 +- ...XmppRosterEventOutboundEndpointParser.java | 2 + .../presence/XmppPresenceMessageMapper.java | 44 +++++++++---------- .../XmppRosterEventMessageDrivenEndpoint.java | 20 ++++----- .../XmppPresenceMessageMapperTests.java | 8 ---- 5 files changed, 34 insertions(+), 42 deletions(-) diff --git a/spring-integration-xmpp/src/main/java/org/springframework/integration/xmpp/config/XmppRosterEventInboundEndpointParser.java b/spring-integration-xmpp/src/main/java/org/springframework/integration/xmpp/config/XmppRosterEventInboundEndpointParser.java index 72c2478692..df9fe02e2c 100644 --- a/spring-integration-xmpp/src/main/java/org/springframework/integration/xmpp/config/XmppRosterEventInboundEndpointParser.java +++ b/spring-integration-xmpp/src/main/java/org/springframework/integration/xmpp/config/XmppRosterEventInboundEndpointParser.java @@ -32,7 +32,7 @@ public class XmppRosterEventInboundEndpointParser extends AbstractSingleBeanDefi @Override protected String getBeanClassName(Element element) { - return "org.springframework.integration.xmpp.presenceXmppRosterEventMessageDrivenEndpoint"; + return "org.springframework.integration.xmpp.presence.XmppRosterEventMessageDrivenEndpoint"; } @Override diff --git a/spring-integration-xmpp/src/main/java/org/springframework/integration/xmpp/config/XmppRosterEventOutboundEndpointParser.java b/spring-integration-xmpp/src/main/java/org/springframework/integration/xmpp/config/XmppRosterEventOutboundEndpointParser.java index 80d9f007f2..498e55ba93 100644 --- a/spring-integration-xmpp/src/main/java/org/springframework/integration/xmpp/config/XmppRosterEventOutboundEndpointParser.java +++ b/spring-integration-xmpp/src/main/java/org/springframework/integration/xmpp/config/XmppRosterEventOutboundEndpointParser.java @@ -23,6 +23,8 @@ import org.springframework.integration.config.xml.IntegrationNamespaceUtils; import org.w3c.dom.Element; /** + * Parser for 'xmpp:roster-event-outbound-channel-adapter' element + * * @author Oleg Zhurakousky * @since 2.0 */ diff --git a/spring-integration-xmpp/src/main/java/org/springframework/integration/xmpp/presence/XmppPresenceMessageMapper.java b/spring-integration-xmpp/src/main/java/org/springframework/integration/xmpp/presence/XmppPresenceMessageMapper.java index 6612887ec0..99ec16f0c3 100644 --- a/spring-integration-xmpp/src/main/java/org/springframework/integration/xmpp/presence/XmppPresenceMessageMapper.java +++ b/spring-integration-xmpp/src/main/java/org/springframework/integration/xmpp/presence/XmppPresenceMessageMapper.java @@ -18,10 +18,8 @@ package org.springframework.integration.xmpp.presence; import org.jivesoftware.smack.packet.Presence; import org.springframework.integration.Message; import org.springframework.integration.MessageHeaders; -import org.springframework.integration.mapping.InboundMessageMapper; import org.springframework.integration.mapping.MessageMappingException; import org.springframework.integration.mapping.OutboundMessageMapper; -import org.springframework.integration.support.MessageBuilder; import org.springframework.integration.xmpp.XmppHeaders; import org.springframework.util.StringUtils; @@ -34,27 +32,26 @@ import org.springframework.util.StringUtils; * @author Oleg Zhurakousky * @since 2.0 */ -public class XmppPresenceMessageMapper implements OutboundMessageMapper, - InboundMessageMapper { +public class XmppPresenceMessageMapper implements OutboundMessageMapper { - /** - * Builds {@link Message} with payload of {@link Presence} while also - * setting Presence attributes as {@link MessageHeaders} - * - * @param presence the presence object - * @return the Message - * @throws Exception thrown if conversion should fail - */ - @SuppressWarnings("unchecked") - public Message toMessage(Presence presence) throws Exception { - MessageBuilder presenceMessageBuilder = MessageBuilder.withPayload(presence); - presenceMessageBuilder.setHeader(XmppHeaders.PRESENCE_PRIORITY, presence.getPriority()); - presenceMessageBuilder.setHeader(XmppHeaders.PRESENCE_STATUS, presence.getStatus()); - presenceMessageBuilder.setHeader(XmppHeaders.PRESENCE_MODE, presence.getMode()); - presenceMessageBuilder.setHeader(XmppHeaders.PRESENCE_FROM, presence.getFrom()); - - return (Message) presenceMessageBuilder.build(); - } +// /** +// * Builds {@link Message} with payload of {@link Presence} while also +// * setting Presence attributes as {@link MessageHeaders} +// * +// * @param presence the presence object +// * @return the Message +// * @throws Exception thrown if conversion should fail +// */ +// @SuppressWarnings("unchecked") +// public Message toMessage(Presence presence) throws Exception { +// MessageBuilder presenceMessageBuilder = MessageBuilder.withPayload(presence); +// presenceMessageBuilder.setHeader(XmppHeaders.PRESENCE_PRIORITY, presence.getPriority()); +// presenceMessageBuilder.setHeader(XmppHeaders.PRESENCE_STATUS, presence.getStatus()); +// presenceMessageBuilder.setHeader(XmppHeaders.PRESENCE_MODE, presence.getMode()); +// presenceMessageBuilder.setHeader(XmppHeaders.PRESENCE_FROM, presence.getFrom()); +// +// return (Message) presenceMessageBuilder.build(); +// } /** * Builds a {@link Presence} object from the inbound Message headers, if possible. @@ -95,7 +92,8 @@ public class XmppPresenceMessageMapper implements OutboundMessageMapper messageMapper; + //private volatile InboundMessageMapper messageMapper; private final MessagingTemplate messagingTemplate = new MessagingTemplate(); @@ -75,9 +75,9 @@ public class XmppRosterEventMessageDrivenEndpoint extends AbstractEndpoint { this.requestChannel = requestChannel; } - public void setMessageMapper(InboundMessageMapper messageMapper) { - this.messageMapper = messageMapper; - } +// public void setMessageMapper(InboundMessageMapper messageMapper) { +// this.messageMapper = messageMapper; +// } @Override protected void doStart() { @@ -92,9 +92,9 @@ public class XmppRosterEventMessageDrivenEndpoint extends AbstractEndpoint { @Override protected void onInit() throws Exception { - if (null == this.messageMapper) { - this.messageMapper = new XmppPresenceMessageMapper(); - } +// if (null == this.messageMapper) { +// this.messageMapper = new XmppPresenceMessageMapper(); +// } this.messagingTemplate.setDefaultChannel(requestChannel); this.messagingTemplate.afterPropertiesSet(); this.initialized = true; @@ -106,9 +106,9 @@ public class XmppRosterEventMessageDrivenEndpoint extends AbstractEndpoint { * @param presence the {@link Presence} object representing the new state */ private void forwardRosterEventMessage(Presence presence) { - Message message = null; + Message message = null; try { - message = this.messageMapper.toMessage(presence); + message = MessageBuilder.withPayload(presence).build(); messagingTemplate.send(requestChannel, message); } catch (Exception e) { diff --git a/spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/presence/XmppPresenceMessageMapperTests.java b/spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/presence/XmppPresenceMessageMapperTests.java index 4b4bfa0b00..5514892d98 100644 --- a/spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/presence/XmppPresenceMessageMapperTests.java +++ b/spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/presence/XmppPresenceMessageMapperTests.java @@ -32,14 +32,6 @@ import org.springframework.integration.xmpp.XmppHeaders; */ public class XmppPresenceMessageMapperTests { - @Test - public void testToMessage() throws Exception{ - Presence presence = new Presence(Type.available, "Hello", 1, Mode.chat); - XmppPresenceMessageMapper mapper = new XmppPresenceMessageMapper(); - Message presenceMessage = mapper.toMessage(presence); - assertEquals(presence, presenceMessage.getPayload()); - // TODO look into why presence attributes are also duplicated as headers - } @Test public void testFromMessageWithPayloadPresence() throws Exception{ Presence presence = new Presence(Type.available, "Hello", 1, Mode.chat); From ca765c1c089d220146a9c06975dac76ae6b4336d Mon Sep 17 00:00:00 2001 From: Chris Beams Date: Fri, 5 Nov 2010 06:49:10 -0700 Subject: [PATCH 52/82] Supply ssh private key during docs upload Prior to this change, a graphical Ivy-branded authentication dialog was appearing when attepmting to scp the docs zip file to static.springframework.org. This was because the 'keyFile' property of the uploadArchives task was not being set. It is being set correctly now, based on the value of the 'sshPrivateKey' project property that must be set in gradle.properties. This value has been set on the build server's gradle.properties file, such that the INT-NIGHTLY build can succeed in pushing docs during the build. --- docs/build.gradle | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/docs/build.gradle b/docs/build.gradle index 7c35775829..8535b1c092 100644 --- a/docs/build.gradle +++ b/docs/build.gradle @@ -186,7 +186,7 @@ dependencies { scpAntTask("org.apache.ant:ant-jsch:1.8.1") } -checkForProps(taskPath: project.path + ':uploadArchives', requiredProps: ['sshHost', 'sshUsername']) +checkForProps(taskPath: project.path + ':uploadArchives', requiredProps: ['sshHost', 'sshUsername', 'sshPrivateKey']) uploadArchives { def sshHost = project.properties.sshHost @@ -206,9 +206,7 @@ uploadArchives { name = 'sshHost: ' + sshHost // used for debugging host = sshHost user = sshUsername - if (project.hasProperty('remoteSiteDir')) { - keyFile = sshPrivateKey as File - } + keyFile = sshPrivateKey as File addArtifactPattern "${remoteDocsDir}/${archive.archiveName}" } } @@ -227,7 +225,7 @@ uploadArchives { classpath: configurations.scpAntTask.asPath) // copy the archive, unpack it, then delete it - def unpackCommand = "cd ${remoteDocsDir} && unzip ${archive.archiveName}" + def unpackCommand = "cd ${remoteDocsDir} && unzip -o ${archive.archiveName}" def deleteCommand = "rm ${remoteDocsDir}/${archive.archiveName}" println "sshexec ${unpackCommand}" From e85adbba9c13333c8f9938d40819c3ed93515e46 Mon Sep 17 00:00:00 2001 From: Oleg Zhurakousky Date: Fri, 5 Nov 2010 10:42:23 -0400 Subject: [PATCH 53/82] INT-1554 removed Presence headers, Inbound/Outboound Message Mapper, fixed schema and tests --- build.gradle | 1 + .../integration/xmpp/XmppHeaders.java | 16 +-- .../xmpp/config/XmppHeaderEnricherParser.java | 8 +- ...XmppRosterEventOutboundEndpointParser.java | 2 - .../presence/XmppPresenceMessageMapper.java | 130 ------------------ .../XmppRosterEventMessageSendingHandler.java | 24 +--- .../config/spring-integration-xmpp-2.0.xsd | 16 --- .../XmppHeaderEnricherParserTests-context.xml | 6 +- .../config/XmppHeaderEnricherParserTests.java | 39 ++++-- ...boundChannelAdapterParserTests-context.xml | 7 +- ...ventOutboundChannelAdapterParserTests.java | 27 +--- .../xmpp/ignore/ConsoleChatTests-context.xml | 33 ++--- .../xmpp/ignore/ConsoleChatTests.java | 2 +- .../xmpp/ignore/XmppRosterEventConsumer.java | 14 +- .../xmpp/ignore/XmppRosterEventProducer.java | 23 ++-- .../XmppPresenceMessageMapperTests.java | 107 +++++++------- .../src/test/java/test.properties | 26 +--- 17 files changed, 127 insertions(+), 354 deletions(-) delete mode 100644 spring-integration-xmpp/src/main/java/org/springframework/integration/xmpp/presence/XmppPresenceMessageMapper.java diff --git a/build.gradle b/build.gradle index 73f221658b..25f1b5584f 100644 --- a/build.gradle +++ b/build.gradle @@ -404,6 +404,7 @@ project('spring-integration-xmpp') { compile "jivesoftware:smackx:3.1.0" compile "org.springframework:spring-context-support:$springVersion" testCompile project(":spring-integration-test") + testCompile project(":spring-integration-stream") } } diff --git a/spring-integration-xmpp/src/main/java/org/springframework/integration/xmpp/XmppHeaders.java b/spring-integration-xmpp/src/main/java/org/springframework/integration/xmpp/XmppHeaders.java index 3d9426bbba..010be8ad60 100644 --- a/spring-integration-xmpp/src/main/java/org/springframework/integration/xmpp/XmppHeaders.java +++ b/spring-integration-xmpp/src/main/java/org/springframework/integration/xmpp/XmppHeaders.java @@ -16,14 +16,13 @@ package org.springframework.integration.xmpp; import org.springframework.integration.MessageHeaders; - - /** * Used as keys for {@link org.springframework.integration.Message} objects * that handle XMPP events. * * @author Mario Gray * @author Josh Long + * @author Oleg Zhurakousky * @since 2.0 */ public class XmppHeaders { @@ -37,17 +36,4 @@ public class XmppHeaders { public static final String CHAT_THREAD_ID = PREFIX + "threadId"; public static final String TYPE = PREFIX + "type"; - - public static final String PRESENCE = PREFIX + "presence"; - - public static final String PRESENCE_LANGUAGE = PRESENCE + "language"; - - public static final String PRESENCE_PRIORITY = PRESENCE + "priority"; - - public static final String PRESENCE_MODE = PRESENCE + "mode"; - - public static final String PRESENCE_STATUS = PRESENCE + "status"; - - public static final String PRESENCE_FROM = PRESENCE + "from"; - } diff --git a/spring-integration-xmpp/src/main/java/org/springframework/integration/xmpp/config/XmppHeaderEnricherParser.java b/spring-integration-xmpp/src/main/java/org/springframework/integration/xmpp/config/XmppHeaderEnricherParser.java index 144bcc4784..3e59f171b4 100644 --- a/spring-integration-xmpp/src/main/java/org/springframework/integration/xmpp/config/XmppHeaderEnricherParser.java +++ b/spring-integration-xmpp/src/main/java/org/springframework/integration/xmpp/config/XmppHeaderEnricherParser.java @@ -15,12 +15,13 @@ */ package org.springframework.integration.xmpp.config; -import org.jivesoftware.smack.packet.Presence; import org.springframework.integration.config.xml.HeaderEnricherParserSupport; import org.springframework.integration.xmpp.XmppHeaders; /** + * Parser for 'xmpp:header-enricher' element * @author Josh Long + * @author Oleg ZHurakousky * @since 2.0 * */ @@ -32,10 +33,5 @@ public class XmppHeaderEnricherParser extends HeaderEnricherParserSupport { this.addElementToHeaderMapping("message-to", XmppHeaders.CHAT_TO_USER); this.addElementToHeaderMapping("message-thread-id", XmppHeaders.CHAT_THREAD_ID); - // presence headers - this.addElementToHeaderMapping("presence-mode", XmppHeaders.PRESENCE_MODE, Presence.Mode.class); - this.addElementToHeaderMapping("presence-from", XmppHeaders.PRESENCE_FROM); - this.addElementToHeaderMapping("presence-status", XmppHeaders.PRESENCE_STATUS); - this.addElementToHeaderMapping("presence-priority", XmppHeaders.PRESENCE_PRIORITY, Integer.class); } } diff --git a/spring-integration-xmpp/src/main/java/org/springframework/integration/xmpp/config/XmppRosterEventOutboundEndpointParser.java b/spring-integration-xmpp/src/main/java/org/springframework/integration/xmpp/config/XmppRosterEventOutboundEndpointParser.java index 498e55ba93..206f5caad5 100644 --- a/spring-integration-xmpp/src/main/java/org/springframework/integration/xmpp/config/XmppRosterEventOutboundEndpointParser.java +++ b/spring-integration-xmpp/src/main/java/org/springframework/integration/xmpp/config/XmppRosterEventOutboundEndpointParser.java @@ -19,7 +19,6 @@ import org.springframework.beans.factory.support.AbstractBeanDefinition; import org.springframework.beans.factory.support.BeanDefinitionBuilder; import org.springframework.beans.factory.xml.ParserContext; import org.springframework.integration.config.xml.AbstractOutboundChannelAdapterParser; -import org.springframework.integration.config.xml.IntegrationNamespaceUtils; import org.w3c.dom.Element; /** @@ -36,7 +35,6 @@ public class XmppRosterEventOutboundEndpointParser extends AbstractOutboundChann "org.springframework.integration.xmpp.presence.XmppRosterEventMessageSendingHandler"); String connectionName = element.getAttribute("xmpp-connection"); builder.addConstructorArgReference(connectionName); - IntegrationNamespaceUtils.setReferenceIfAttributeDefined(builder, element, "message-mapper"); return builder.getBeanDefinition(); } } diff --git a/spring-integration-xmpp/src/main/java/org/springframework/integration/xmpp/presence/XmppPresenceMessageMapper.java b/spring-integration-xmpp/src/main/java/org/springframework/integration/xmpp/presence/XmppPresenceMessageMapper.java deleted file mode 100644 index 99ec16f0c3..0000000000 --- a/spring-integration-xmpp/src/main/java/org/springframework/integration/xmpp/presence/XmppPresenceMessageMapper.java +++ /dev/null @@ -1,130 +0,0 @@ -/* - * Copyright 2002-2010 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.integration.xmpp.presence; - -import org.jivesoftware.smack.packet.Presence; -import org.springframework.integration.Message; -import org.springframework.integration.MessageHeaders; -import org.springframework.integration.mapping.MessageMappingException; -import org.springframework.integration.mapping.OutboundMessageMapper; -import org.springframework.integration.xmpp.XmppHeaders; -import org.springframework.util.StringUtils; - - -/** - * Implementation of the strategy interface {@link OutboundMessageMapper} - * which maps {@link Presence} to {@link Message} - * - * @author Josh Long - * @author Oleg Zhurakousky - * @since 2.0 - */ -public class XmppPresenceMessageMapper implements OutboundMessageMapper { - -// /** -// * Builds {@link Message} with payload of {@link Presence} while also -// * setting Presence attributes as {@link MessageHeaders} -// * -// * @param presence the presence object -// * @return the Message -// * @throws Exception thrown if conversion should fail -// */ -// @SuppressWarnings("unchecked") -// public Message toMessage(Presence presence) throws Exception { -// MessageBuilder presenceMessageBuilder = MessageBuilder.withPayload(presence); -// presenceMessageBuilder.setHeader(XmppHeaders.PRESENCE_PRIORITY, presence.getPriority()); -// presenceMessageBuilder.setHeader(XmppHeaders.PRESENCE_STATUS, presence.getStatus()); -// presenceMessageBuilder.setHeader(XmppHeaders.PRESENCE_MODE, presence.getMode()); -// presenceMessageBuilder.setHeader(XmppHeaders.PRESENCE_FROM, presence.getFrom()); -// -// return (Message) presenceMessageBuilder.build(); -// } - - /** - * Builds a {@link Presence} object from the inbound Message headers, if possible. - * - * @param message the Message whose headers and payload willl b - * @return the presence object as constructed from the {@link org.springframework.integration.Message} object - * @throws Exception if there is a problem - */ - public Presence fromMessage(Message message) throws Exception { - Object payload = message.getPayload(); - if (payload instanceof Presence) { - return (Presence) payload; - } - else if (payload instanceof Presence.Type) { - Presence.Type presenceType = (Presence.Type) payload; - MessageHeaders messageHeaders = message.getHeaders(); - - Integer priority = (Integer) messageHeaders.get(XmppHeaders.PRESENCE_PRIORITY); - String status = (String) messageHeaders.get(XmppHeaders.PRESENCE_STATUS); - String language = (String) messageHeaders.get(XmppHeaders.PRESENCE_LANGUAGE); - String from = (String) messageHeaders.get(XmppHeaders.PRESENCE_FROM); - - Object modeObj = messageHeaders.get(XmppHeaders.PRESENCE_MODE); - Presence.Mode mode = null; - - if (modeObj != null){ - if (modeObj instanceof String) { - mode = Presence.Mode.valueOf((String) modeObj); - } - else if (modeObj instanceof Presence.Mode) { - mode = (Presence.Mode) modeObj; - } - else { - throw new MessageMappingException("Unsupported type for Presence mode. Only" + - " String or Presence.Mode is allowed, but was: " + modeObj.getClass().getName()); - } - } - return this.factoryPresence(from, status, priority, presenceType, mode, language); - } - else { - throw new MessageMappingException("Unsupported Payload type. " + - "The only supported payload type is org.jivesoftware.smack.packet.Presence: " + payload.getClass().getName()); - } - } - - private Presence factoryPresence(String from, String status, Integer priority, - Presence.Type type, Presence.Mode mode, String language) { - if (null == type) { - type = Presence.Type.available; - } - - Presence presence = new Presence(type); - - if (null != priority) { - presence.setPriority(priority); - } - - if (StringUtils.hasText(status)) { - presence.setStatus(status); - } - - if (StringUtils.hasText(from)) { - presence.setFrom(from); - } - - if (null != mode) { - presence.setMode(mode); - } - - if (StringUtils.hasText(language)) { - presence.setLanguage(language); - } - - return presence; - } -} diff --git a/spring-integration-xmpp/src/main/java/org/springframework/integration/xmpp/presence/XmppRosterEventMessageSendingHandler.java b/spring-integration-xmpp/src/main/java/org/springframework/integration/xmpp/presence/XmppRosterEventMessageSendingHandler.java index 9e356ec6ad..4acc102df4 100644 --- a/spring-integration-xmpp/src/main/java/org/springframework/integration/xmpp/presence/XmppRosterEventMessageSendingHandler.java +++ b/spring-integration-xmpp/src/main/java/org/springframework/integration/xmpp/presence/XmppRosterEventMessageSendingHandler.java @@ -36,34 +36,18 @@ import org.springframework.util.Assert; */ public class XmppRosterEventMessageSendingHandler extends AbstractMessageHandler { - private OutboundMessageMapper messageMapper; - private final XMPPConnection xmppConnection; public XmppRosterEventMessageSendingHandler(XMPPConnection xmppConnection){ Assert.notNull(xmppConnection, "'xmppConnection' must not be null"); this.xmppConnection = xmppConnection; } - - /** - * the MessageMapper is responsible for converting outbound Messages into status updates of type - * {@link org.jivesoftware.smack.packet.Presence} - * - * @param messageMapper mapper for the message into a {@link Presence} instance - */ - public void setMessageMapper(OutboundMessageMapper messageMapper) { - this.messageMapper = messageMapper; - } - - protected void onInit() throws Exception { - if (this.messageMapper == null) { - this.messageMapper = new XmppPresenceMessageMapper(); - } - } @Override protected void handleMessageInternal(Message message) throws Exception { - Presence presence = this.messageMapper.fromMessage(message); - this.xmppConnection.sendPacket(presence); + Object payload = message.getPayload(); + Assert.isInstanceOf(Presence.class, payload, "'payload' must be of type 'org.jivesoftware.smack.packet.Presence', was " + + payload.getClass().getName()); + this.xmppConnection.sendPacket((Presence)payload); } } diff --git a/spring-integration-xmpp/src/main/resources/org/springframework/integration/xmpp/config/spring-integration-xmpp-2.0.xsd b/spring-integration-xmpp/src/main/resources/org/springframework/integration/xmpp/config/spring-integration-xmpp-2.0.xsd index 9fddf0bb0e..59e25d5a41 100644 --- a/spring-integration-xmpp/src/main/resources/org/springframework/integration/xmpp/config/spring-integration-xmpp-2.0.xsd +++ b/spring-integration-xmpp/src/main/resources/org/springframework/integration/xmpp/config/spring-integration-xmpp-2.0.xsd @@ -57,15 +57,6 @@ - - - - - - - - - @@ -191,15 +182,8 @@ - - - - - - - diff --git a/spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/config/XmppHeaderEnricherParserTests-context.xml b/spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/config/XmppHeaderEnricherParserTests-context.xml index 0ffe11c8c6..77bd4eac39 100644 --- a/spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/config/XmppHeaderEnricherParserTests-context.xml +++ b/spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/config/XmppHeaderEnricherParserTests-context.xml @@ -17,11 +17,7 @@ - - - - + - diff --git a/spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/config/XmppHeaderEnricherParserTests.java b/spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/config/XmppHeaderEnricherParserTests.java index 1c10639af0..d66c7e7d11 100644 --- a/spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/config/XmppHeaderEnricherParserTests.java +++ b/spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/config/XmppHeaderEnricherParserTests.java @@ -16,19 +16,25 @@ package org.springframework.integration.xmpp.config; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; +import static junit.framework.Assert.assertEquals; +import static junit.framework.Assert.assertNotNull; +import static org.mockito.Mockito.doAnswer; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; + import org.junit.Test; import org.junit.runner.RunWith; +import org.mockito.Mockito; +import org.mockito.invocation.InvocationOnMock; +import org.mockito.stubbing.Answer; import org.springframework.beans.factory.annotation.Value; import org.springframework.integration.Message; -import org.springframework.integration.MessageDeliveryException; -import org.springframework.integration.MessageHandlingException; -import org.springframework.integration.MessageRejectedException; import org.springframework.integration.channel.DirectChannel; import org.springframework.integration.core.MessageHandler; import org.springframework.integration.core.MessagingTemplate; import org.springframework.integration.support.MessageBuilder; +import org.springframework.integration.xmpp.XmppHeaders; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; @@ -41,27 +47,30 @@ import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; @RunWith(SpringJUnit4ClassRunner.class) public class XmppHeaderEnricherParserTests { - - private static final Log logger = LogFactory.getLog(XmppHeaderEnricherParserTests.class); - @Value("#{input}") private DirectChannel input; @Value("#{output}") private DirectChannel output; + @SuppressWarnings("rawtypes") @Test public void to() { MessagingTemplate messagingTemplate = new MessagingTemplate(); - output.subscribe(new MessageHandler() { - public void handleMessage(Message message) - throws MessageRejectedException, MessageHandlingException, - MessageDeliveryException { - for (String h : message.getHeaders().keySet()) - logger.debug(String.format("%s=%s (class: %s)", h, message.getHeaders().get(h), message.getHeaders().get(h).getClass().toString())); + MessageHandler handler = mock(MessageHandler.class); + doAnswer(new Answer() { + @Override + public Object answer(InvocationOnMock invocation) throws Throwable { + Message message = (Message) invocation.getArguments()[0]; + String chatToUser = (String) message.getHeaders().get(XmppHeaders.CHAT_TO_USER); + assertNotNull(chatToUser); + assertEquals("test1@example.org", chatToUser); + return null; } - }); + }).when(handler).handleMessage(Mockito.any(Message.class)); + output.subscribe(handler); messagingTemplate.send(input, MessageBuilder.withPayload("foo").build()); + verify(handler, times(1)).handleMessage(Mockito.any(Message.class)); } } diff --git a/spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/config/XmppRosterEventOutboundChannelAdapterParserTests-context.xml b/spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/config/XmppRosterEventOutboundChannelAdapterParserTests-context.xml index 02a0d3f985..53da9d7e89 100644 --- a/spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/config/XmppRosterEventOutboundChannelAdapterParserTests-context.xml +++ b/spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/config/XmppRosterEventOutboundChannelAdapterParserTests-context.xml @@ -26,12 +26,7 @@ + channel="eventChannel"/> - - - - diff --git a/spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/config/XmppRosterEventOutboundChannelAdapterParserTests.java b/spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/config/XmppRosterEventOutboundChannelAdapterParserTests.java index 576a1c2407..0129e08518 100644 --- a/spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/config/XmppRosterEventOutboundChannelAdapterParserTests.java +++ b/spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/config/XmppRosterEventOutboundChannelAdapterParserTests.java @@ -15,8 +15,6 @@ */ package org.springframework.integration.xmpp.config; -import static junit.framework.Assert.assertFalse; -import static junit.framework.Assert.assertNotNull; import static junit.framework.Assert.assertTrue; import org.junit.Test; @@ -24,10 +22,6 @@ import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import org.springframework.integration.endpoint.EventDrivenConsumer; import org.springframework.integration.endpoint.PollingConsumer; -import org.springframework.integration.mapping.OutboundMessageMapper; -import org.springframework.integration.test.util.TestUtils; -import org.springframework.integration.xmpp.presence.XmppPresenceMessageMapper; -import org.springframework.integration.xmpp.presence.XmppRosterEventMessageSendingHandler; /** * @author Oleg Zhurakousky @@ -42,29 +36,12 @@ public class XmppRosterEventOutboundChannelAdapterParserTests { Object pollingConsumer = ac.getBean("pollingOutboundRosterAdapter"); assertTrue(pollingConsumer instanceof PollingConsumer); } + @Test - @SuppressWarnings("rawtypes") - public void testRosterEventOutboundChannelAdapterParserDefaultMapper(){ - ApplicationContext ac = - new ClassPathXmlApplicationContext("XmppRosterEventOutboundChannelAdapterParserTests-context.xml", this.getClass()); - Object pollingConsumer = ac.getBean("pollingOutboundRosterAdapter"); - XmppRosterEventMessageSendingHandler handler = - TestUtils.getPropertyValue(pollingConsumer, "handler", XmppRosterEventMessageSendingHandler.class); - OutboundMessageMapper mapper = TestUtils.getPropertyValue(handler, "messageMapper", OutboundMessageMapper.class); - assertNotNull(mapper); - assertTrue(mapper instanceof XmppPresenceMessageMapper); - } - @SuppressWarnings("rawtypes") - @Test - public void testRosterEventOutboundChannelAdapterParserCustomMapperEventDriven(){ + public void testRosterEventOutboundChannelAdapterParserEventConsumer(){ ApplicationContext ac = new ClassPathXmlApplicationContext("XmppRosterEventOutboundChannelAdapterParserTests-context.xml", this.getClass()); Object eventConsumer = ac.getBean("eventOutboundRosterAdapter"); assertTrue(eventConsumer instanceof EventDrivenConsumer); - XmppRosterEventMessageSendingHandler handler = - TestUtils.getPropertyValue(eventConsumer, "handler", XmppRosterEventMessageSendingHandler.class); - OutboundMessageMapper mapper = TestUtils.getPropertyValue(handler, "messageMapper", OutboundMessageMapper.class); - assertNotNull(mapper); - assertFalse(mapper instanceof XmppPresenceMessageMapper); } } diff --git a/spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/ignore/ConsoleChatTests-context.xml b/spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/ignore/ConsoleChatTests-context.xml index ca93cc36ee..cb3e200708 100644 --- a/spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/ignore/ConsoleChatTests-context.xml +++ b/spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/ignore/ConsoleChatTests-context.xml @@ -8,33 +8,33 @@ xsi:schemaLocation="http://www.springframework.org/schema/integration http://www.springframework.org/schema/integration/spring-integration.xsd http://www.springframework.org/schema/tool http://www.springframework.org/schema/tool/spring-tool-3.0.xsd http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd - http://www.springframework.org/schema/integration/xmpp http://www.springframework.org/schema/integration/xmpp/spring-integration-xmpp.xsd + http://www.springframework.org/schema/integration/xmpp http://www.springframework.org/schema/integration/xmpp/spring-integration-xmpp-2.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.0.xsd http://www.springframework.org/schema/lang http://www.springframework.org/schema/lang/spring-lang-3.0.xsd http://www.springframework.org/schema/integration/stream http://www.springframework.org/schema/integration/stream/spring-integration-stream.xsd"> - + + user="${user.1.login}" + password="${user.1.password}" + host="${user.1.host}" + service-name="${user.1.service}"/> - - - -
- + + + + + + + + @@ -42,9 +42,4 @@ - - - - - diff --git a/spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/ignore/ConsoleChatTests.java b/spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/ignore/ConsoleChatTests.java index cdf972aee0..b75b958da2 100644 --- a/spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/ignore/ConsoleChatTests.java +++ b/spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/ignore/ConsoleChatTests.java @@ -33,7 +33,7 @@ public class ConsoleChatTests { @Test @Ignore public void run() throws Exception { - Thread.sleep(10 * 1000); + Thread.sleep(10 * 1000 * 1000); } } diff --git a/spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/ignore/XmppRosterEventConsumer.java b/spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/ignore/XmppRosterEventConsumer.java index 7049af120d..720fe4f6ac 100644 --- a/spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/ignore/XmppRosterEventConsumer.java +++ b/spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/ignore/XmppRosterEventConsumer.java @@ -33,13 +33,13 @@ public class XmppRosterEventConsumer { @ServiceActivator public void presenceChanged(Message presenceEventMsg) throws Exception { - System.out.println(StringUtils.repeat("-", 100)); - String whosePresence = (String) presenceEventMsg.getHeaders().get(XmppHeaders.PRESENCE_FROM); - System.out.println("entries affected: " + whosePresence); - MessageHeaders messageHeaders = presenceEventMsg.getHeaders(); - for (String h : messageHeaders.keySet()) { - System.out.println(String.format("%s = %s", h, messageHeaders.get(h))); - } +// System.out.println(StringUtils.repeat("-", 100)); +// String whosePresence = (String) presenceEventMsg.getHeaders().get(XmppHeaders.PRESENCE_FROM); +// System.out.println("entries affected: " + whosePresence); +// MessageHeaders messageHeaders = presenceEventMsg.getHeaders(); +// for (String h : messageHeaders.keySet()) { +// System.out.println(String.format("%s = %s", h, messageHeaders.get(h))); +// } } } diff --git a/spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/ignore/XmppRosterEventProducer.java b/spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/ignore/XmppRosterEventProducer.java index 015b582ead..d4536cf838 100644 --- a/spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/ignore/XmppRosterEventProducer.java +++ b/spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/ignore/XmppRosterEventProducer.java @@ -35,17 +35,18 @@ import org.springframework.integration.xmpp.XmppHeaders; public class XmppRosterEventProducer implements MessageSource { public Message receive() { - try { - Thread.sleep(1000 * 10); - } - catch (InterruptedException e) { - // eat it - } - return (Math.random() > .5) ? MessageBuilder.withPayload("available").setHeader( - XmppHeaders.PRESENCE_MODE, Presence.Mode.chat) - .setHeader(XmppHeaders.PRESENCE_STATUS, "She Loves me").build() - : MessageBuilder.withPayload(StringUtils.EMPTY).setHeader(XmppHeaders.PRESENCE_MODE, Presence.Mode.dnd) - .setHeader(XmppHeaders.PRESENCE_STATUS, "She Loves me not").build(); +// try { +// Thread.sleep(1000 * 10); +// } +// catch (InterruptedException e) { +// // eat it +// } +// return (Math.random() > .5) ? MessageBuilder.withPayload("available").setHeader( +// XmppHeaders.PRESENCE_MODE, Presence.Mode.chat) +// .setHeader(XmppHeaders.PRESENCE_STATUS, "She Loves me").build() +// : MessageBuilder.withPayload(StringUtils.EMPTY).setHeader(XmppHeaders.PRESENCE_MODE, Presence.Mode.dnd) +// .setHeader(XmppHeaders.PRESENCE_STATUS, "She Loves me not").build(); + return null; } } diff --git a/spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/presence/XmppPresenceMessageMapperTests.java b/spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/presence/XmppPresenceMessageMapperTests.java index 5514892d98..3abd323e5f 100644 --- a/spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/presence/XmppPresenceMessageMapperTests.java +++ b/spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/presence/XmppPresenceMessageMapperTests.java @@ -24,7 +24,6 @@ import org.junit.Test; import org.springframework.integration.Message; import org.springframework.integration.mapping.MessageMappingException; import org.springframework.integration.support.MessageBuilder; -import org.springframework.integration.xmpp.XmppHeaders; /** * @author Oleg Zhurakousky @@ -34,61 +33,61 @@ public class XmppPresenceMessageMapperTests { @Test public void testFromMessageWithPayloadPresence() throws Exception{ - Presence presence = new Presence(Type.available, "Hello", 1, Mode.chat); - Message message = MessageBuilder.withPayload(presence).build(); - XmppPresenceMessageMapper mapper = new XmppPresenceMessageMapper(); - Presence mappedPresence = mapper.fromMessage(message); - assertEquals(Mode.chat, mappedPresence.getMode()); - assertEquals(Type.available, mappedPresence.getType()); - assertEquals("Hello", mappedPresence.getStatus()); - assertEquals(1, mappedPresence.getPriority()); +// Presence presence = new Presence(Type.available, "Hello", 1, Mode.chat); +// Message message = MessageBuilder.withPayload(presence).build(); +// XmppPresenceMessageMapper mapper = new XmppPresenceMessageMapper(); +// Presence mappedPresence = mapper.fromMessage(message); +// assertEquals(Mode.chat, mappedPresence.getMode()); +// assertEquals(Type.available, mappedPresence.getType()); +// assertEquals("Hello", mappedPresence.getStatus()); +// assertEquals(1, mappedPresence.getPriority()); } - @Test - public void testFromMessageWithPayloadPresenceType() throws Exception{ - Message message = MessageBuilder.withPayload(Type.available) - .setHeader(XmppHeaders.PRESENCE_FROM, "oleg") - .setHeader(XmppHeaders.PRESENCE_MODE, Mode.chat) - .setHeader(XmppHeaders.PRESENCE_STATUS, "hello") - .setHeader(XmppHeaders.PRESENCE_PRIORITY, 1) - .build(); - XmppPresenceMessageMapper mapper = new XmppPresenceMessageMapper(); - Presence mappedPresence = mapper.fromMessage(message); - assertEquals(Mode.chat, mappedPresence.getMode()); - assertEquals(Type.available, mappedPresence.getType()); - assertEquals("hello", mappedPresence.getStatus()); - assertEquals(1, mappedPresence.getPriority()); - } - @Test - public void testFromMessageWithPayloadPresenceTypeAndStringModeType() throws Exception{ - Message message = MessageBuilder.withPayload(Type.available) - .setHeader(XmppHeaders.PRESENCE_FROM, "oleg") - .setHeader(XmppHeaders.PRESENCE_MODE, "chat") - .setHeader(XmppHeaders.PRESENCE_STATUS, "hello") - .setHeader(XmppHeaders.PRESENCE_PRIORITY, 1) - .build(); - XmppPresenceMessageMapper mapper = new XmppPresenceMessageMapper(); - Presence mappedPresence = mapper.fromMessage(message); - assertEquals(Mode.chat, mappedPresence.getMode()); - assertEquals(Type.available, mappedPresence.getType()); - assertEquals("hello", mappedPresence.getStatus()); - assertEquals(1, mappedPresence.getPriority()); - } +// @Test +// public void testFromMessageWithPayloadPresenceType() throws Exception{ +// Message message = MessageBuilder.withPayload(Type.available) +// .setHeader(XmppHeaders.PRESENCE_FROM, "oleg") +// .setHeader(XmppHeaders.PRESENCE_MODE, Mode.chat) +// .setHeader(XmppHeaders.PRESENCE_STATUS, "hello") +// .setHeader(XmppHeaders.PRESENCE_PRIORITY, 1) +// .build(); +// XmppPresenceMessageMapper mapper = new XmppPresenceMessageMapper(); +// Presence mappedPresence = mapper.fromMessage(message); +// assertEquals(Mode.chat, mappedPresence.getMode()); +// assertEquals(Type.available, mappedPresence.getType()); +// assertEquals("hello", mappedPresence.getStatus()); +// assertEquals(1, mappedPresence.getPriority()); +// } +// @Test +// public void testFromMessageWithPayloadPresenceTypeAndStringModeType() throws Exception{ +// Message message = MessageBuilder.withPayload(Type.available) +// .setHeader(XmppHeaders.PRESENCE_FROM, "oleg") +// .setHeader(XmppHeaders.PRESENCE_MODE, "chat") +// .setHeader(XmppHeaders.PRESENCE_STATUS, "hello") +// .setHeader(XmppHeaders.PRESENCE_PRIORITY, 1) +// .build(); +// XmppPresenceMessageMapper mapper = new XmppPresenceMessageMapper(); +// Presence mappedPresence = mapper.fromMessage(message); +// assertEquals(Mode.chat, mappedPresence.getMode()); +// assertEquals(Type.available, mappedPresence.getType()); +// assertEquals("hello", mappedPresence.getStatus()); +// assertEquals(1, mappedPresence.getPriority()); +// } - @Test(expected=MessageMappingException.class) - public void testFromMessageWithPayloadPresenceTypeUnsupportedMode() throws Exception{ - - Message message = MessageBuilder.withPayload(Type.available) - .setHeader(XmppHeaders.PRESENCE_MODE, 1) - .build(); - XmppPresenceMessageMapper mapper = new XmppPresenceMessageMapper(); - mapper.fromMessage(message); - } +// @Test(expected=MessageMappingException.class) +// public void testFromMessageWithPayloadPresenceTypeUnsupportedMode() throws Exception{ +// +// Message message = MessageBuilder.withPayload(Type.available) +// .setHeader(XmppHeaders.PRESENCE_MODE, 1) +// .build(); +// XmppPresenceMessageMapper mapper = new XmppPresenceMessageMapper(); +// mapper.fromMessage(message); +// } - @Test(expected=MessageMappingException.class) - public void testFromMessageWithUnsupportedPayload() throws Exception{ - Message message = MessageBuilder.withPayload("hello").build(); - XmppPresenceMessageMapper mapper = new XmppPresenceMessageMapper(); - mapper.fromMessage(message); - } +// @Test(expected=MessageMappingException.class) +// public void testFromMessageWithUnsupportedPayload() throws Exception{ +// Message message = MessageBuilder.withPayload("hello").build(); +// XmppPresenceMessageMapper mapper = new XmppPresenceMessageMapper(); +// mapper.fromMessage(message); +// } } diff --git a/spring-integration-xmpp/src/test/java/test.properties b/spring-integration-xmpp/src/test/java/test.properties index 02213f3b6d..0aaf3b43a7 100644 --- a/spring-integration-xmpp/src/test/java/test.properties +++ b/spring-integration-xmpp/src/test/java/test.properties @@ -1,24 +1,6 @@ -# -# 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. -# -# to be able to run these tests, put this file on your desktop and configure as appropriate -user.1.login=user@gmail.com +user.2.login=user1@gmail.com + +user.1.login=user2@gmail.com user.1.password=password user.1.host=talk.google.com -user.1.service=gmail.com -#user.1.sasl.mechanism=PLAIN -#user.1.sasl.index=0 -#user.1.resource=resource -#user.1.port=5222 +user.1.service=gmail.com \ No newline at end of file From a5aa8b975764882b98f692420f63002995a2cc33 Mon Sep 17 00:00:00 2001 From: Mark Fisher Date: Fri, 5 Nov 2010 10:46:33 -0400 Subject: [PATCH 54/82] moved the FeedEntryMessageSource into the 'inbound' package, and general polishing --- .../FeedInboundChannelAdapterParser.java | 2 +- .../{ => inbound}/FeedEntryMessageSource.java | 29 +++++++--- ...ChannelAdapterParserTests-file-context.xml | 4 +- ...lAdapterParserTests-file-usage-context.xml | 4 +- ...terParserTests-file-usage-noid-context.xml | 4 +- .../FeedInboundChannelAdapterParserTests.java | 2 +- .../integration/feed/config/sample.rss | 53 ------------------- .../FeedEntryMessageSourceTests.java | 3 +- .../{ => inbound}/FileUrlFeedFetcher.java | 4 +- 9 files changed, 34 insertions(+), 71 deletions(-) rename spring-integration-feed/src/main/java/org/springframework/integration/feed/{ => inbound}/FeedEntryMessageSource.java (90%) delete mode 100644 spring-integration-feed/src/test/java/org/springframework/integration/feed/config/sample.rss rename spring-integration-feed/src/test/java/org/springframework/integration/feed/{ => inbound}/FeedEntryMessageSourceTests.java (98%) rename spring-integration-feed/src/test/java/org/springframework/integration/feed/{ => inbound}/FileUrlFeedFetcher.java (97%) diff --git a/spring-integration-feed/src/main/java/org/springframework/integration/feed/config/FeedInboundChannelAdapterParser.java b/spring-integration-feed/src/main/java/org/springframework/integration/feed/config/FeedInboundChannelAdapterParser.java index 7e4b7c8ff2..c71a959827 100644 --- a/spring-integration-feed/src/main/java/org/springframework/integration/feed/config/FeedInboundChannelAdapterParser.java +++ b/spring-integration-feed/src/main/java/org/springframework/integration/feed/config/FeedInboundChannelAdapterParser.java @@ -38,7 +38,7 @@ public class FeedInboundChannelAdapterParser extends AbstractPollingInboundChann @Override protected BeanMetadataElement parseSource(final Element element, final ParserContext parserContext) { BeanDefinitionBuilder sourceBuilder = BeanDefinitionBuilder.genericBeanDefinition( - "org.springframework.integration.feed.FeedEntryMessageSource"); + "org.springframework.integration.feed.inbound.FeedEntryMessageSource"); sourceBuilder.addConstructorArgValue(element.getAttribute("url")); String feedFetcherRef = element.getAttribute("feed-fetcher"); if (StringUtils.hasText(feedFetcherRef)) { diff --git a/spring-integration-feed/src/main/java/org/springframework/integration/feed/FeedEntryMessageSource.java b/spring-integration-feed/src/main/java/org/springframework/integration/feed/inbound/FeedEntryMessageSource.java similarity index 90% rename from spring-integration-feed/src/main/java/org/springframework/integration/feed/FeedEntryMessageSource.java rename to spring-integration-feed/src/main/java/org/springframework/integration/feed/inbound/FeedEntryMessageSource.java index 102723871a..e77fe55fb4 100644 --- a/spring-integration-feed/src/main/java/org/springframework/integration/feed/FeedEntryMessageSource.java +++ b/spring-integration-feed/src/main/java/org/springframework/integration/feed/inbound/FeedEntryMessageSource.java @@ -14,11 +14,12 @@ * limitations under the License. */ -package org.springframework.integration.feed; +package org.springframework.integration.feed.inbound; import java.net.URL; import java.util.Collections; import java.util.Comparator; +import java.util.Date; import java.util.List; import java.util.Queue; import java.util.concurrent.ConcurrentLinkedQueue; @@ -73,7 +74,7 @@ public class FeedEntryMessageSource extends IntegrationObjectSupport implements private final Object monitor = new Object(); - private final Comparator syndEntryComparator = new SyndEntryComparator(); + private final Comparator syndEntryComparator = new SyndEntryPublishedDateComparator(); private final Object feedMonitor = new Object(); @@ -211,10 +212,18 @@ public class FeedEntryMessageSource extends IntegrationObjectSupport implements } - private static class SyndEntryComparator implements Comparator { + private static class SyndEntryPublishedDateComparator implements Comparator { public int compare(SyndEntry entry1, SyndEntry entry2) { - return entry1.getPublishedDate().compareTo(entry2.getPublishedDate()); + Date date1 = entry1.getPublishedDate(); + Date date2 = entry2.getPublishedDate(); + if (date1 != null && date2 != null) { + return date1.compareTo(date2); + } + if (date1 == null && date2 == null) { + return 0; + } + return (date2 == null) ? 1 : 0; } } @@ -227,14 +236,20 @@ public class FeedEntryMessageSource extends IntegrationObjectSupport implements public void fetcherEvent(final FetcherEvent event) { String eventType = event.getEventType(); if (FetcherEvent.EVENT_TYPE_FEED_POLLED.equals(eventType)) { - logger.debug("\tEVENT: Feed Polled. URL = " + event.getUrlString()); + if (logger.isDebugEnabled()) { + logger.debug("\tEVENT: Feed Polled. URL = " + event.getUrlString()); + } } else if (FetcherEvent.EVENT_TYPE_FEED_RETRIEVED.equals(eventType)) { - logger.debug("\tEVENT: Feed Retrieved. URL = " + event.getUrlString()); + if (logger.isDebugEnabled()) { + logger.debug("\tEVENT: Feed Retrieved. URL = " + event.getUrlString()); + } feeds.add(event.getFeed()); } else if (FetcherEvent.EVENT_TYPE_FEED_UNCHANGED.equals(eventType)) { - logger.debug("\tEVENT: Feed Unchanged. URL = " + event.getUrlString()); + if (logger.isDebugEnabled()) { + logger.debug("\tEVENT: Feed Unchanged. URL = " + event.getUrlString()); + } } } } diff --git a/spring-integration-feed/src/test/java/org/springframework/integration/feed/config/FeedInboundChannelAdapterParserTests-file-context.xml b/spring-integration-feed/src/test/java/org/springframework/integration/feed/config/FeedInboundChannelAdapterParserTests-file-context.xml index 176b200724..03bbec7e75 100644 --- a/spring-integration-feed/src/test/java/org/springframework/integration/feed/config/FeedInboundChannelAdapterParserTests-file-context.xml +++ b/spring-integration-feed/src/test/java/org/springframework/integration/feed/config/FeedInboundChannelAdapterParserTests-file-context.xml @@ -11,7 +11,7 @@ auto-startup="false" feed-fetcher="fileUrlFeedFetcher" metadata-store="customMetadataStore" - url="file:src/test/java/org/springframework/integration/feed/config/sample.rss"> + url="file:src/test/java/org/springframework/integration/feed/sample.rss"> @@ -19,7 +19,7 @@ - + diff --git a/spring-integration-feed/src/test/java/org/springframework/integration/feed/config/FeedInboundChannelAdapterParserTests-file-usage-context.xml b/spring-integration-feed/src/test/java/org/springframework/integration/feed/config/FeedInboundChannelAdapterParserTests-file-usage-context.xml index cd222f738f..d579ad9629 100644 --- a/spring-integration-feed/src/test/java/org/springframework/integration/feed/config/FeedInboundChannelAdapterParserTests-file-usage-context.xml +++ b/spring-integration-feed/src/test/java/org/springframework/integration/feed/config/FeedInboundChannelAdapterParserTests-file-usage-context.xml @@ -10,7 +10,7 @@ @@ -19,7 +19,7 @@ - + diff --git a/spring-integration-feed/src/test/java/org/springframework/integration/feed/config/FeedInboundChannelAdapterParserTests-file-usage-noid-context.xml b/spring-integration-feed/src/test/java/org/springframework/integration/feed/config/FeedInboundChannelAdapterParserTests-file-usage-noid-context.xml index 842246bea9..411fb567e7 100644 --- a/spring-integration-feed/src/test/java/org/springframework/integration/feed/config/FeedInboundChannelAdapterParserTests-file-usage-noid-context.xml +++ b/spring-integration-feed/src/test/java/org/springframework/integration/feed/config/FeedInboundChannelAdapterParserTests-file-usage-noid-context.xml @@ -7,7 +7,7 @@ http://www.springframework.org/schema/integration/feed http://www.springframework.org/schema/integration/feed/spring-integration-feed-2.0.xsd"> @@ -16,6 +16,6 @@ - + \ No newline at end of file diff --git a/spring-integration-feed/src/test/java/org/springframework/integration/feed/config/FeedInboundChannelAdapterParserTests.java b/spring-integration-feed/src/test/java/org/springframework/integration/feed/config/FeedInboundChannelAdapterParserTests.java index 6329d313e5..cbae2bf856 100644 --- a/spring-integration-feed/src/test/java/org/springframework/integration/feed/config/FeedInboundChannelAdapterParserTests.java +++ b/spring-integration-feed/src/test/java/org/springframework/integration/feed/config/FeedInboundChannelAdapterParserTests.java @@ -40,7 +40,7 @@ import org.springframework.integration.MessagingException; import org.springframework.integration.channel.DirectChannel; import org.springframework.integration.core.MessageHandler; import org.springframework.integration.endpoint.SourcePollingChannelAdapter; -import org.springframework.integration.feed.FeedEntryMessageSource; +import org.springframework.integration.feed.inbound.FeedEntryMessageSource; import org.springframework.integration.history.MessageHistory; import org.springframework.integration.store.MetadataStore; import org.springframework.integration.test.util.TestUtils; diff --git a/spring-integration-feed/src/test/java/org/springframework/integration/feed/config/sample.rss b/spring-integration-feed/src/test/java/org/springframework/integration/feed/config/sample.rss deleted file mode 100644 index 31fa532a39..0000000000 --- a/spring-integration-feed/src/test/java/org/springframework/integration/feed/config/sample.rss +++ /dev/null @@ -1,53 +0,0 @@ - - -Spring Integration -http://www.springsource.org/spring-integration - -Spring Integration is a really cool framework - -en-us -Copyright 2004-2010 SpringSource/VMWare -All Rights Reserved. -Tue, 12 Apr 2010 18:21:32 EST -240 - -http://www.springsource.org/sites/all/themes/dotorg09/images/dotorg09_logo.png -Spring Integration -http://www.springsource.org/spring-integration - - - - -Spring Integration adapters - -http://www.springsource.org/extensions/se-sia - -Spring Integration adapters are realy cool - -Tue, 23 Apr 2010 12:34:58 EST - - - - -Spring Integration download - -http://www.springsource.com/products/spring-community-download - -Download Spring Integration - -Sun, 13 Feb 2010 14:12:17 EST - - - - -Check out Spring Integration forums - -http://forum.springsource.org/forumdisplay.php?f=42 - -Spring Integration forums are awesome - -Wed, 13 Mar 2010 03:38:21 EST - - - - diff --git a/spring-integration-feed/src/test/java/org/springframework/integration/feed/FeedEntryMessageSourceTests.java b/spring-integration-feed/src/test/java/org/springframework/integration/feed/inbound/FeedEntryMessageSourceTests.java similarity index 98% rename from spring-integration-feed/src/test/java/org/springframework/integration/feed/FeedEntryMessageSourceTests.java rename to spring-integration-feed/src/test/java/org/springframework/integration/feed/inbound/FeedEntryMessageSourceTests.java index b9ccb2248e..2b43b0d9f5 100644 --- a/spring-integration-feed/src/test/java/org/springframework/integration/feed/FeedEntryMessageSourceTests.java +++ b/spring-integration-feed/src/test/java/org/springframework/integration/feed/inbound/FeedEntryMessageSourceTests.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.springframework.integration.feed; +package org.springframework.integration.feed.inbound; import static junit.framework.Assert.assertEquals; import static junit.framework.Assert.assertNull; @@ -27,6 +27,7 @@ import org.junit.Before; import org.junit.Test; import org.springframework.integration.Message; +import org.springframework.integration.feed.inbound.FeedEntryMessageSource; import org.springframework.integration.store.PropertiesPersistingMetadataStore; import com.sun.syndication.feed.synd.SyndEntry; diff --git a/spring-integration-feed/src/test/java/org/springframework/integration/feed/FileUrlFeedFetcher.java b/spring-integration-feed/src/test/java/org/springframework/integration/feed/inbound/FileUrlFeedFetcher.java similarity index 97% rename from spring-integration-feed/src/test/java/org/springframework/integration/feed/FileUrlFeedFetcher.java rename to spring-integration-feed/src/test/java/org/springframework/integration/feed/inbound/FileUrlFeedFetcher.java index d5a37e9305..2ef4f34b2f 100644 --- a/spring-integration-feed/src/test/java/org/springframework/integration/feed/FileUrlFeedFetcher.java +++ b/spring-integration-feed/src/test/java/org/springframework/integration/feed/inbound/FileUrlFeedFetcher.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.springframework.integration.feed; +package org.springframework.integration.feed.inbound; import java.io.BufferedInputStream; import java.io.IOException; @@ -39,7 +39,7 @@ import com.sun.syndication.io.XmlReader; * @author Mark Fisher * @since 2.0 */ -public class FileUrlFeedFetcher extends AbstractFeedFetcher { +class FileUrlFeedFetcher extends AbstractFeedFetcher { /** * Retrieve a SyndFeed for the given URL. From 43aa08958adbb4acd76c4524b2a8aaed92a15b41 Mon Sep 17 00:00:00 2001 From: Mark Fisher Date: Fri, 5 Nov 2010 11:24:22 -0400 Subject: [PATCH 55/82] avoiding chance of NPE with feed entry publishedDate --- .../feed/inbound/FeedEntryMessageSource.java | 21 +++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/spring-integration-feed/src/main/java/org/springframework/integration/feed/inbound/FeedEntryMessageSource.java b/spring-integration-feed/src/main/java/org/springframework/integration/feed/inbound/FeedEntryMessageSource.java index e77fe55fb4..44eb19cbed 100644 --- a/spring-integration-feed/src/main/java/org/springframework/integration/feed/inbound/FeedEntryMessageSource.java +++ b/spring-integration-feed/src/main/java/org/springframework/integration/feed/inbound/FeedEntryMessageSource.java @@ -168,7 +168,12 @@ public class FeedEntryMessageSource extends IntegrationObjectSupport implements if (next == null) { return null; } - this.lastTime = next.getPublishedDate().getTime(); + if (next.getPublishedDate() != null) { + this.lastTime = next.getPublishedDate().getTime(); + } + else { + this.lastTime += 1; + } this.metadataStore.put(this.metadataKey, this.lastTime + ""); return next; } @@ -179,10 +184,14 @@ public class FeedEntryMessageSource extends IntegrationObjectSupport implements if (syndFeed != null) { List retrievedEntries = (List) syndFeed.getEntries(); if (!CollectionUtils.isEmpty(retrievedEntries)) { + boolean withinNewEntries = false; Collections.sort(retrievedEntries, this.syndEntryComparator); for (SyndEntry entry : retrievedEntries) { - if (entry.getPublishedDate().getTime() > this.lastTime) { + Date entryDate = getLastModifiedDate(entry); + if ((entryDate != null && entryDate.getTime() > this.lastTime) + || (entryDate == null && withinNewEntries)) { this.entries.add(entry); + withinNewEntries = true; } } } @@ -211,12 +220,16 @@ public class FeedEntryMessageSource extends IntegrationObjectSupport implements return feed; } + private static Date getLastModifiedDate(SyndEntry entry) { + return (entry.getUpdatedDate() != null) ? entry.getUpdatedDate() : entry.getPublishedDate(); + } + private static class SyndEntryPublishedDateComparator implements Comparator { public int compare(SyndEntry entry1, SyndEntry entry2) { - Date date1 = entry1.getPublishedDate(); - Date date2 = entry2.getPublishedDate(); + Date date1 = getLastModifiedDate(entry1); + Date date2 = getLastModifiedDate(entry2); if (date1 != null && date2 != null) { return date1.compareTo(date2); } From 5946cb048beef8ea8d1adb24bb6695db7b54b2c0 Mon Sep 17 00:00:00 2001 From: Oleg Zhurakousky Date: Fri, 5 Nov 2010 11:36:10 -0400 Subject: [PATCH 56/82] INT-1554 general polishing --- .../xmpp/config/XmppConnectionParser.java | 2 ++ .../XmppRosterEventInboundEndpointParser.java | 2 ++ .../XmppRosterEventMessageDrivenEndpoint.java | 32 ++++++------------- ...RosterEventMessageDrivenEndpointTests.java | 8 ++--- 4 files changed, 17 insertions(+), 27 deletions(-) diff --git a/spring-integration-xmpp/src/main/java/org/springframework/integration/xmpp/config/XmppConnectionParser.java b/spring-integration-xmpp/src/main/java/org/springframework/integration/xmpp/config/XmppConnectionParser.java index 8c3f66cb52..372d76404e 100644 --- a/spring-integration-xmpp/src/main/java/org/springframework/integration/xmpp/config/XmppConnectionParser.java +++ b/spring-integration-xmpp/src/main/java/org/springframework/integration/xmpp/config/XmppConnectionParser.java @@ -24,6 +24,8 @@ import org.springframework.util.StringUtils; import org.w3c.dom.Element; /** + * Parser for 'xmpp:xmpp-connection' element + * * @author Oleg Zhurakousky * @since 2.0 */ diff --git a/spring-integration-xmpp/src/main/java/org/springframework/integration/xmpp/config/XmppRosterEventInboundEndpointParser.java b/spring-integration-xmpp/src/main/java/org/springframework/integration/xmpp/config/XmppRosterEventInboundEndpointParser.java index df9fe02e2c..8789072956 100644 --- a/spring-integration-xmpp/src/main/java/org/springframework/integration/xmpp/config/XmppRosterEventInboundEndpointParser.java +++ b/spring-integration-xmpp/src/main/java/org/springframework/integration/xmpp/config/XmppRosterEventInboundEndpointParser.java @@ -23,6 +23,8 @@ import org.springframework.util.Assert; import org.w3c.dom.Element; /** + * Parser for 'xmpp:roster-event-inbound-channel-adapter' element. + * * @author Josh Long * @author Oleg Zhurakousky * @since 2.0 diff --git a/spring-integration-xmpp/src/main/java/org/springframework/integration/xmpp/presence/XmppRosterEventMessageDrivenEndpoint.java b/spring-integration-xmpp/src/main/java/org/springframework/integration/xmpp/presence/XmppRosterEventMessageDrivenEndpoint.java index 4cda7eac6d..8aac117f33 100644 --- a/spring-integration-xmpp/src/main/java/org/springframework/integration/xmpp/presence/XmppRosterEventMessageDrivenEndpoint.java +++ b/spring-integration-xmpp/src/main/java/org/springframework/integration/xmpp/presence/XmppRosterEventMessageDrivenEndpoint.java @@ -49,9 +49,7 @@ public class XmppRosterEventMessageDrivenEndpoint extends AbstractEndpoint { private volatile MessageChannel requestChannel; - private volatile XMPPConnection xmppConnection; - - //private volatile InboundMessageMapper messageMapper; + private final XMPPConnection xmppConnection; private final MessagingTemplate messagingTemplate = new MessagingTemplate(); @@ -59,15 +57,9 @@ public class XmppRosterEventMessageDrivenEndpoint extends AbstractEndpoint { private volatile boolean initialized; - /** - * This will be injected or configured via a xmpp-connection-factory element. - * - * @param xmppConnection the connection - */ - public void setXmppConnection(XMPPConnection xmppConnection) { + public XmppRosterEventMessageDrivenEndpoint(XMPPConnection xmppConnection){ this.xmppConnection = xmppConnection; } - /** * @param requestChannel the channel on which the inbound message should be sent */ @@ -75,10 +67,6 @@ public class XmppRosterEventMessageDrivenEndpoint extends AbstractEndpoint { this.requestChannel = requestChannel; } -// public void setMessageMapper(InboundMessageMapper messageMapper) { -// this.messageMapper = messageMapper; -// } - @Override protected void doStart() { Assert.isTrue(this.initialized, this.getComponentType() + " must be initialized"); @@ -92,9 +80,6 @@ public class XmppRosterEventMessageDrivenEndpoint extends AbstractEndpoint { @Override protected void onInit() throws Exception { -// if (null == this.messageMapper) { -// this.messageMapper = new XmppPresenceMessageMapper(); -// } this.messagingTemplate.setDefaultChannel(requestChannel); this.messagingTemplate.afterPropertiesSet(); this.initialized = true; @@ -102,13 +87,13 @@ public class XmppRosterEventMessageDrivenEndpoint extends AbstractEndpoint { /** * Called whenever an event happens related to the {@link Roster} - * - * @param presence the {@link Presence} object representing the new state + * + * @param payload */ - private void forwardRosterEventMessage(Presence presence) { - Message message = null; + private void forwardRosterEventMessage(Object payload) { + Message message = null; try { - message = MessageBuilder.withPayload(presence).build(); + message = MessageBuilder.withPayload(payload).build(); messagingTemplate.send(requestChannel, message); } catch (Exception e) { @@ -128,14 +113,17 @@ public class XmppRosterEventMessageDrivenEndpoint extends AbstractEndpoint { class EventForwardingRosterListener implements RosterListener { public void entriesAdded(final Collection entries) { logger.debug("entries added: " + StringUtils.join(entries.iterator(), ",")); + forwardRosterEventMessage(entries); } public void entriesUpdated(final Collection entries) { logger.debug("entries updated: " + StringUtils.join(entries.iterator(), ",")); + forwardRosterEventMessage(entries); } public void entriesDeleted(final Collection entries) { logger.debug("entries deleted: " + StringUtils.join(entries.iterator(), ",")); + forwardRosterEventMessage(entries); } public void presenceChanged(final Presence presence) { diff --git a/spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/presence/XmppRosterEventMessageDrivenEndpointTests.java b/spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/presence/XmppRosterEventMessageDrivenEndpointTests.java index f3c382672a..47a08ed520 100644 --- a/spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/presence/XmppRosterEventMessageDrivenEndpointTests.java +++ b/spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/presence/XmppRosterEventMessageDrivenEndpointTests.java @@ -65,8 +65,7 @@ public class XmppRosterEventMessageDrivenEndpointTests { return null; } }).when(roster).removeRosterListener(Mockito.any(RosterListener.class)); - XmppRosterEventMessageDrivenEndpoint rosterEndpoint = new XmppRosterEventMessageDrivenEndpoint(); - rosterEndpoint.setXmppConnection(connection); + XmppRosterEventMessageDrivenEndpoint rosterEndpoint = new XmppRosterEventMessageDrivenEndpoint(connection); rosterEndpoint.afterPropertiesSet(); assertEquals(0, rosterSet.size()); rosterEndpoint.start(); @@ -77,7 +76,7 @@ public class XmppRosterEventMessageDrivenEndpointTests { @Test(expected=IllegalArgumentException.class) public void testNonInitializedFailure(){ - XmppRosterEventMessageDrivenEndpoint rosterEndpoint = new XmppRosterEventMessageDrivenEndpoint(); + XmppRosterEventMessageDrivenEndpoint rosterEndpoint = new XmppRosterEventMessageDrivenEndpoint(mock(XMPPConnection.class)); rosterEndpoint.start(); } @@ -86,8 +85,7 @@ public class XmppRosterEventMessageDrivenEndpointTests { XMPPConnection connection = mock(XMPPConnection.class); Roster roster = mock(Roster.class); when(connection.getRoster()).thenReturn(roster); - XmppRosterEventMessageDrivenEndpoint rosterEndpoint = new XmppRosterEventMessageDrivenEndpoint(); - rosterEndpoint.setXmppConnection(connection); + XmppRosterEventMessageDrivenEndpoint rosterEndpoint = new XmppRosterEventMessageDrivenEndpoint(connection); QueueChannel channel = new QueueChannel(); rosterEndpoint.setRequestChannel(channel); rosterEndpoint.afterPropertiesSet(); From cba26580636f20b101ed38618ed9b22548a90b08 Mon Sep 17 00:00:00 2001 From: Oleg Zhurakousky Date: Fri, 5 Nov 2010 12:07:51 -0400 Subject: [PATCH 57/82] INT-1554 more polishing and tests --- .../XmppMessageInboundEndpointParser.java | 5 --- .../XmppRosterEventInboundEndpointParser.java | 3 +- .../XmppRosterEventMessageDrivenEndpoint.java | 8 ++--- ...ssageDrivenEndpointParserTests-context.xml | 19 +++++++++++ ...EventMessageDrivenEndpointParserTests.java | 32 +++++++++++++++++++ .../InboundXmppEndpointTests-context.xml | 14 ++++---- ...dXmppRosterEventsEndpointTests-context.xml | 2 +- .../OutboundXmppEndpointTests-context.xml | 21 ++++-------- .../ignore/OutboundXmppEndpointTests.java | 2 +- ...RosterEventMessageDrivenEndpointTests.java | 21 +++++++++++- .../src/test/java/test.properties | 6 ++-- 11 files changed, 95 insertions(+), 38 deletions(-) create mode 100644 spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/config/XmppRosterEventMessageDrivenEndpointParserTests-context.xml create mode 100644 spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/config/XmppRosterEventMessageDrivenEndpointParserTests.java diff --git a/spring-integration-xmpp/src/main/java/org/springframework/integration/xmpp/config/XmppMessageInboundEndpointParser.java b/spring-integration-xmpp/src/main/java/org/springframework/integration/xmpp/config/XmppMessageInboundEndpointParser.java index 2542ff53ae..8b187c9858 100644 --- a/spring-integration-xmpp/src/main/java/org/springframework/integration/xmpp/config/XmppMessageInboundEndpointParser.java +++ b/spring-integration-xmpp/src/main/java/org/springframework/integration/xmpp/config/XmppMessageInboundEndpointParser.java @@ -35,11 +35,6 @@ public class XmppMessageInboundEndpointParser extends AbstractSingleBeanDefiniti return "org.springframework.integration.xmpp.messages.XmppMessageDrivenEndpoint"; } - @Override - protected boolean shouldGenerateIdAsFallback() { - return true; - } - @Override protected void doParse(Element element, ParserContext parserContext, BeanDefinitionBuilder builder) { String connectionName = element.getAttribute("xmpp-connection"); diff --git a/spring-integration-xmpp/src/main/java/org/springframework/integration/xmpp/config/XmppRosterEventInboundEndpointParser.java b/spring-integration-xmpp/src/main/java/org/springframework/integration/xmpp/config/XmppRosterEventInboundEndpointParser.java index 8789072956..6c27c84142 100644 --- a/spring-integration-xmpp/src/main/java/org/springframework/integration/xmpp/config/XmppRosterEventInboundEndpointParser.java +++ b/spring-integration-xmpp/src/main/java/org/springframework/integration/xmpp/config/XmppRosterEventInboundEndpointParser.java @@ -45,8 +45,7 @@ public class XmppRosterEventInboundEndpointParser extends AbstractSingleBeanDefi @Override protected void doParse(Element element, ParserContext parserContext, BeanDefinitionBuilder builder) { String connectionName = element.getAttribute("xmpp-connection"); - Assert.hasText(connectionName, "'xmpp-connection' must be defined"); - builder.addPropertyReference("xmppConnection", connectionName); + builder.addConstructorArgReference(connectionName); IntegrationNamespaceUtils.setReferenceIfAttributeDefined(builder, element, "channel", "requestChannel"); IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, "auto-startup"); } diff --git a/spring-integration-xmpp/src/main/java/org/springframework/integration/xmpp/presence/XmppRosterEventMessageDrivenEndpoint.java b/spring-integration-xmpp/src/main/java/org/springframework/integration/xmpp/presence/XmppRosterEventMessageDrivenEndpoint.java index 8aac117f33..40c4ae4aba 100644 --- a/spring-integration-xmpp/src/main/java/org/springframework/integration/xmpp/presence/XmppRosterEventMessageDrivenEndpoint.java +++ b/spring-integration-xmpp/src/main/java/org/springframework/integration/xmpp/presence/XmppRosterEventMessageDrivenEndpoint.java @@ -111,22 +111,22 @@ public class XmppRosterEventMessageDrivenEndpoint extends AbstractEndpoint { * and forwards them to messaging bus */ class EventForwardingRosterListener implements RosterListener { - public void entriesAdded(final Collection entries) { + public void entriesAdded(Collection entries) { logger.debug("entries added: " + StringUtils.join(entries.iterator(), ",")); forwardRosterEventMessage(entries); } - public void entriesUpdated(final Collection entries) { + public void entriesUpdated(Collection entries) { logger.debug("entries updated: " + StringUtils.join(entries.iterator(), ",")); forwardRosterEventMessage(entries); } - public void entriesDeleted(final Collection entries) { + public void entriesDeleted(Collection entries) { logger.debug("entries deleted: " + StringUtils.join(entries.iterator(), ",")); forwardRosterEventMessage(entries); } - public void presenceChanged(final Presence presence) { + public void presenceChanged(Presence presence) { logger.debug("presence changed: " + ToStringBuilder.reflectionToString(presence)); forwardRosterEventMessage(presence); } diff --git a/spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/config/XmppRosterEventMessageDrivenEndpointParserTests-context.xml b/spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/config/XmppRosterEventMessageDrivenEndpointParserTests-context.xml new file mode 100644 index 0000000000..ed31e1c71b --- /dev/null +++ b/spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/config/XmppRosterEventMessageDrivenEndpointParserTests-context.xml @@ -0,0 +1,19 @@ + + + + + + + + + + + + diff --git a/spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/config/XmppRosterEventMessageDrivenEndpointParserTests.java b/spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/config/XmppRosterEventMessageDrivenEndpointParserTests.java new file mode 100644 index 0000000000..dd9b58e58f --- /dev/null +++ b/spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/config/XmppRosterEventMessageDrivenEndpointParserTests.java @@ -0,0 +1,32 @@ +/* + * Copyright 2002-2010 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.integration.xmpp.config; + +import org.junit.Test; +import org.springframework.context.support.ClassPathXmlApplicationContext; + +/** + * @author Oleg Zhurakousky + * + */ +public class XmppRosterEventMessageDrivenEndpointParserTests { + + @Test + public void testXmppRosterEventMessageDrivenEndpointParser(){ + new ClassPathXmlApplicationContext("XmppRosterEventMessageDrivenEndpointParserTests-context.xml", this.getClass()); + // no assertion needed. THe fact that no exception was thrown satisfies this test + } +} diff --git a/spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/ignore/InboundXmppEndpointTests-context.xml b/spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/ignore/InboundXmppEndpointTests-context.xml index c2d0a86fc0..0c6ffece36 100644 --- a/spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/ignore/InboundXmppEndpointTests-context.xml +++ b/spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/ignore/InboundXmppEndpointTests-context.xml @@ -18,23 +18,23 @@ http://www.springframework.org/schema/tool http://www.springframework.org/schema/tool/spring-tool-3.0.xsd http://www.springframework.org/schema/lang http://www.springframework.org/schema/lang/spring-lang-3.0.xsd"> - - + + user="${user.1.login}" + password="${user.1.password}" + host="${user.1.host}" + service-name="${user.1.service}"/> + + diff --git a/spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/ignore/InboundXmppRosterEventsEndpointTests-context.xml b/spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/ignore/InboundXmppRosterEventsEndpointTests-context.xml index 3a02802460..cb00b2b131 100644 --- a/spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/ignore/InboundXmppRosterEventsEndpointTests-context.xml +++ b/spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/ignore/InboundXmppRosterEventsEndpointTests-context.xml @@ -19,7 +19,7 @@ - + - - - + + class="org.springframework.integration.xmpp.ignore.XmppMessageProducer" + p:recipient="${user.2.login}"/> - - + user="${user.1.login}" + password="${user.1.password}" + host="${user.1.host}" + service-name="${user.1.service}"/> diff --git a/spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/ignore/OutboundXmppEndpointTests.java b/spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/ignore/OutboundXmppEndpointTests.java index e631f0a8a6..5569e640f7 100644 --- a/spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/ignore/OutboundXmppEndpointTests.java +++ b/spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/ignore/OutboundXmppEndpointTests.java @@ -35,7 +35,7 @@ public class OutboundXmppEndpointTests { @Test @Ignore public void run() throws Exception { - Thread.sleep(10 * 1000); + Thread.sleep(10 * 1000*100); } } diff --git a/spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/presence/XmppRosterEventMessageDrivenEndpointTests.java b/spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/presence/XmppRosterEventMessageDrivenEndpointTests.java index 47a08ed520..3b44c79e77 100644 --- a/spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/presence/XmppRosterEventMessageDrivenEndpointTests.java +++ b/spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/presence/XmppRosterEventMessageDrivenEndpointTests.java @@ -20,7 +20,9 @@ import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; +import java.util.Arrays; import java.util.HashSet; +import java.util.List; import java.util.Set; import org.jivesoftware.smack.Roster; @@ -81,7 +83,7 @@ public class XmppRosterEventMessageDrivenEndpointTests { } @Test - public void testPresenceChangeEvent(){ + public void testRosterPresenceChangeEvent(){ XMPPConnection connection = mock(XMPPConnection.class); Roster roster = mock(Roster.class); when(connection.getRoster()).thenReturn(roster); @@ -96,4 +98,21 @@ public class XmppRosterEventMessageDrivenEndpointTests { Message message = channel.receive(10); assertEquals(presence, message.getPayload()); } + @SuppressWarnings({ "rawtypes", "unchecked" }) + @Test + public void testRosterEntriesEvents(){ + XMPPConnection connection = mock(XMPPConnection.class); + Roster roster = mock(Roster.class); + when(connection.getRoster()).thenReturn(roster); + XmppRosterEventMessageDrivenEndpoint rosterEndpoint = new XmppRosterEventMessageDrivenEndpoint(connection); + QueueChannel channel = new QueueChannel(); + rosterEndpoint.setRequestChannel(channel); + rosterEndpoint.afterPropertiesSet(); + rosterEndpoint.start(); + RosterListener rosterListener = (RosterListener) TestUtils.getPropertyValue(rosterEndpoint, "rosterListener"); + List entries = Arrays.asList(new String[]{"many", "moe", "jack"}); + rosterListener.entriesUpdated(entries); + Message message = channel.receive(10); + assertEquals(entries, message.getPayload()); + } } diff --git a/spring-integration-xmpp/src/test/java/test.properties b/spring-integration-xmpp/src/test/java/test.properties index 0aaf3b43a7..dbdaca6ebc 100644 --- a/spring-integration-xmpp/src/test/java/test.properties +++ b/spring-integration-xmpp/src/test/java/test.properties @@ -1,6 +1,6 @@ -user.2.login=user1@gmail.com +user.2.login=user2@gmail.com -user.1.login=user2@gmail.com -user.1.password=password +user.1.login=suser1@gmail.com +user.1.password=foo user.1.host=talk.google.com user.1.service=gmail.com \ No newline at end of file From 541370c29584ec88d3b70e8a6467e0c300452870 Mon Sep 17 00:00:00 2001 From: Chris Beams Date: Fri, 5 Nov 2010 09:31:53 -0700 Subject: [PATCH 58/82] Respect sticky/setuid bits when unzipping docs remotely The spring-integration/docs/ directory on static.springframework.org has sticky group-write permissions. unzip is now invoked with the '-K' flag to ensure that newly created directories respect these permissions. This is important to ensure that different (ssh) users can release the project without running into permissions errors. Without -K, the unzip command will preserve whatever permissions were present on the files and directories at the time of archiving, and this usually means that group-write is off. Of course, all this assumes that users doing releases are part of the same group - 'springorg' in this case. --- docs/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/build.gradle b/docs/build.gradle index 8535b1c092..9c3ea47505 100644 --- a/docs/build.gradle +++ b/docs/build.gradle @@ -225,7 +225,7 @@ uploadArchives { classpath: configurations.scpAntTask.asPath) // copy the archive, unpack it, then delete it - def unpackCommand = "cd ${remoteDocsDir} && unzip -o ${archive.archiveName}" + def unpackCommand = "cd ${remoteDocsDir} && unzip -K -o ${archive.archiveName}" def deleteCommand = "rm ${remoteDocsDir}/${archive.archiveName}" println "sshexec ${unpackCommand}" From 9271269433da8e882ad7090ffaba1c576978e623 Mon Sep 17 00:00:00 2001 From: Mark Fisher Date: Fri, 5 Nov 2010 13:22:19 -0400 Subject: [PATCH 59/82] INT-1562 moved synchronization base classes into a dedicated package --- ...actInboundRemoteFileSystemSychronizer.java | 161 --------------- ...eFileSystemSynchronizingMessageSource.java | 135 ------------- ...actInboundRemoteFileSystemSychronizer.java | 190 ++++++++++++++++++ ...eFileSystemSynchronizingMessageSource.java | 165 +++++++++++++++ ...tpInboundRemoteFileSystemSynchronizer.java | 6 +- ...eFileSystemSynchronizingMessageSource.java | 2 +- ...tpInboundRemoteFileSystemSynchronizer.java | 4 +- ...eFileSystemSynchronizingMessageSource.java | 3 +- ...oundRemoteFileSystemSynchronizerTests.java | 2 +- 9 files changed, 364 insertions(+), 304 deletions(-) delete mode 100644 spring-integration-file/src/main/java/org/springframework/integration/file/AbstractInboundRemoteFileSystemSychronizer.java delete mode 100644 spring-integration-file/src/main/java/org/springframework/integration/file/AbstractInboundRemoteFileSystemSynchronizingMessageSource.java create mode 100644 spring-integration-file/src/main/java/org/springframework/integration/file/synchronization/AbstractInboundRemoteFileSystemSychronizer.java create mode 100644 spring-integration-file/src/main/java/org/springframework/integration/file/synchronization/AbstractInboundRemoteFileSystemSynchronizingMessageSource.java diff --git a/spring-integration-file/src/main/java/org/springframework/integration/file/AbstractInboundRemoteFileSystemSychronizer.java b/spring-integration-file/src/main/java/org/springframework/integration/file/AbstractInboundRemoteFileSystemSychronizer.java deleted file mode 100644 index b560747508..0000000000 --- a/spring-integration-file/src/main/java/org/springframework/integration/file/AbstractInboundRemoteFileSystemSychronizer.java +++ /dev/null @@ -1,161 +0,0 @@ -package org.springframework.integration.file; - -import org.springframework.core.io.Resource; -import org.springframework.integration.endpoint.AbstractEndpoint; -import org.springframework.integration.file.entries.AcceptAllEntryListFilter; -import org.springframework.integration.file.entries.EntryListFilter; -import org.springframework.scheduling.Trigger; -import org.springframework.util.Assert; - -import java.util.concurrent.ScheduledFuture; - - -/** - * Strategy class charged with knowing how to connect to a remote file system, scan it for new files and then downloading the file. - *

- * The implementation should run through any configured {@link org.springframework.integration.file.entries.EntryListFilter}s - * to ensure the entry is worth downloading. - * - * @author Josh Long - */ -public abstract class AbstractInboundRemoteFileSystemSychronizer extends AbstractEndpoint { - /** - * Should we delete the source file? - * For an FTP server, for example, this would delete the original FTPFile instance - *

- * At the moment I can simply see this triggering an implementation specific {@link org.springframework.integration.file.AbstractInboundRemoteFileSystemSychronizer.EntryAcknowledgmentStrategy} - * implementation that knows how to delete an entry on the remote file system. - */ - protected boolean shouldDeleteSourceFile; - - /** - * the directory we're writing our synchronizations to - */ - protected volatile Resource localDirectory; - - /** - * a {@link org.springframework.integration.file.entries.EntryListFilter} that we're running against the remote file system view! - */ - protected volatile EntryListFilter filter = new AcceptAllEntryListFilter(); - - /** - * the {@link java.util.concurrent.ScheduledFuture} instance we get when we schedule our {@link AbstractInboundRemoteFileSystemSychronizer.SynchronizeTask} - */ - protected ScheduledFuture scheduledFuture; - - /** - * Used to store the {@link org.springframework.integration.file.AbstractInboundRemoteFileSystemSychronizer.EntryAcknowledgmentStrategy} implementation - */ - protected EntryAcknowledgmentStrategy entryAcknowledgmentStrategy; - - /** - * Obviously thread safe - simply provides a NOOP impl so we don't have to keep dancing around NPE's - */ - private EntryAcknowledgmentStrategy noOpEntryAcknowledgmentStrategy = new EntryAcknowledgmentStrategy() { - public void acknowledge(Object o, T msg) { - } - }; - - public void setEntryAcknowledgmentStrategy(EntryAcknowledgmentStrategy entryAcknowledgmentStrategy) { - this.entryAcknowledgmentStrategy = entryAcknowledgmentStrategy; - } - - public void setShouldDeleteSourceFile(boolean shouldDeleteSourceFile) { - this.shouldDeleteSourceFile = shouldDeleteSourceFile; - } - - public void setLocalDirectory(Resource localDirectory) { - this.localDirectory = localDirectory; - } - - public void setFilter(EntryListFilter filter) { - this.filter = filter; - } - - /** - * @param usefulContextOrClientData this is context information to be passed to the individual {@link org.springframework.integration.file.AbstractInboundRemoteFileSystemSychronizer.EntryAcknowledgmentStrategy} implementation. - * {@link org.springframework.integration.file.AbstractInboundRemoteFileSystemSychronizer.EntryAcknowledgmentStrategy#acknowledge(Object, Object)} will be called - * in line with the {@link org.springframework.integration.core.MessageSource#receive()} call so this could conceivably be a 'live' stateful - * client (a connection?) that is inappropriate to cache as it has per-request state. - * @param t leverages strategy implementations to enable different behavior. It's a hook to the entry ({@link T}) after it's been successfully downloaded. - * Conceptually, you might delete the remote one or rename it or something - * @throws Throwable escape hatch exception, let the adapter deal with it. - */ - protected void acknowledge(Object usefulContextOrClientData, T t) - throws Throwable { - Assert.notNull(this.entryAcknowledgmentStrategy != null, "entryAcknowledgmentStrategy can't be null!"); - this.entryAcknowledgmentStrategy.acknowledge(usefulContextOrClientData, t); - } - - /** - * This is the callback where we need the implementation to do some specific work - * - * @throws Exception thrown if anything goes wrong - */ - protected abstract void syncRemoteToLocalFileSystem() - throws Exception; - - /** - * {@inheritDoc} - */ - protected void doStop() { - Assert.notNull(this.scheduledFuture, "the 'scheduledFuture' can't be null!"); - this.scheduledFuture.cancel(true); - } - - /** - * Returns a value in millis dictating how frequently the trigger should fire - * - * @return a {@link org.springframework.scheduling.Trigger} implementation (likely, - * {@link org.springframework.scheduling.support.PeriodicTrigger}) - */ - protected abstract Trigger getTrigger(); - - /** - * {@inheritDoc} - */ - protected void doStart() { - if (this.entryAcknowledgmentStrategy == null) { - this.entryAcknowledgmentStrategy = noOpEntryAcknowledgmentStrategy; - } - - this.scheduledFuture = this.getTaskScheduler().schedule(new SynchronizeTask(), this.getTrigger()); - } - - /** - * Strategy interface to expose a hook for dispatching, moving, or deleting the file once it's been delivered. - * This will typically be a NOOP for the implementation. Adapters should (for consistency) expose an attribute - * dictating whether the adapter will delete the source entry on the remote file system. - * This is the file-system version of an ack-mode. Future implementations should consider - * exposing a custom attribute that plugs a custom {@link org.springframework.integration.file.AbstractInboundRemoteFileSystemSychronizer.EntryAcknowledgmentStrategy} - * into the pipeline and also some more advanced scenarios (i.e., 'move file to another folder on delete ', or 'rename on delete') - * - * @param the entry type (file, sftp, ftp, ...) - */ - public static interface EntryAcknowledgmentStrategy { - /** - * Semantics are simple. You get a pointer to the entry just processed and any kind of helper data you could ask for. Since the strategy is a - * singleton and the clients you might ask for as context data are pooled, it's not recommended that you try to cache them. - * - * @param useful any context data - * @param msg the data / file / entry you want to process -- specific to sublcasses - * @throws Exception thrown for any old reason - */ - void acknowledge(Object useful, T msg) throws Exception; - } - - /** - * This {@link Runnable} is launched as a background thread and is used to babysit the - * {@link org.springframework.integration.file.AbstractInboundRemoteFileSystemSychronizer#localDirectory}, - * queueing and delivering accumulated files as possible. - */ - class SynchronizeTask implements Runnable { - public void run() { - try { - syncRemoteToLocalFileSystem(); - } catch (Exception e) { - throw new RuntimeException(e); - } - } - } -} diff --git a/spring-integration-file/src/main/java/org/springframework/integration/file/AbstractInboundRemoteFileSystemSynchronizingMessageSource.java b/spring-integration-file/src/main/java/org/springframework/integration/file/AbstractInboundRemoteFileSystemSynchronizingMessageSource.java deleted file mode 100644 index 0c908a29dc..0000000000 --- a/spring-integration-file/src/main/java/org/springframework/integration/file/AbstractInboundRemoteFileSystemSynchronizingMessageSource.java +++ /dev/null @@ -1,135 +0,0 @@ -package org.springframework.integration.file; - -import org.springframework.core.io.Resource; -import org.springframework.integration.Message; -import org.springframework.integration.MessagingException; -import org.springframework.integration.core.MessageSource; -import org.springframework.integration.endpoint.AbstractEndpoint; -import org.springframework.integration.endpoint.MessageProducerSupport; -import org.springframework.integration.file.entries.*; - -import java.io.File; -import java.io.FileNotFoundException; -import java.util.Arrays; -import java.util.regex.Pattern; - - -/** - * Ultimately, this factors out a lot of the common logic between the FTP and SFTP adapters. Designed to be extendable to handle - * adapters whose task it is to synchronize a remote file system with a local file system (NB: this does *NOT* handle pushing files TO the remote - * file system that exist uniquely in the local file system. It only handles bringing down the remote file system - as you'd expect - * an 'inbound' adapter would). - *

- * The base class supports configuration of whether the remote file system and local file system's directories should - * be created on start (what 'creating a directory' means to the specific adapter is of course implementaton specific). - *

- * This class is to be used as a pair with an implementation of - * {@link org.springframework.integration.file.AbstractInboundRemoteFileSystemSychronizer}. This synchronizer - * must handle the work of actually connecting to the remote file system and delivering new {@link java.io.File}s. - * The synchronizer is designed to be - * - * @author Josh Long - */ -public abstract class AbstractInboundRemoteFileSystemSynchronizingMessageSource> extends MessageProducerSupport implements MessageSource { - /** - * Extension used when downloading files. We change it right after we know it's downloaded - */ - public static final String INCOMPLETE_EXTENSION = ".INCOMPLETE"; - - /** - * Should the endpoint attempt to create the local directory and / or the remote directory? - */ - protected volatile boolean autoCreateDirectories = true; - - /** - * An implementation that will handle the chores of actually connecting to and syncing up the remote FS with the local one, in an inbound direction - */ - protected volatile T synchronizer; - - /** - * What directory should things be synced to locally ? - */ - protected volatile Resource localDirectory; - - /** - * The actual {@link FileReadingMessageSource} that we continue to trust to do the job monitoring the filesystem once files are moved down - */ - protected volatile FileReadingMessageSource fileSource; - - /** - * The predicate to use in scanning the remote Fs for downloads - */ - protected EntryListFilter remotePredicate; - - public void setAutoCreateDirectories(boolean autoCreateDirectories) { - this.autoCreateDirectories = autoCreateDirectories; - } - - public void setSynchronizer(T synchronizer) { - this.synchronizer = synchronizer; - } - - public void setLocalDirectory(Resource localDirectory) { - this.localDirectory = localDirectory; - } - - public void setRemotePredicate(EntryListFilter remotePredicate) { - this.remotePredicate = remotePredicate; - } - - @SuppressWarnings("unchecked") - private EntryListFilter buildFilter() { - FileEntryNamer fileEntryNamer = new FileEntryNamer(); - Pattern completePattern = Pattern.compile("^.*(?( - Arrays.asList( - new AcceptOnceEntryFileListFilter(), new PatternMatchingEntryListFilter(fileEntryNamer, completePattern))); - } - - @Override - protected void onInit() { - try { - if (this.remotePredicate != null) { - this.synchronizer.setFilter(this.remotePredicate); - } - - if (this.localDirectory != null && !this.localDirectory.exists()){ - if (this.autoCreateDirectories){ - logger.debug("The '" + localDirectory + "' directory doesn't exist. Creating " + this.localDirectory); - this.localDirectory.getFile().mkdirs(); - } else { - throw new FileNotFoundException(localDirectory.getFilename()); - } - } - - /** - * Handles making sure the remote files get here in one piece - */ - this.synchronizer.setLocalDirectory(this.localDirectory); - this.synchronizer.setTaskScheduler(this.getTaskScheduler()); - this.synchronizer.setBeanFactory(this.getBeanFactory()); - this.synchronizer.setPhase(this.getPhase()); - this.synchronizer.setBeanName(this.getComponentName()); - - /** - * Handles forwarding files once they ultimately appear in the {@link #localDirectory} - */ - this.fileSource = new FileReadingMessageSource(); - this.fileSource.setFilter(buildFilter()); - this.fileSource.setDirectory(this.localDirectory.getFile()); - this.fileSource.afterPropertiesSet(); - this.synchronizer.afterPropertiesSet(); - } catch (Exception e) { - if (e instanceof RuntimeException){ - throw (RuntimeException)e; - } else { - throw new MessagingException("Failure during initialization of MessageSource for: " + this.getComponentType(), e); - } - } - - } - - public Message receive() { - return this.fileSource.receive(); - } -} diff --git a/spring-integration-file/src/main/java/org/springframework/integration/file/synchronization/AbstractInboundRemoteFileSystemSychronizer.java b/spring-integration-file/src/main/java/org/springframework/integration/file/synchronization/AbstractInboundRemoteFileSystemSychronizer.java new file mode 100644 index 0000000000..772e4ad571 --- /dev/null +++ b/spring-integration-file/src/main/java/org/springframework/integration/file/synchronization/AbstractInboundRemoteFileSystemSychronizer.java @@ -0,0 +1,190 @@ +/* + * Copyright 2002-2010 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.integration.file.synchronization; + +import org.springframework.core.io.Resource; +import org.springframework.integration.MessagingException; +import org.springframework.integration.endpoint.AbstractEndpoint; +import org.springframework.integration.file.entries.AcceptAllEntryListFilter; +import org.springframework.integration.file.entries.EntryListFilter; +import org.springframework.scheduling.Trigger; +import org.springframework.util.Assert; + +import java.util.concurrent.ScheduledFuture; + +/** + * Base class charged with knowing how to connect to a remote file system, + * scan it for new files and then download the files. + *

+ * The implementation should run through any configured + * {@link org.springframework.integration.file.entries.EntryListFilter}s to + * ensure the entry is acceptable. + * + * @author Josh Long + */ +public abstract class AbstractInboundRemoteFileSystemSychronizer extends AbstractEndpoint { + + /** + * Should we delete the source file? For an FTP + * server, for example, this would delete the original FTPFile instance. + */ + protected boolean shouldDeleteSourceFile; + + /** + * The directory to which we write our synchronizations. + */ + protected volatile Resource localDirectory; + + /** + * An {@link EntryListFilter} that runs against the remote file system view. + */ + protected volatile EntryListFilter filter = new AcceptAllEntryListFilter(); + + /** + * The {@link ScheduledFuture} instance we get when we + * schedule our {@link SynchronizeTask} + */ + protected ScheduledFuture scheduledFuture; + + /** + * The {@link EntryAcknowledgmentStrategy} implementation. + */ + protected EntryAcknowledgmentStrategy entryAcknowledgmentStrategy; + + + public void setEntryAcknowledgmentStrategy(EntryAcknowledgmentStrategy entryAcknowledgmentStrategy) { + this.entryAcknowledgmentStrategy = entryAcknowledgmentStrategy; + } + + public void setShouldDeleteSourceFile(boolean shouldDeleteSourceFile) { + this.shouldDeleteSourceFile = shouldDeleteSourceFile; + } + + public void setLocalDirectory(Resource localDirectory) { + this.localDirectory = localDirectory; + } + + public void setFilter(EntryListFilter filter) { + this.filter = filter; + } + + /** + * @param usefulContextOrClientData + * this is context information to be passed to the individual {@link EntryAcknowledgmentStrategy}. + * {@link EntryAcknowledgmentStrategy#acknowledge(Object, Object)} will be called in line with the + * {@link org.springframework.integration.core.MessageSource#receive()} call so this could conceivably + * be a 'live' stateful client (a connection?) that is inappropriate to cache as it has per-request state. + * @param t + * leverages strategy implementations to enable different + * behavior. It's a hook to the entry ({@link T}) after it's been + * successfully downloaded. Conceptually, you might delete the + * remote one or rename it, etc. + * @throws Throwable + * escape hatch exception, let the adapter deal with it. + */ + protected void acknowledge(Object usefulContextOrClientData, T t) throws Throwable { + Assert.notNull(this.entryAcknowledgmentStrategy != null, + "entryAcknowledgmentStrategy can't be null!"); + this.entryAcknowledgmentStrategy.acknowledge(usefulContextOrClientData, t); + } + + /** + * {@inheritDoc} + */ + protected void doStart() { + if (this.entryAcknowledgmentStrategy == null) { + this.entryAcknowledgmentStrategy = new EntryAcknowledgmentStrategy() { + public void acknowledge(Object o, T msg) { + // no-op + } + }; + } + this.scheduledFuture = this.getTaskScheduler().schedule(new SynchronizeTask(), this.getTrigger()); + } + + /** + * {@inheritDoc} + */ + protected void doStop() { + if (this.scheduledFuture != null) { + this.scheduledFuture.cancel(true); + } + } + + /** + * Returns the {@link Trigger} that dictates how frequently the trigger should fire. + */ + protected abstract Trigger getTrigger(); + + /** + * This is the callback where we need the implementation to do some specific work + */ + protected abstract void syncRemoteToLocalFileSystem() throws Exception; + + + /** + * This {@link Runnable} is launched as a background thread and is used to manage the + * {@link AbstractInboundRemoteFileSystemSychronizer#localDirectory} by queueing and + * delivering accumulated files as possible. + */ + class SynchronizeTask implements Runnable { + public void run() { + try { + syncRemoteToLocalFileSystem(); + } + catch (RuntimeException e) { + throw e; + } + catch (Exception e) { + throw new MessagingException("failure occurred in synchronization task", e); + } + } + } + + + /** + * Strategy interface to expose a hook for dispatching, moving, or deleting + * the file once it has been delivered. This will typically be a NOOP for the + * implementation. Adapters should (for consistency) expose an attribute + * dictating whether the adapter will delete the source + * entry on the remote file system. This is the file-system version of an + * ack-mode. Future implementations should consider exposing a + * custom attribute that plugs a custom {@link EntryAcknowledgmentStrategy} + * into the pipeline and also some more advanced scenarios (i.e., 'move file + * to another folder on delete ', or 'rename on delete') + * + * @param the entry type (file, sftp, ftp, ...) + */ + public static interface EntryAcknowledgmentStrategy { + + /** + * Semantics are simple. You get a pointer to the entry just processed + * and any kind of helper data you could ask for. Since the strategy is + * a singleton and the clients you might ask for as context data are + * pooled, it's not recommended that you try to cache them. + * + * @param useful + * any context data + * @param msg + * the data / file / entry you want to process -- specific to subclasses + * @throws Exception in case of an error while acknowledging + */ + void acknowledge(Object useful, T msg) throws Exception; + + } + +} diff --git a/spring-integration-file/src/main/java/org/springframework/integration/file/synchronization/AbstractInboundRemoteFileSystemSynchronizingMessageSource.java b/spring-integration-file/src/main/java/org/springframework/integration/file/synchronization/AbstractInboundRemoteFileSystemSynchronizingMessageSource.java new file mode 100644 index 0000000000..45896881e5 --- /dev/null +++ b/spring-integration-file/src/main/java/org/springframework/integration/file/synchronization/AbstractInboundRemoteFileSystemSynchronizingMessageSource.java @@ -0,0 +1,165 @@ +/* + * Copyright 2002-2010 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.integration.file.synchronization; + +import java.io.File; +import java.io.FileNotFoundException; +import java.util.Arrays; +import java.util.regex.Pattern; + +import org.springframework.core.io.Resource; +import org.springframework.integration.Message; +import org.springframework.integration.MessagingException; +import org.springframework.integration.core.MessageSource; +import org.springframework.integration.endpoint.MessageProducerSupport; +import org.springframework.integration.file.FileReadingMessageSource; +import org.springframework.integration.file.entries.AcceptOnceEntryFileListFilter; +import org.springframework.integration.file.entries.CompositeEntryListFilter; +import org.springframework.integration.file.entries.EntryListFilter; +import org.springframework.integration.file.entries.FileEntryNamer; +import org.springframework.integration.file.entries.PatternMatchingEntryListFilter; + +/** + * Factors out the common logic between the FTP and SFTP adapters. Designed to + * be extensible to handle adapters whose task it is to synchronize a remote + * file system with a local file system (NB: this does *NOT* handle pushing + * files TO the remote file system that exist uniquely in the local file system. + * It only handles pulling from the remote file system - as you would expect + * from an 'inbound' adapter). + *

+ * The base class supports configuration of whether the remote file system and + * local file system's directories should be created on start (what 'creating a + * directory' means to the specific adapter is of course implementaton + * specific). + *

+ * This class is to be used as a pair with an implementation of + * {@link AbstractInboundRemoteFileSystemSychronizer}. The synchronizer must + * handle the work of actually connecting to the remote file system and + * delivering new {@link File}s. + * + * @author Josh Long + */ +public abstract class AbstractInboundRemoteFileSystemSynchronizingMessageSource> + extends MessageProducerSupport implements MessageSource { + + /** + * Extension used when downloading files. We change it right after we know it's downloaded. + */ + public static final String INCOMPLETE_EXTENSION = ".INCOMPLETE"; + + /** + * Should the endpoint attempt to create the local directory and/or the remote directory? + */ + protected volatile boolean autoCreateDirectories = true; + + /** + * An implementation that will handle the chores of actually connecting to and synching up + * the remote file system with the local one, in an inbound direction. + */ + protected volatile T synchronizer; + + /** + * Directory to which things should be synched locally. + */ + protected volatile Resource localDirectory; + + /** + * The actual {@link FileReadingMessageSource} that monitors the local filesystem once files are synched. + */ + protected volatile FileReadingMessageSource fileSource; + + /** + * The predicate to use in scanning the remote File system for downloads. + */ + protected EntryListFilter remotePredicate; + + + public void setAutoCreateDirectories(boolean autoCreateDirectories) { + this.autoCreateDirectories = autoCreateDirectories; + } + + public void setSynchronizer(T synchronizer) { + this.synchronizer = synchronizer; + } + + public void setLocalDirectory(Resource localDirectory) { + this.localDirectory = localDirectory; + } + + public void setRemotePredicate(EntryListFilter remotePredicate) { + this.remotePredicate = remotePredicate; + } + + @Override + protected void onInit() { + try { + if (this.remotePredicate != null) { + this.synchronizer.setFilter(this.remotePredicate); + } + if (this.localDirectory != null && !this.localDirectory.exists()) { + if (this.autoCreateDirectories) { + if (logger.isDebugEnabled()) { + logger.debug("The '" + this.localDirectory + "' directory doesn't exist; Will create."); + } + this.localDirectory.getFile().mkdirs(); + } + else { + throw new FileNotFoundException(this.localDirectory.getFilename()); + } + } + + /** + * Make sure the remote files get here. + */ + this.synchronizer.setLocalDirectory(this.localDirectory); + this.synchronizer.setTaskScheduler(this.getTaskScheduler()); + this.synchronizer.setBeanFactory(this.getBeanFactory()); + this.synchronizer.setPhase(this.getPhase()); + this.synchronizer.setBeanName(this.getComponentName()); + + /** + * Forwards files once they ultimately appear in the {@link #localDirectory}. + */ + this.fileSource = new FileReadingMessageSource(); + this.fileSource.setFilter(this.buildFilter()); + this.fileSource.setDirectory(this.localDirectory.getFile()); + this.fileSource.afterPropertiesSet(); + this.synchronizer.afterPropertiesSet(); + } + catch (RuntimeException e) { + throw e; + } + catch (Exception e) { + throw new MessagingException("Failure during initialization of MessageSource for: " + + this.getComponentType(), e); + } + } + + public Message receive() { + return this.fileSource.receive(); + } + + @SuppressWarnings("unchecked") + private EntryListFilter buildFilter() { + FileEntryNamer fileEntryNamer = new FileEntryNamer(); + Pattern completePattern = Pattern.compile("^.*(?(Arrays.asList( + new AcceptOnceEntryFileListFilter(), + new PatternMatchingEntryListFilter(fileEntryNamer, completePattern))); + } + +} diff --git a/spring-integration-ftp/src/main/java/org/springframework/integration/ftp/FtpInboundRemoteFileSystemSynchronizer.java b/spring-integration-ftp/src/main/java/org/springframework/integration/ftp/FtpInboundRemoteFileSystemSynchronizer.java index ca49d602a0..1ae78b1254 100644 --- a/spring-integration-ftp/src/main/java/org/springframework/integration/ftp/FtpInboundRemoteFileSystemSynchronizer.java +++ b/spring-integration-ftp/src/main/java/org/springframework/integration/ftp/FtpInboundRemoteFileSystemSynchronizer.java @@ -20,8 +20,8 @@ import org.apache.commons.net.ftp.FTPClient; import org.apache.commons.net.ftp.FTPFile; import org.springframework.core.io.Resource; import org.springframework.integration.MessagingException; -import org.springframework.integration.file.AbstractInboundRemoteFileSystemSychronizer; -import org.springframework.integration.file.AbstractInboundRemoteFileSystemSynchronizingMessageSource; +import org.springframework.integration.file.synchronization.AbstractInboundRemoteFileSystemSychronizer; +import org.springframework.integration.file.synchronization.AbstractInboundRemoteFileSystemSynchronizingMessageSource; import org.springframework.integration.ftp.FtpClientPool; import org.springframework.scheduling.Trigger; import org.springframework.scheduling.support.PeriodicTrigger; @@ -34,7 +34,7 @@ import java.io.IOException; import java.util.Collection; /** - * An FTP-adapter implementation of {@link org.springframework.integration.file.AbstractInboundRemoteFileSystemSychronizer} + * An FTP-adapter implementation of {@link org.springframework.integration.file.synchronization.AbstractInboundRemoteFileSystemSychronizer} * * @author Iwein Fuld * @author Josh Long diff --git a/spring-integration-ftp/src/main/java/org/springframework/integration/ftp/FtpInboundRemoteFileSystemSynchronizingMessageSource.java b/spring-integration-ftp/src/main/java/org/springframework/integration/ftp/FtpInboundRemoteFileSystemSynchronizingMessageSource.java index 3494d98703..9b48d4e055 100644 --- a/spring-integration-ftp/src/main/java/org/springframework/integration/ftp/FtpInboundRemoteFileSystemSynchronizingMessageSource.java +++ b/spring-integration-ftp/src/main/java/org/springframework/integration/ftp/FtpInboundRemoteFileSystemSynchronizingMessageSource.java @@ -18,7 +18,7 @@ package org.springframework.integration.ftp; import org.apache.commons.net.ftp.FTPFile; -import org.springframework.integration.file.AbstractInboundRemoteFileSystemSynchronizingMessageSource; +import org.springframework.integration.file.synchronization.AbstractInboundRemoteFileSystemSynchronizingMessageSource; /** * A {@link org.springframework.integration.core.MessageSource} implementation for FTP. diff --git a/spring-integration-sftp/src/main/java/org/springframework/integration/sftp/impl/SftpInboundRemoteFileSystemSynchronizer.java b/spring-integration-sftp/src/main/java/org/springframework/integration/sftp/impl/SftpInboundRemoteFileSystemSynchronizer.java index 2c922976db..cde8fbacbc 100644 --- a/spring-integration-sftp/src/main/java/org/springframework/integration/sftp/impl/SftpInboundRemoteFileSystemSynchronizer.java +++ b/spring-integration-sftp/src/main/java/org/springframework/integration/sftp/impl/SftpInboundRemoteFileSystemSynchronizer.java @@ -21,8 +21,8 @@ import org.apache.commons.io.IOUtils; import org.springframework.beans.factory.annotation.Required; import org.springframework.core.io.Resource; import org.springframework.integration.MessagingException; -import org.springframework.integration.file.AbstractInboundRemoteFileSystemSychronizer; -import org.springframework.integration.file.AbstractInboundRemoteFileSystemSynchronizingMessageSource; +import org.springframework.integration.file.synchronization.AbstractInboundRemoteFileSystemSychronizer; +import org.springframework.integration.file.synchronization.AbstractInboundRemoteFileSystemSynchronizingMessageSource; import org.springframework.integration.sftp.SftpSession; import org.springframework.integration.sftp.SftpSessionPool; import org.springframework.scheduling.Trigger; diff --git a/spring-integration-sftp/src/main/java/org/springframework/integration/sftp/impl/SftpInboundRemoteFileSystemSynchronizingMessageSource.java b/spring-integration-sftp/src/main/java/org/springframework/integration/sftp/impl/SftpInboundRemoteFileSystemSynchronizingMessageSource.java index 73632b7c3c..180f5ba07f 100644 --- a/spring-integration-sftp/src/main/java/org/springframework/integration/sftp/impl/SftpInboundRemoteFileSystemSynchronizingMessageSource.java +++ b/spring-integration-sftp/src/main/java/org/springframework/integration/sftp/impl/SftpInboundRemoteFileSystemSynchronizingMessageSource.java @@ -17,7 +17,8 @@ package org.springframework.integration.sftp.impl; import com.jcraft.jsch.ChannelSftp; import com.jcraft.jsch.SftpATTRS; -import org.springframework.integration.file.AbstractInboundRemoteFileSystemSynchronizingMessageSource; + +import org.springframework.integration.file.synchronization.AbstractInboundRemoteFileSystemSynchronizingMessageSource; import org.springframework.integration.sftp.SftpSession; import org.springframework.integration.sftp.SftpSessionPool; import org.springframework.util.Assert; diff --git a/spring-integration-sftp/src/test/java/org/springframework/integration/sftp/impl/SftpInboundRemoteFileSystemSynchronizerTests.java b/spring-integration-sftp/src/test/java/org/springframework/integration/sftp/impl/SftpInboundRemoteFileSystemSynchronizerTests.java index 1c5eb5e876..9f0107ab00 100644 --- a/spring-integration-sftp/src/test/java/org/springframework/integration/sftp/impl/SftpInboundRemoteFileSystemSynchronizerTests.java +++ b/spring-integration-sftp/src/test/java/org/springframework/integration/sftp/impl/SftpInboundRemoteFileSystemSynchronizerTests.java @@ -25,7 +25,7 @@ import org.junit.Before; import org.junit.Test; import org.springframework.core.io.FileSystemResource; import org.springframework.core.io.Resource; -import org.springframework.integration.file.AbstractInboundRemoteFileSystemSychronizer.EntryAcknowledgmentStrategy; +import org.springframework.integration.file.synchronization.AbstractInboundRemoteFileSystemSychronizer.EntryAcknowledgmentStrategy; import org.springframework.integration.sftp.SftpSession; import org.springframework.util.ReflectionUtils; From 225a4a3322251235048843c902776c67c53f8e86 Mon Sep 17 00:00:00 2001 From: Oleg Zhurakousky Date: Fri, 5 Nov 2010 13:22:39 -0400 Subject: [PATCH 60/82] INT-1554 final polishing --- .../OutboundXmppEndpointTests-context.xml | 9 +++-- ...dXmppRosterEventsEndpointTests-context.xml | 35 ++++--------------- .../src/test/java/test.properties | 6 ++-- 3 files changed, 13 insertions(+), 37 deletions(-) diff --git a/spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/ignore/OutboundXmppEndpointTests-context.xml b/spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/ignore/OutboundXmppEndpointTests-context.xml index b418821d1c..5d329251c3 100644 --- a/spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/ignore/OutboundXmppEndpointTests-context.xml +++ b/spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/ignore/OutboundXmppEndpointTests-context.xml @@ -6,7 +6,7 @@ xmlns:tool="http://www.springframework.org/schema/tool" xmlns:lang="http://www.springframework.org/schema/lang" xsi:schemaLocation="http://www.springframework.org/schema/integration/xmpp http://www.springframework.org/schema/integration/xmpp/spring-integration-xmpp.xsd http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd - http://www.springframework.org/schema/integration http://www.springframework.org/schema/integration/spring-integration.xsd + http://www.springframework.org/schema/integration http://www.springframework.org/schema/integration/spring-integration-2.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.0.xsd http://www.springframework.org/schema/tool http://www.springframework.org/schema/tool/spring-tool-3.0.xsd @@ -18,16 +18,15 @@ class="org.springframework.integration.xmpp.ignore.XmppMessageProducer" p:recipient="${user.2.login}"/> - - - - + + + diff --git a/spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/ignore/OutboundXmppRosterEventsEndpointTests-context.xml b/spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/ignore/OutboundXmppRosterEventsEndpointTests-context.xml index a26994b502..1022a494f2 100644 --- a/spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/ignore/OutboundXmppRosterEventsEndpointTests-context.xml +++ b/spring-integration-xmpp/src/test/java/org/springframework/integration/xmpp/ignore/OutboundXmppRosterEventsEndpointTests-context.xml @@ -1,57 +1,34 @@ - - - - - - - - + + - - + service-name="${user.1.service}"/> - - - + diff --git a/spring-integration-xmpp/src/test/java/test.properties b/spring-integration-xmpp/src/test/java/test.properties index dbdaca6ebc..a053e85a69 100644 --- a/spring-integration-xmpp/src/test/java/test.properties +++ b/spring-integration-xmpp/src/test/java/test.properties @@ -1,6 +1,6 @@ -user.2.login=user2@gmail.com +user.2.login=springintegration@gmail.com -user.1.login=suser1@gmail.com -user.1.password=foo +user.1.login=springintegration.eip@gmail.com +user.1.password=spr1ng1p user.1.host=talk.google.com user.1.service=gmail.com \ No newline at end of file From 295af552421fe4184e1bdbb751b7b09dde9f1c6f Mon Sep 17 00:00:00 2001 From: Mark Fisher Date: Fri, 5 Nov 2010 13:53:59 -0400 Subject: [PATCH 61/82] polishing --- .../file/DefaultDirectoryScanner.java | 93 ++-- .../file/DefaultFileNameGenerator.java | 5 +- .../integration/file/DirectoryScanner.java | 85 ++-- .../integration/file/FileHeaders.java | 2 +- .../integration/file/FileLocker.java | 2 +- .../integration/file/FileNameGenerator.java | 2 +- .../file/FileReadingMessageSource.java | 440 ++++++++++-------- .../file/FileWritingMessageHandler.java | 11 +- .../file/HeadDirectoryScanner.java | 39 +- .../RecursiveLeafOnlyDirectoryScanner.java | 50 +- ...nelAdapterWithRecursiveDirectoryTests.java | 2 +- 11 files changed, 402 insertions(+), 329 deletions(-) diff --git a/spring-integration-file/src/main/java/org/springframework/integration/file/DefaultDirectoryScanner.java b/spring-integration-file/src/main/java/org/springframework/integration/file/DefaultDirectoryScanner.java index aff9f362ec..87b41a67cb 100644 --- a/spring-integration-file/src/main/java/org/springframework/integration/file/DefaultDirectoryScanner.java +++ b/spring-integration-file/src/main/java/org/springframework/integration/file/DefaultDirectoryScanner.java @@ -13,66 +13,71 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.springframework.integration.file; +import java.io.File; +import java.util.Arrays; +import java.util.List; + import org.springframework.integration.MessagingException; import org.springframework.integration.file.entries.AcceptOnceEntryFileListFilter; import org.springframework.integration.file.entries.EntryListFilter; -import java.io.File; - -import java.util.List; - - /** - * Default directory scanner and base class for other directory scanners. It takes care of the default interrelations - * between filtering, scanning and locking. - * + * Default directory scanner and base class for other directory scanners. + * Manages the default interrelations between filtering, scanning and locking. + * * @author Iwein Fuld * @since 2.0 */ public class DefaultDirectoryScanner implements DirectoryScanner { - private EntryListFilter filter = new AcceptOnceEntryFileListFilter(); - private FileLocker locker; - public final List listFiles(File directory) throws IllegalArgumentException { - File[] files = listEligibleFiles(directory); + private volatile EntryListFilter filter = new AcceptOnceEntryFileListFilter(); - if (files == null) { - throw new MessagingException("The path [" + directory + "] does not denote a properly accessible directory."); - } + private volatile FileLocker locker; - return this.filter.filterEntries(files); - } - /** - * Subclasses may refine the listing strategy by overriding this method. The files returned here are passed onto the - * filter. - * - * @param directory root directory to use for listing - * @return the files this scanner should consider - */ - protected File[] listEligibleFiles(File directory) { - return directory.listFiles(); - } + public void setFilter(EntryListFilter filter) { + this.filter = filter; + } - public void setFilter(EntryListFilter filter) { - this.filter = filter; - } + /** + * {@inheritDoc} + */ + public final void setLocker(FileLocker locker) { + this.locker = locker; + } - /** - * {@inheritDoc} - *

- * This class takes the minimal implementation and merely delegates to the locker if set. - */ - public final boolean tryClaim(File file) { - return (locker == null) || locker.lock(file); - } - /** - * {@inheritDoc} - */ - public final void setLocker(FileLocker locker) { - this.locker = locker; - } + /** + * {@inheritDoc} + *

+ * This class takes the minimal implementation and merely delegates to the + * locker if set. + */ + public final boolean tryClaim(File file) { + return (this.locker == null) || this.locker.lock(file); + } + + public final List listFiles(File directory) throws IllegalArgumentException { + File[] files = listEligibleFiles(directory); + if (files == null) { + throw new MessagingException("The path [" + directory + + "] does not denote a properly accessible directory."); + } + return (this.filter != null) ? this.filter.filterEntries(files) : Arrays.asList(files); + } + + /** + * Subclasses may refine the listing strategy by overriding this method. The + * files returned here are passed onto the filter. + * + * @param directory root directory to use for listing + * @return the files this scanner should consider + */ + protected File[] listEligibleFiles(File directory) { + return directory.listFiles(); + } + } diff --git a/spring-integration-file/src/main/java/org/springframework/integration/file/DefaultFileNameGenerator.java b/spring-integration-file/src/main/java/org/springframework/integration/file/DefaultFileNameGenerator.java index ad46cc549b..20fdc3a97e 100644 --- a/spring-integration-file/src/main/java/org/springframework/integration/file/DefaultFileNameGenerator.java +++ b/spring-integration-file/src/main/java/org/springframework/integration/file/DefaultFileNameGenerator.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2009 the original author or authors. + * Copyright 2002-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. @@ -49,8 +49,7 @@ public class DefaultFileNameGenerator implements FileNameGenerator { public String generateFileName(Message message) { Object filenameProperty = message.getHeaders().get(this.headerName); - if (filenameProperty instanceof String - && StringUtils.hasText((String) filenameProperty)) { + if (filenameProperty instanceof String && StringUtils.hasText((String) filenameProperty)) { return (String) filenameProperty; } if (message.getPayload() instanceof File) { diff --git a/spring-integration-file/src/main/java/org/springframework/integration/file/DirectoryScanner.java b/spring-integration-file/src/main/java/org/springframework/integration/file/DirectoryScanner.java index bcd3d69396..c9090e3277 100644 --- a/spring-integration-file/src/main/java/org/springframework/integration/file/DirectoryScanner.java +++ b/spring-integration-file/src/main/java/org/springframework/integration/file/DirectoryScanner.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2009 the original author or authors. + * Copyright 2002-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. @@ -22,52 +22,57 @@ import java.io.File; import java.util.List; /** - * Strategy for scanning directories. Implementations may select all children and grandchildren of the scanned directory - * in any order. This interface is intended to enable the customization of selection, locking and ordering of files in a - * directory like RecursiveDirectoryScanner. If the only requirement is to ignore certain files a EntryListFilter - * implementation should suffice. - * + * Strategy for scanning directories. Implementations may select all children + * and grandchildren of the scanned directory in any order. This interface is + * intended to enable the customization of selection, locking and ordering of + * files in a directory like RecursiveDirectoryScanner. If the only requirement + * is to ignore certain files a EntryListFilter implementation should suffice. * - * * @author Iwein Fuld */ public interface DirectoryScanner { - /** - * Scans the directory according to the strategy particular to this implementation and returns the selected files as - * a File array. This method may never return files that are rejected by the filter. - * - * @param directory the directory to scan for files - * @return a list of files representing the content of the directory - * @throws IllegalArgumentException thrown if the input is incorrect - */ - List listFiles(File directory) throws IllegalArgumentException; + /** + * Scans the directory according to the strategy particular to this + * implementation and returns the selected files as a File array. This + * method may never return files that are rejected by the filter. + * + * @param directory the directory to scan for files + * @return a list of files representing the content of the directory + * @throws IllegalArgumentException if the input is incorrect + */ + List listFiles(File directory) throws IllegalArgumentException; - /** - * Sets a custom filter to be used by this scanner. The filter will get a chance to reject files before the scanner - * presents them through its listFiles method. A scanner may use additional filtering that is out of the control of - * the provided filter. - * - * @param filter the custom filter to be used - */ - void setFilter(EntryListFilter filter); + /** + * Sets a custom filter to be used by this scanner. The filter will get a + * chance to reject files before the scanner presents them through its + * listFiles method. A scanner may use additional filtering that is out of + * the control of the provided filter. + * + * @param filter + * the custom filter to be used + */ + void setFilter(EntryListFilter filter); + /** + * Sets a custom locker to be used by this scanner. The locker will get a + * chance to lock files and reject claims on files that are already locked. + * + * @param locker + * the custom locker to be used + */ + void setLocker(FileLocker locker); - /** - * Claim the file to process. It is up to the implementation to decide what additional safe guards are required to - * attain a claim to the file. But if a locker is set implementations MUST invoke its lock method and - * MUST return false if the locker did not grant the lock. - * - * @param file file to be claimed - * @return true if the claim was granted false otherwise - */ - boolean tryClaim(File file); + /** + * Claim the file to process. It is up to the implementation to decide what + * additional safe guards are required to attain a claim to the file. But if + * a locker is set implementations MUST invoke its lock method + * and MUST return false if the locker did not grant the lock. + * + * @param file + * file to be claimed + * @return true if the claim was granted false otherwise + */ + boolean tryClaim(File file); - /** - * Sets a custom locker to be used by this scanner. The locker will get a chance to lock files and reject claims on - * files that are already locked. - * - * @param locker the custom locker to be used - */ - void setLocker(FileLocker locker); } diff --git a/spring-integration-file/src/main/java/org/springframework/integration/file/FileHeaders.java b/spring-integration-file/src/main/java/org/springframework/integration/file/FileHeaders.java index d14537ddfb..3bfbdaf65f 100644 --- a/spring-integration-file/src/main/java/org/springframework/integration/file/FileHeaders.java +++ b/spring-integration-file/src/main/java/org/springframework/integration/file/FileHeaders.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2009 the original author or authors. + * Copyright 2002-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. diff --git a/spring-integration-file/src/main/java/org/springframework/integration/file/FileLocker.java b/spring-integration-file/src/main/java/org/springframework/integration/file/FileLocker.java index e96883d806..06b02a358f 100644 --- a/spring-integration-file/src/main/java/org/springframework/integration/file/FileLocker.java +++ b/spring-integration-file/src/main/java/org/springframework/integration/file/FileLocker.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2009 the original author or authors. + * Copyright 2002-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. diff --git a/spring-integration-file/src/main/java/org/springframework/integration/file/FileNameGenerator.java b/spring-integration-file/src/main/java/org/springframework/integration/file/FileNameGenerator.java index 7fda8e92a3..0c7ca53aeb 100644 --- a/spring-integration-file/src/main/java/org/springframework/integration/file/FileNameGenerator.java +++ b/spring-integration-file/src/main/java/org/springframework/integration/file/FileNameGenerator.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2008 the original author or authors. + * Copyright 2002-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. diff --git a/spring-integration-file/src/main/java/org/springframework/integration/file/FileReadingMessageSource.java b/spring-integration-file/src/main/java/org/springframework/integration/file/FileReadingMessageSource.java index 3eade29e94..89b39b9d8d 100644 --- a/spring-integration-file/src/main/java/org/springframework/integration/file/FileReadingMessageSource.java +++ b/spring-integration-file/src/main/java/org/springframework/integration/file/FileReadingMessageSource.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2009 the original author or authors. + * Copyright 2002-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. @@ -13,6 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.springframework.integration.file; import java.io.File; @@ -34,232 +35,275 @@ import org.springframework.integration.file.entries.EntryListFilter; import org.springframework.integration.support.MessageBuilder; import org.springframework.util.Assert; - /** - * {@link MessageSource} that creates messages from a file system directory. To prevent messages for certain files, you - * may supply a {@link org.springframework.integration.file.entries.EntryListFilter}. By default, - * an {@link org.springframework.integration.file.entries.AcceptOnceEntryFileListFilter} is used. It ensures files are - * picked up only once from the directory. + * {@link MessageSource} that creates messages from a file system directory. To + * prevent messages for certain files, you may supply a + * {@link org.springframework.integration.file.entries.EntryListFilter}. By + * default, an + * {@link org.springframework.integration.file.entries.AcceptOnceEntryFileListFilter} + * is used. It ensures files are picked up only once from the directory. *

- * A common problem with reading files is that a file may be detected before it is ready. The default {@link - * org.springframework.integration.file.entries.AcceptOnceEntryFileListFilter} does not prevent this. In most cases, this can be prevented if the file-writing process - * renames each file as soon as it is ready for reading. A pattern-matching filter that accepts only files that are - * ready (e.g. based on a known suffix), composed with the default {@link org.springframework.integration.file.entries.AcceptOnceEntryFileListFilter} would allow for - * this. See {@link org.springframework.integration.file.entries.CompositeEntryListFilter} for a way to do this. + * A common problem with reading files is that a file may be detected before it + * is ready. The default + * {@link org.springframework.integration.file.entries.AcceptOnceEntryFileListFilter} + * does not prevent this. In most cases, this can be prevented if the + * file-writing process renames each file as soon as it is ready for reading. A + * pattern-matching filter that accepts only files that are ready (e.g. based on + * a known suffix), composed with the default + * {@link org.springframework.integration.file.entries.AcceptOnceEntryFileListFilter} + * would allow for this. See + * {@link org.springframework.integration.file.entries.CompositeEntryListFilter} + * for a way to do this. *

- * A {@link Comparator} can be used to ensure internal ordering of the Files in a {@link PriorityBlockingQueue}. This - * does not provide the same guarantees as a {@link ResequencingMessageGroupProcessor}, but in cases where writing files and failure - * downstream are rare it might be sufficient. + * A {@link Comparator} can be used to ensure internal ordering of the Files in + * a {@link PriorityBlockingQueue}. This does not provide the same guarantees as + * a {@link ResequencingMessageGroupProcessor}, but in cases where writing files + * and failure downstream are rare it might be sufficient. *

- * FileReadingMessageSource is fully thread-safe under concurrent receive() invocations and message - * delivery callbacks. - * + * FileReadingMessageSource is fully thread-safe under concurrent + * receive() invocations and message delivery callbacks. + * * @author Iwein Fuld * @author Mark Fisher * @author Oleg Zhurakousky */ -public class FileReadingMessageSource extends IntegrationObjectSupport implements MessageSource{ - private static final int DEFAULT_INTERNAL_QUEUE_CAPACITY = 5; - private static final Log logger = LogFactory.getLog(FileReadingMessageSource.class); - private volatile File directory; - private volatile DirectoryScanner scanner = new DefaultDirectoryScanner(); - private volatile boolean autoCreateDirectory = true; +public class FileReadingMessageSource extends IntegrationObjectSupport implements MessageSource { - /* - * {@link PriorityBlockingQueue#iterator()} throws {@link java.util.ConcurrentModificationException} in Java 5. - * There is no locking around the queue, so there is also no iteration. - */ - private final Queue toBeReceived; - private boolean scanEachPoll = false; + private static final int DEFAULT_INTERNAL_QUEUE_CAPACITY = 5; - /** - * Creates a FileReadingMessageSource with a naturally ordered queue of unbounded capacity. - */ - public FileReadingMessageSource() { - this(null); - } + private static final Log logger = LogFactory.getLog(FileReadingMessageSource.class); - /** - * Creates a FileReadingMessageSource with a bounded queue of the given capacity. This can be used to reduce the - * memory footprint of this component when reading from a large directory. - * - * @param internalQueueCapacity the size of the queue used to cache files to be received internally. This queue can - * be made larger to optimize the directory scanning. With scanEachPoll set to false - * and the queue to a large size, it will be filled once and then completely emptied - * before a new directory listing is done. This is particularly useful to reduce scans - * of large numbers of files in a directory. - */ - public FileReadingMessageSource(int internalQueueCapacity) { - this(null); - Assert.isTrue(internalQueueCapacity > 0, "Cannot create a queue with non positive capacity"); - this.setScanner(new HeadDirectoryScanner(internalQueueCapacity)); - } - /** - * Creates a FileReadingMessageSource with a {@link PriorityBlockingQueue} ordered with the passed in {@link - * Comparator} - *

- * The size of the queue used should be large enough to hold all the files in the input directory in order to sort - * all of them, so restricting the size of the queue is mutually exclusive with ordering. No guarantees about file - * delivery order can be made under concurrent access. - *

- * - * @param receptionOrderComparator the comparator to be used to order the files in the internal queue - */ - public FileReadingMessageSource(Comparator receptionOrderComparator) { - toBeReceived = new PriorityBlockingQueue(DEFAULT_INTERNAL_QUEUE_CAPACITY, receptionOrderComparator); - } + private volatile File directory; - /** - * Specify the input directory. - * - * @param directory to monitor - */ - public void setDirectory(File directory) { - Assert.notNull(directory, "directory must not be null"); - this.directory = directory; - } + private volatile DirectoryScanner scanner = new DefaultDirectoryScanner(); - /** - * Optionally specify a custom scanner, for example the {@link org.springframework.integration.file.RecursiveLeafOnlyDirectoryScanner} - * - * @param scanner scanner impl - */ - public void setScanner(DirectoryScanner scanner) { - this.scanner = scanner; - } + private volatile boolean autoCreateDirectory = true; - /** - * Specify whether to create the source directory automatically if it does not yet exist upon initialization. By - * default, this value is true. If set to false and the source directory - * does not exist, an Exception will be thrown upon initialization. - * - * @param autoCreateDirectory should the directory to be monitored be created when this component starts up? - */ - public void setAutoCreateDirectory(boolean autoCreateDirectory) { - this.autoCreateDirectory = autoCreateDirectory; - } + /* + * {@link PriorityBlockingQueue#iterator()} throws + * {@link java.util.ConcurrentModificationException} in Java 5. + * There is no locking around the queue, so there is also no iteration. + */ + private final Queue toBeReceived; - /** - * Sets a {@link org.springframework.integration.file.entries.EntryListFilter}. By default a {@link org.springframework.integration.file.entries.AcceptOnceEntryFileListFilter} with no bounds is used. In most - * cases a customized {@link org.springframework.integration.file.entries.EntryListFilter} will be needed to deal with modification and duplication concerns. If - * multiple filters are required a {@link org.springframework.integration.file.entries.CompositeEntryListFilter} can be used to group them together. - *

- * The supplied filter must be thread safe.. - * - * @param filter a filter - */ - public void setFilter(EntryListFilter filter) { - Assert.notNull(filter, "'filter' must not be null"); - this.scanner.setFilter(filter); - } + private volatile boolean scanEachPoll = false; - /** - * Optional. Sets a {@link FileLocker} to be used to guard files - * against duplicate processing. - *

- * The supplied FileLocker must be thread safe - * - * @param locker a locker - */ - public void setLocker(FileLocker locker) { - Assert.notNull(locker, "'fileLocker' must not be null."); - this.scanner.setLocker(locker); - } - /** - * Optional. Set this flag if you want to make sure the internal queue is refreshed with the latest content of the - * input directory on each poll. - *

- * By default this implementation will empty its queue before looking at the directory again. In cases where order - * is relevant it is important to consider the effects of setting this flag. The internal {@link - * java.util.concurrent.BlockingQueue} that this class is keeping will more likely be out of sync with the file - * system if this flag is set to false, but it will change more often (causing expensive reordering) if - * it is set to true. - * - * @param scanEachPoll whether or not the component should re-scan (as opposed to not rescanning until the entire backlog has been delivered) - */ - public void setScanEachPoll(boolean scanEachPoll) { - this.scanEachPoll = scanEachPoll; - } + /** + * Creates a FileReadingMessageSource with a naturally ordered queue of unbounded capacity. + */ + public FileReadingMessageSource() { + this(null); + } - protected void onInit() { - Assert.notNull(directory, "'directory' must not be set before initialization"); + /** + * Creates a FileReadingMessageSource with a bounded queue of the given + * capacity. This can be used to reduce the memory footprint of this + * component when reading from a large directory. + * + * @param internalQueueCapacity + * the size of the queue used to cache files to be received + * internally. This queue can be made larger to optimize the + * directory scanning. With scanEachPoll set to false and the + * queue to a large size, it will be filled once and then + * completely emptied before a new directory listing is done. + * This is particularly useful to reduce scans of large numbers + * of files in a directory. + */ + public FileReadingMessageSource(int internalQueueCapacity) { + this(null); + Assert.isTrue(internalQueueCapacity > 0, + "Cannot create a queue with non positive capacity"); + this.setScanner(new HeadDirectoryScanner(internalQueueCapacity)); + } - if (!this.directory.exists() && this.autoCreateDirectory) { - this.directory.mkdirs(); - } + /** + * Creates a FileReadingMessageSource with a {@link PriorityBlockingQueue} + * ordered with the passed in {@link Comparator} + *

+ * The size of the queue used should be large enough to hold all the files + * in the input directory in order to sort all of them, so restricting the + * size of the queue is mutually exclusive with ordering. No guarantees + * about file delivery order can be made under concurrent access. + *

+ * + * @param receptionOrderComparator + * the comparator to be used to order the files in the internal + * queue + */ + public FileReadingMessageSource(Comparator receptionOrderComparator) { + this.toBeReceived = new PriorityBlockingQueue( + DEFAULT_INTERNAL_QUEUE_CAPACITY, receptionOrderComparator); + } - Assert.isTrue(this.directory.exists(), "Source directory [" + directory + "] does not exist."); - Assert.isTrue(this.directory.isDirectory(), "Source path [" + this.directory + "] does not point to a directory."); - Assert.isTrue(this.directory.canRead(), "Source directory [" + this.directory + "] is not readable."); - } - public Message receive() throws MessagingException { - Message message = null; + /** + * Specify the input directory. + * + * @param directory to monitor + */ + public void setDirectory(File directory) { + Assert.notNull(directory, "directory must not be null"); + this.directory = directory; + } - // rescan only if needed or explicitly configured - if (scanEachPoll || toBeReceived.isEmpty()) { - scanInputDirectory(); - } + /** + * Optionally specify a custom scanner, for example the + * {@link org.springframework.integration.file.RecursiveLeafOnlyDirectoryScanner} + * + * @param scanner scanner implementation + */ + public void setScanner(DirectoryScanner scanner) { + this.scanner = scanner; + } - File file = toBeReceived.poll(); + /** + * Specify whether to create the source directory automatically if it does + * not yet exist upon initialization. By default, this value is + * true. If set to false and the + * source directory does not exist, an Exception will be thrown upon + * initialization. + * + * @param autoCreateDirectory + * should the directory to be monitored be created when this + * component starts up? + */ + public void setAutoCreateDirectory(boolean autoCreateDirectory) { + this.autoCreateDirectory = autoCreateDirectory; + } - // file == null means the queue was empty - // we can't rely on isEmpty for concurrency reasons - while ((file != null) && !scanner.tryClaim(file)) { - file = toBeReceived.poll(); - } + /** + * Sets a + * {@link org.springframework.integration.file.entries.EntryListFilter}. By + * default a + * {@link org.springframework.integration.file.entries.AcceptOnceEntryFileListFilter} + * with no bounds is used. In most cases a customized + * {@link org.springframework.integration.file.entries.EntryListFilter} will + * be needed to deal with modification and duplication concerns. If multiple + * filters are required a + * {@link org.springframework.integration.file.entries.CompositeEntryListFilter} + * can be used to group them together. + *

+ * The supplied filter must be thread safe.. + * + * @param filter a filter + */ + public void setFilter(EntryListFilter filter) { + Assert.notNull(filter, "'filter' must not be null"); + this.scanner.setFilter(filter); + } - if (file != null) { - message = MessageBuilder.withPayload(file).build(); + /** + * Optional. Sets a {@link FileLocker} to be used to guard files against + * duplicate processing. + *

+ * The supplied FileLocker must be thread safe + * + * @param locker a locker + */ + public void setLocker(FileLocker locker) { + Assert.notNull(locker, "'fileLocker' must not be null."); + this.scanner.setLocker(locker); + } - if (logger.isInfoEnabled()) { - logger.info("Created message: [" + message + "]"); - } - } - - return message; - } - - private void scanInputDirectory() { - List filteredFiles = scanner.listFiles(directory); - Set freshFiles = new HashSet(filteredFiles); - - if (!freshFiles.isEmpty()) { - toBeReceived.addAll(freshFiles); - - if (logger.isDebugEnabled()) { - logger.debug("Added to queue: " + freshFiles); - } - } - } - - /** - * Adds the failed message back to the 'toBeReceived' queue if there is room. - * - * @param failedMessage the {@link org.springframework.integration.Message} that blew up - */ - public void onFailure(Message failedMessage) { - if (logger.isWarnEnabled()) { - logger.warn("Failed to send: " + failedMessage); - } - - toBeReceived.offer(failedMessage.getPayload()); - } - - /** - * The message is just logged. It was already removed from the queue during the call to receive() - * - * @param sentMessage the message that was successfully delivered - */ - public void onSend(Message sentMessage) { - if (logger.isDebugEnabled()) { - logger.debug("Sent: " + sentMessage); - } - } + /** + * Optional. Set this flag if you want to make sure the internal queue is + * refreshed with the latest content of the input directory on each poll. + *

+ * By default this implementation will empty its queue before looking at the + * directory again. In cases where order is relevant it is important to + * consider the effects of setting this flag. The internal + * {@link java.util.concurrent.BlockingQueue} that this class is keeping + * will more likely be out of sync with the file system if this flag is set + * to false, but it will change more often (causing expensive + * reordering) if it is set to true. + * + * @param scanEachPoll + * whether or not the component should re-scan (as opposed to not + * rescanning until the entire backlog has been delivered) + */ + public void setScanEachPoll(boolean scanEachPoll) { + this.scanEachPoll = scanEachPoll; + } public String getComponentType() { return "file:inbound-channel-adapter"; } + + protected void onInit() { + Assert.notNull(directory, "'directory' must not be null"); + if (!this.directory.exists() && this.autoCreateDirectory) { + this.directory.mkdirs(); + } + Assert.isTrue(this.directory.exists(), + "Source directory [" + directory + "] does not exist."); + Assert.isTrue(this.directory.isDirectory(), + "Source path [" + this.directory + "] does not point to a directory."); + Assert.isTrue(this.directory.canRead(), + "Source directory [" + this.directory + "] is not readable."); + } + + public Message receive() throws MessagingException { + Message message = null; + + // rescan only if needed or explicitly configured + if (scanEachPoll || toBeReceived.isEmpty()) { + scanInputDirectory(); + } + + File file = toBeReceived.poll(); + + // file == null means the queue was empty + // we can't rely on isEmpty for concurrency reasons + while ((file != null) && !scanner.tryClaim(file)) { + file = toBeReceived.poll(); + } + + if (file != null) { + message = MessageBuilder.withPayload(file).build(); + if (logger.isInfoEnabled()) { + logger.info("Created message: [" + message + "]"); + } + } + return message; + } + + private void scanInputDirectory() { + List filteredFiles = scanner.listFiles(directory); + Set freshFiles = new HashSet(filteredFiles); + if (!freshFiles.isEmpty()) { + toBeReceived.addAll(freshFiles); + if (logger.isDebugEnabled()) { + logger.debug("Added to queue: " + freshFiles); + } + } + } + + /** + * Adds the failed message back to the 'toBeReceived' queue if there is room. + * + * @param failedMessage + * the {@link org.springframework.integration.Message} that failed + */ + public void onFailure(Message failedMessage) { + if (logger.isWarnEnabled()) { + logger.warn("Failed to send: " + failedMessage); + } + toBeReceived.offer(failedMessage.getPayload()); + } + + /** + * The message is just logged. It was already removed from the queue during + * the call to receive() + * + * @param sentMessage + * the message that was successfully delivered + */ + public void onSend(Message sentMessage) { + if (logger.isDebugEnabled()) { + logger.debug("Sent: " + sentMessage); + } + } + } diff --git a/spring-integration-file/src/main/java/org/springframework/integration/file/FileWritingMessageHandler.java b/spring-integration-file/src/main/java/org/springframework/integration/file/FileWritingMessageHandler.java index b89fe2f196..ba5478d040 100644 --- a/spring-integration-file/src/main/java/org/springframework/integration/file/FileWritingMessageHandler.java +++ b/spring-integration-file/src/main/java/org/springframework/integration/file/FileWritingMessageHandler.java @@ -204,9 +204,7 @@ public class FileWritingMessageHandler extends AbstractReplyProducingMessageHand return resultFile; } - private File handleByteArrayMessage(byte[] bytes, File originalFile, File tempFile, File resultFile) - throws IOException { - + private File handleByteArrayMessage(byte[] bytes, File originalFile, File tempFile, File resultFile) throws IOException { FileCopyUtils.copy(bytes, tempFile); tempFile.renameTo(resultFile); if (this.deleteSourceFiles && originalFile != null) { @@ -215,11 +213,8 @@ public class FileWritingMessageHandler extends AbstractReplyProducingMessageHand return resultFile; } - private File handleStringMessage(String content, File originalFile, File tempFile, File resultFile) - throws IOException { - - OutputStreamWriter writer = new OutputStreamWriter( - new FileOutputStream(tempFile), this.charset); + private File handleStringMessage(String content, File originalFile, File tempFile, File resultFile) throws IOException { + OutputStreamWriter writer = new OutputStreamWriter(new FileOutputStream(tempFile), this.charset); FileCopyUtils.copy(content, writer); tempFile.renameTo(resultFile); if (this.deleteSourceFiles && originalFile != null) { diff --git a/spring-integration-file/src/main/java/org/springframework/integration/file/HeadDirectoryScanner.java b/spring-integration-file/src/main/java/org/springframework/integration/file/HeadDirectoryScanner.java index 6a3c291b24..999a56df71 100644 --- a/spring-integration-file/src/main/java/org/springframework/integration/file/HeadDirectoryScanner.java +++ b/spring-integration-file/src/main/java/org/springframework/integration/file/HeadDirectoryScanner.java @@ -13,6 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.springframework.integration.file; import org.springframework.integration.file.entries.EntryListFilter; @@ -22,28 +23,32 @@ import java.io.File; import java.util.Arrays; import java.util.List; - /** - * A custom scanner that only returns the first maxNumberOfFiles elements from a directory listing. This is - * useful to limit the number of File objects in memory and therefore mutually exclusive with AcceptOnceFileListFilter. - * + * A custom scanner that only returns the first maxNumberOfFiles + * elements from a directory listing. This is useful to limit the number of File + * objects in memory and therefore mutually exclusive with AcceptOnceFileListFilter. + * * @author Iwein Fuld - * @since 2.0.0 + * @since 2.0 */ public class HeadDirectoryScanner extends DefaultDirectoryScanner { - public HeadDirectoryScanner(int maxNumberOfFiles) { - this.setFilter(new HeadFilter(maxNumberOfFiles)); - } - private class HeadFilter implements EntryListFilter { - private final int maxNumberOfFiles; + public HeadDirectoryScanner(int maxNumberOfFiles) { + this.setFilter(new HeadFilter(maxNumberOfFiles)); + } - public HeadFilter(int maxNumberOfFiles) { - this.maxNumberOfFiles = maxNumberOfFiles; - } - public List filterEntries(File[] files) { - return Arrays.asList(files).subList(0, Math.min(files.length, maxNumberOfFiles)); - } - } + private static class HeadFilter implements EntryListFilter { + + private final int maxNumberOfFiles; + + public HeadFilter(int maxNumberOfFiles) { + this.maxNumberOfFiles = maxNumberOfFiles; + } + + public List filterEntries(File[] files) { + return Arrays.asList(files).subList(0, Math.min(files.length, maxNumberOfFiles)); + } + } + } diff --git a/spring-integration-file/src/main/java/org/springframework/integration/file/RecursiveLeafOnlyDirectoryScanner.java b/spring-integration-file/src/main/java/org/springframework/integration/file/RecursiveLeafOnlyDirectoryScanner.java index f417e98993..de531f4d29 100644 --- a/spring-integration-file/src/main/java/org/springframework/integration/file/RecursiveLeafOnlyDirectoryScanner.java +++ b/spring-integration-file/src/main/java/org/springframework/integration/file/RecursiveLeafOnlyDirectoryScanner.java @@ -1,3 +1,19 @@ +/* + * Copyright 2002-2010 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package org.springframework.integration.file; import java.io.File; @@ -6,23 +22,27 @@ import java.util.Arrays; import java.util.List; /** - * DirectoryScanner that lists all files inside a directory and subdirectories, without limit. This scanner should not - * be used with directories that contain a vast number of files or on deep trees, as all the file names will be read + * DirectoryScanner that lists all files inside a directory and subdirectories, + * without limit. This scanner should not be used with directories that contain + * a vast number of files or on deep trees, as all the file names will be read * into memory and the scanning will be done recursively. - * + * * @author Iwein Fuld */ public class RecursiveLeafOnlyDirectoryScanner extends DefaultDirectoryScanner { - protected File[] listEligibleFiles(File directory) throws IllegalArgumentException { - File[] rootFiles = directory.listFiles(); - List files = new ArrayList(rootFiles.length); - for (File rootFile : rootFiles) { - if (rootFile.isDirectory()) { - files.addAll(Arrays.asList(listEligibleFiles(rootFile))); - } else { - files.add(rootFile); - } - } - return files.toArray(new File[files.size()]); - } + + protected File[] listEligibleFiles(File directory) throws IllegalArgumentException { + File[] rootFiles = directory.listFiles(); + List files = new ArrayList(rootFiles.length); + for (File rootFile : rootFiles) { + if (rootFile.isDirectory()) { + files.addAll(Arrays.asList(listEligibleFiles(rootFile))); + } + else { + files.add(rootFile); + } + } + return files.toArray(new File[files.size()]); + } + } diff --git a/spring-integration-file/src/test/java/org/springframework/integration/file/recursive/FileInboundChannelAdapterWithRecursiveDirectoryTests.java b/spring-integration-file/src/test/java/org/springframework/integration/file/recursive/FileInboundChannelAdapterWithRecursiveDirectoryTests.java index b8792d06fd..247c189654 100644 --- a/spring-integration-file/src/test/java/org/springframework/integration/file/recursive/FileInboundChannelAdapterWithRecursiveDirectoryTests.java +++ b/spring-integration-file/src/test/java/org/springframework/integration/file/recursive/FileInboundChannelAdapterWithRecursiveDirectoryTests.java @@ -61,7 +61,7 @@ public class FileInboundChannelAdapterWithRecursiveDirectoryTests { } @SuppressWarnings("unchecked") - @Test(timeout = 2000) + @Test(timeout = 3000) public void shouldReturnFilesMultipleLevels() throws IOException { //when From 6abae5412bd06f9355df7320578c1617f00328d8 Mon Sep 17 00:00:00 2001 From: Mark Fisher Date: Fri, 5 Nov 2010 14:07:11 -0400 Subject: [PATCH 62/82] polishing --- .../AbstractFilePayloadTransformerParser.java | 2 +- .../FileInboundChannelAdapterParser.java | 119 ++++++----- .../config/FileListFilterFactoryBean.java | 163 ++++++++------- .../file/config/FileNamespaceHandler.java | 2 +- .../FileOutboundChannelAdapterParser.java | 2 +- .../config/FileOutboundGatewayParser.java | 2 +- .../FileReadingMessageSourceFactoryBean.java | 197 +++++++++--------- .../FileToByteArrayTransformerParser.java | 2 +- .../config/FileToStringTransformerParser.java | 2 +- ...ngMessageHandlerBeanDefinitionBuilder.java | 2 +- .../FileWritingMessageHandlerFactoryBean.java | 4 +- 11 files changed, 249 insertions(+), 248 deletions(-) diff --git a/spring-integration-file/src/main/java/org/springframework/integration/file/config/AbstractFilePayloadTransformerParser.java b/spring-integration-file/src/main/java/org/springframework/integration/file/config/AbstractFilePayloadTransformerParser.java index 2d495b7e08..74f9383589 100644 --- a/spring-integration-file/src/main/java/org/springframework/integration/file/config/AbstractFilePayloadTransformerParser.java +++ b/spring-integration-file/src/main/java/org/springframework/integration/file/config/AbstractFilePayloadTransformerParser.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2009 the original author or authors. + * Copyright 2002-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. diff --git a/spring-integration-file/src/main/java/org/springframework/integration/file/config/FileInboundChannelAdapterParser.java b/spring-integration-file/src/main/java/org/springframework/integration/file/config/FileInboundChannelAdapterParser.java index afef32cdc2..65e13c8311 100644 --- a/spring-integration-file/src/main/java/org/springframework/integration/file/config/FileInboundChannelAdapterParser.java +++ b/spring-integration-file/src/main/java/org/springframework/integration/file/config/FileInboundChannelAdapterParser.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2009 the original author or authors. + * Copyright 2002-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. @@ -31,73 +31,72 @@ import org.springframework.util.xml.DomUtils; /** * Parser for the <inbound-channel-adapter> element of the 'file' namespace. - * + * * @author Iwein Fuld * @author Mark Fisher */ public class FileInboundChannelAdapterParser extends AbstractPollingInboundChannelAdapterParser { - private static final String PACKAGE_NAME = "org.springframework.integration.file"; + private static final String PACKAGE_NAME = "org.springframework.integration.file"; - @Override - protected BeanMetadataElement parseSource(Element element, ParserContext parserContext) { - BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition( - PACKAGE_NAME + ".config.FileReadingMessageSourceFactoryBean"); - IntegrationNamespaceUtils.setReferenceIfAttributeDefined(builder, element, "comparator"); - IntegrationNamespaceUtils.setReferenceIfAttributeDefined(builder, element, "scanner"); - IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, "directory"); - IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, "auto-create-directory"); - IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, "queue-size"); - String filterBeanName = this.registerFilter(element, parserContext); - String lockerBeanName = registerLocker(element, parserContext); - if (lockerBeanName != null) { - builder.addPropertyReference("locker", lockerBeanName); - } - builder.addPropertyReference("filter", filterBeanName); - String beanName = BeanDefinitionReaderUtils.registerWithGeneratedName(builder.getBeanDefinition(), parserContext.getRegistry()); - return new RuntimeBeanReference(beanName); - } + @Override + protected BeanMetadataElement parseSource(Element element, ParserContext parserContext) { + BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition( + PACKAGE_NAME + ".config.FileReadingMessageSourceFactoryBean"); + IntegrationNamespaceUtils.setReferenceIfAttributeDefined(builder, element, "comparator"); + IntegrationNamespaceUtils.setReferenceIfAttributeDefined(builder, element, "scanner"); + IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, "directory"); + IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, "auto-create-directory"); + IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, "queue-size"); + String filterBeanName = this.registerFilter(element, parserContext); + String lockerBeanName = registerLocker(element, parserContext); + if (lockerBeanName != null) { + builder.addPropertyReference("locker", lockerBeanName); + } + builder.addPropertyReference("filter", filterBeanName); + String beanName = BeanDefinitionReaderUtils.registerWithGeneratedName( + builder.getBeanDefinition(), parserContext.getRegistry()); + return new RuntimeBeanReference(beanName); + } - private String registerLocker(Element element, ParserContext parserContext) { - String lockerBeanName = null; - Element nioLocker = DomUtils.getChildElementByTagName(element, "nio-locker"); - if (nioLocker != null) { - BeanDefinitionBuilder builder = BeanDefinitionBuilder - .genericBeanDefinition(PACKAGE_NAME + ".locking.NioFileLocker"); - lockerBeanName = BeanDefinitionReaderUtils.registerWithGeneratedName(builder.getBeanDefinition(), - parserContext.getRegistry()); - } else { - Element locker = DomUtils.getChildElementByTagName(element, "locker"); - if (locker != null) { - lockerBeanName = locker.getAttribute("ref"); - } - } - return lockerBeanName; - } + private String registerLocker(Element element, ParserContext parserContext) { + String lockerBeanName = null; + Element nioLocker = DomUtils.getChildElementByTagName(element, "nio-locker"); + if (nioLocker != null) { + BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition( + PACKAGE_NAME + ".locking.NioFileLocker"); + lockerBeanName = BeanDefinitionReaderUtils.registerWithGeneratedName( + builder.getBeanDefinition(), parserContext.getRegistry()); + } + else { + Element locker = DomUtils.getChildElementByTagName(element, "locker"); + if (locker != null) { + lockerBeanName = locker.getAttribute("ref"); + } + } + return lockerBeanName; + } - private String registerFilter(Element element, ParserContext parserContext) { - BeanDefinitionBuilder factoryBeanBuilder = BeanDefinitionBuilder.genericBeanDefinition( - PACKAGE_NAME + ".config.FileListFilterFactoryBean"); - factoryBeanBuilder.setRole(BeanDefinition.ROLE_SUPPORT); - String filter = element.getAttribute("filter"); - if (StringUtils.hasText(filter)) { - factoryBeanBuilder.addPropertyReference("filterReference", filter); - } - String filenamePattern = element.getAttribute("filename-pattern"); - if (StringUtils.hasText(filenamePattern)) { - if (StringUtils.hasText(filter)) { - parserContext.getReaderContext().error( - "At most one of 'filter' and 'filename-pattern' may be provided.", element); - } - factoryBeanBuilder.addPropertyValue("filenamePattern", filenamePattern); - } - String preventDuplicates = element.getAttribute("prevent-duplicates"); - if (StringUtils.hasText(preventDuplicates)) { - factoryBeanBuilder.addPropertyValue("preventDuplicates", preventDuplicates); - } - return BeanDefinitionReaderUtils.registerWithGeneratedName( - factoryBeanBuilder.getBeanDefinition(), parserContext.getRegistry()); - } + private String registerFilter(Element element, ParserContext parserContext) { + BeanDefinitionBuilder factoryBeanBuilder = BeanDefinitionBuilder.genericBeanDefinition( + PACKAGE_NAME + ".config.FileListFilterFactoryBean"); + factoryBeanBuilder.setRole(BeanDefinition.ROLE_SUPPORT); + String filter = element.getAttribute("filter"); + if (StringUtils.hasText(filter)) { + factoryBeanBuilder.addPropertyReference("filterReference", filter); + } + String filenamePattern = element.getAttribute("filename-pattern"); + if (StringUtils.hasText(filenamePattern)) { + if (StringUtils.hasText(filter)) { + parserContext.getReaderContext().error( + "At most one of 'filter' and 'filename-pattern' may be provided.", element); + } + factoryBeanBuilder.addPropertyValue("filenamePattern", filenamePattern); + } + IntegrationNamespaceUtils.setValueIfAttributeDefined(factoryBeanBuilder, element, "prevent-duplicates"); + return BeanDefinitionReaderUtils.registerWithGeneratedName( + factoryBeanBuilder.getBeanDefinition(), parserContext.getRegistry()); + } } diff --git a/spring-integration-file/src/main/java/org/springframework/integration/file/config/FileListFilterFactoryBean.java b/spring-integration-file/src/main/java/org/springframework/integration/file/config/FileListFilterFactoryBean.java index e0a0178462..ebb4b769bd 100644 --- a/spring-integration-file/src/main/java/org/springframework/integration/file/config/FileListFilterFactoryBean.java +++ b/spring-integration-file/src/main/java/org/springframework/integration/file/config/FileListFilterFactoryBean.java @@ -13,6 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.springframework.integration.file.config; import org.springframework.beans.factory.FactoryBean; @@ -22,107 +23,111 @@ import org.springframework.integration.file.filters.SimplePatternFileListFilter; import java.io.File; import java.util.Collection; - /** * @author Mark Fisher * @since 1.0.3 */ public class FileListFilterFactoryBean implements FactoryBean> { - private volatile EntryListFilter fileListFilter; - private volatile EntryListFilter filterReference; - private volatile String filenamePattern; - private volatile Boolean preventDuplicates; - private final Object monitor = new Object(); - private volatile Collection> filterReferences; - private FileEntryNamer fileNamer = new FileEntryNamer(); - public void setFilterReferences(Collection> filterReferences) { - this.filterReferences = filterReferences; - } + private volatile EntryListFilter fileListFilter; - public void setFilterReference(EntryListFilter filterReference) { - this.filterReference = filterReference; - } + private volatile EntryListFilter filterReference; - public void setFilenamePattern(String filenamePattern) { - this.filenamePattern = filenamePattern; - } + private volatile String filenamePattern; - public void setPreventDuplicates(Boolean preventDuplicates) { - this.preventDuplicates = preventDuplicates; - } + private volatile Boolean preventDuplicates; - public EntryListFilter getObject() throws Exception { - if (this.fileListFilter == null) { - synchronized (this.monitor) { - this.intializeFileListFilter(); - } - } + private final Object monitor = new Object(); - return this.fileListFilter; - } + private volatile Collection> filterReferences; - public Class getObjectType() { - return (this.fileListFilter != null) ? this.fileListFilter.getClass() : EntryListFilter.class; - } - public boolean isSingleton() { - return true; - } + public void setFilterReferences(Collection> filterReferences) { + this.filterReferences = filterReferences; + } - private void intializeFileListFilter() { - if (this.fileListFilter != null) { - return; - } + public void setFilterReference(EntryListFilter filterReference) { + this.filterReference = filterReference; + } - EntryListFilter flf ; + public void setFilenamePattern(String filenamePattern) { + this.filenamePattern = filenamePattern; + } - if ((this.filterReference != null) && (this.filenamePattern != null)) { - throw new IllegalArgumentException("The 'filter' reference and " + "'filename-pattern' attributes are mutually exclusive."); - } + public void setPreventDuplicates(Boolean preventDuplicates) { + this.preventDuplicates = preventDuplicates; + } - if (this.filterReference != null) { - if (Boolean.TRUE.equals(this.preventDuplicates)) { - flf = this.createCompositeWithAcceptOnceFilter(this.filterReference); - } else { // preventDuplicates is either FALSE or NULL - flf = this.filterReference; - } - } else if (this.filenamePattern != null) { - SimplePatternFileListFilter patternFilter = new SimplePatternFileListFilter(this.filenamePattern); + public EntryListFilter getObject() throws Exception { + if (this.fileListFilter == null) { + synchronized (this.monitor) { + this.intializeFileListFilter(); + } + } + return this.fileListFilter; + } - if (Boolean.FALSE.equals(this.preventDuplicates)) { - flf = patternFilter; - } else { // preventDuplicates is either TRUE or NULL - flf = this.createCompositeWithAcceptOnceFilter(patternFilter); - } - } else if (Boolean.FALSE.equals(this.preventDuplicates)) { - flf = new AcceptAllEntryListFilter(); - } else { // preventDuplicates is either TRUE or NULL - flf = new AcceptOnceEntryFileListFilter(); - } + public Class getObjectType() { + return (this.fileListFilter != null) ? this.fileListFilter.getClass() : EntryListFilter.class; + } - // finally, it might be that they simply want a {@link CompositeEntryListFilter} - if ((this.filterReferences != null) && (this.filterReferences.size() > 0)) { - CompositeEntryListFilter flfc = new CompositeEntryListFilter(); + public boolean isSingleton() { + return true; + } - for (EntryListFilter ff : filterReferences) - flfc.addFilter(ff); + private void intializeFileListFilter() { + if (this.fileListFilter != null) { + return; + } + EntryListFilter filter; + if ((this.filterReference != null) && (this.filenamePattern != null)) { + throw new IllegalArgumentException("The 'filter' reference and " + + "'filename-pattern' attributes are mutually exclusive."); + } - flf = flfc; - } + if (this.filterReference != null) { + if (Boolean.TRUE.equals(this.preventDuplicates)) { + filter = this.createCompositeWithAcceptOnceFilter(this.filterReference); + } + else { // preventDuplicates is either FALSE or NULL + filter = this.filterReference; + } + } + else if (this.filenamePattern != null) { + SimplePatternFileListFilter patternFilter = new SimplePatternFileListFilter(this.filenamePattern); + if (Boolean.FALSE.equals(this.preventDuplicates)) { + filter = patternFilter; + } + else { // preventDuplicates is either TRUE or NULL + filter = this.createCompositeWithAcceptOnceFilter(patternFilter); + } + } + else if (Boolean.FALSE.equals(this.preventDuplicates)) { + filter = new AcceptAllEntryListFilter(); + } + else { // preventDuplicates is either TRUE or NULL + filter = new AcceptOnceEntryFileListFilter(); + } - if (flf == null) { - flf = new CompositeEntryListFilter(); - } + // finally, it might be that they simply want a {@link CompositeEntryListFilter} + if ((this.filterReferences != null) && (this.filterReferences.size() > 0)) { + CompositeEntryListFilter compositeFilter = new CompositeEntryListFilter(); + for (EntryListFilter ff : filterReferences) { + compositeFilter.addFilter(ff); + } + filter = compositeFilter; + } + if (filter == null) { + filter = new CompositeEntryListFilter(); + } + this.fileListFilter = filter; + } - this.fileListFilter = flf; - } + private CompositeEntryListFilter createCompositeWithAcceptOnceFilter(EntryListFilter otherFilter) { + CompositeEntryListFilter compositeFilter = new CompositeEntryListFilter(); + compositeFilter.addFilter(new AcceptOnceEntryFileListFilter()); + compositeFilter.addFilter(otherFilter); + return compositeFilter; + } - private CompositeEntryListFilter createCompositeWithAcceptOnceFilter(EntryListFilter otherFilter) { - CompositeEntryListFilter compositeFilter = new CompositeEntryListFilter(); - compositeFilter.addFilter(new AcceptOnceEntryFileListFilter()); - compositeFilter.addFilter(otherFilter); - - return compositeFilter; - } } diff --git a/spring-integration-file/src/main/java/org/springframework/integration/file/config/FileNamespaceHandler.java b/spring-integration-file/src/main/java/org/springframework/integration/file/config/FileNamespaceHandler.java index 259f948f56..8b86a87d92 100644 --- a/spring-integration-file/src/main/java/org/springframework/integration/file/config/FileNamespaceHandler.java +++ b/spring-integration-file/src/main/java/org/springframework/integration/file/config/FileNamespaceHandler.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2009 the original author or authors. + * Copyright 2002-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. diff --git a/spring-integration-file/src/main/java/org/springframework/integration/file/config/FileOutboundChannelAdapterParser.java b/spring-integration-file/src/main/java/org/springframework/integration/file/config/FileOutboundChannelAdapterParser.java index 5b7b529b11..0ec13d4e51 100644 --- a/spring-integration-file/src/main/java/org/springframework/integration/file/config/FileOutboundChannelAdapterParser.java +++ b/spring-integration-file/src/main/java/org/springframework/integration/file/config/FileOutboundChannelAdapterParser.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2009 the original author or authors. + * Copyright 2002-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. diff --git a/spring-integration-file/src/main/java/org/springframework/integration/file/config/FileOutboundGatewayParser.java b/spring-integration-file/src/main/java/org/springframework/integration/file/config/FileOutboundGatewayParser.java index b937007064..8c7fed7ac4 100644 --- a/spring-integration-file/src/main/java/org/springframework/integration/file/config/FileOutboundGatewayParser.java +++ b/spring-integration-file/src/main/java/org/springframework/integration/file/config/FileOutboundGatewayParser.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2009 the original author or authors. + * Copyright 2002-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. diff --git a/spring-integration-file/src/main/java/org/springframework/integration/file/config/FileReadingMessageSourceFactoryBean.java b/spring-integration-file/src/main/java/org/springframework/integration/file/config/FileReadingMessageSourceFactoryBean.java index 7a57605ac3..12ebf988e7 100644 --- a/spring-integration-file/src/main/java/org/springframework/integration/file/config/FileReadingMessageSourceFactoryBean.java +++ b/spring-integration-file/src/main/java/org/springframework/integration/file/config/FileReadingMessageSourceFactoryBean.java @@ -13,10 +13,12 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.springframework.integration.file.config; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; + import org.springframework.beans.factory.FactoryBean; import org.springframework.integration.file.DirectoryScanner; import org.springframework.integration.file.FileReadingMessageSource; @@ -27,134 +29,129 @@ import org.springframework.integration.file.locking.AbstractFileLockerFilter; import java.io.File; import java.util.Comparator; - /** * @author Mark Fisher * @author Iwein Fuld * @since 1.0.3 */ public class FileReadingMessageSourceFactoryBean implements FactoryBean { - private static Log logger = LogFactory.getLog(FileReadingMessageSourceFactoryBean.class); - private volatile FileReadingMessageSource source; - private volatile File directory; - private volatile EntryListFilter filter; - private volatile AbstractFileLockerFilter locker; - private volatile Comparator comparator; - private volatile DirectoryScanner scanner; - private volatile Boolean scanEachPoll; - private volatile Boolean autoCreateDirectory; - private volatile Integer queueSize; - private final Object initializationMonitor = new Object(); - @SuppressWarnings("unused") - public void setDirectory(File directory) { - this.directory = directory; - } + private static Log logger = LogFactory.getLog(FileReadingMessageSourceFactoryBean.class); - @SuppressWarnings("unused") - public void setComparator(Comparator comparator) { - this.comparator = comparator; - } + private volatile FileReadingMessageSource source; - @SuppressWarnings("unused") - public void setScanner(DirectoryScanner scanner) { - this.scanner = scanner; - } + private volatile File directory; - @SuppressWarnings("unused") - public void setFilter(EntryListFilter filter) { - if (filter instanceof AbstractFileLockerFilter && (this.locker == null)) { - this.setLocker((AbstractFileLockerFilter) filter); - } + private volatile EntryListFilter filter; - this.filter = filter; - } + private volatile AbstractFileLockerFilter locker; - @SuppressWarnings("unused") - public void setScanEachPoll(Boolean scanEachPoll) { - this.scanEachPoll = scanEachPoll; - } + private volatile Comparator comparator; - @SuppressWarnings("unused") - public void setAutoCreateDirectory(Boolean autoCreateDirectory) { - this.autoCreateDirectory = autoCreateDirectory; - } + private volatile DirectoryScanner scanner; - @SuppressWarnings("unused") - public void setQueueSize(Integer queueSize) { - this.queueSize = queueSize; - } + private volatile Boolean scanEachPoll; - public void setLocker(AbstractFileLockerFilter locker) { - this.locker = locker; - } + private volatile Boolean autoCreateDirectory; - public FileReadingMessageSource getObject() throws Exception { - if (this.source == null) { - initSource(); - } + private volatile Integer queueSize; - return this.source; - } + private final Object initializationMonitor = new Object(); - public Class getObjectType() { - return FileReadingMessageSource.class; - } - public boolean isSingleton() { - return true; - } + public void setDirectory(File directory) { + this.directory = directory; + } - private void initSource() { - synchronized (this.initializationMonitor) { - if (this.source != null) { - return; - } + public void setComparator(Comparator comparator) { + this.comparator = comparator; + } - boolean comparatorSet = this.comparator != null; - boolean queueSizeSet = this.queueSize != null; + public void setScanner(DirectoryScanner scanner) { + this.scanner = scanner; + } - if (comparatorSet) { - if (queueSizeSet) { - logger.warn("'comparator' and 'queueSize' are mutually exclusive. Ignoring 'queueSize'"); - } + public void setFilter(EntryListFilter filter) { + if (filter instanceof AbstractFileLockerFilter && (this.locker == null)) { + this.setLocker((AbstractFileLockerFilter) filter); + } + this.filter = filter; + } - this.source = new FileReadingMessageSource(this.comparator); - } else if (queueSizeSet) { - this.source = new FileReadingMessageSource(queueSize); - } else { - this.source = new FileReadingMessageSource(); - } + public void setScanEachPoll(Boolean scanEachPoll) { + this.scanEachPoll = scanEachPoll; + } - this.source.setDirectory(this.directory); + public void setAutoCreateDirectory(Boolean autoCreateDirectory) { + this.autoCreateDirectory = autoCreateDirectory; + } - if (this.scanner != null) { - this.source.setScanner(this.scanner); - } + public void setQueueSize(Integer queueSize) { + this.queueSize = queueSize; + } - if (this.filter != null) { - if (this.locker == null) { - this.source.setFilter(this.filter); - } else { - CompositeEntryListFilter fileCompositeEntryListFilter = new CompositeEntryListFilter(); + public void setLocker(AbstractFileLockerFilter locker) { + this.locker = locker; + } + public FileReadingMessageSource getObject() throws Exception { + if (this.source == null) { + initSource(); + } + return this.source; + } + + public Class getObjectType() { + return FileReadingMessageSource.class; + } + + public boolean isSingleton() { + return true; + } + + private void initSource() { + synchronized (this.initializationMonitor) { + if (this.source != null) { + return; + } + boolean comparatorSet = this.comparator != null; + boolean queueSizeSet = this.queueSize != null; + if (comparatorSet) { + if (queueSizeSet) { + logger.warn("'comparator' and 'queueSize' are mutually exclusive. Ignoring 'queueSize'"); + } + this.source = new FileReadingMessageSource(this.comparator); + } + else if (queueSizeSet) { + this.source = new FileReadingMessageSource(queueSize); + } + else { + this.source = new FileReadingMessageSource(); + } + this.source.setDirectory(this.directory); + if (this.scanner != null) { + this.source.setScanner(this.scanner); + } + if (this.filter != null) { + if (this.locker == null) { + this.source.setFilter(this.filter); + } + else { + CompositeEntryListFilter fileCompositeEntryListFilter = new CompositeEntryListFilter(); fileCompositeEntryListFilter.addFilter(this.filter); fileCompositeEntryListFilter.addFilter(this.locker); + this.source.setFilter(fileCompositeEntryListFilter); + this.source.setLocker(locker); + } + } + if (this.scanEachPoll != null) { + this.source.setScanEachPoll(this.scanEachPoll); + } + if (this.autoCreateDirectory != null) { + this.source.setAutoCreateDirectory(this.autoCreateDirectory); + } + this.source.afterPropertiesSet(); + } + } - this.source.setFilter(fileCompositeEntryListFilter); - this.source.setLocker(locker); - } - } - - if (this.scanEachPoll != null) { - this.source.setScanEachPoll(this.scanEachPoll); - } - - if (this.autoCreateDirectory != null) { - this.source.setAutoCreateDirectory(this.autoCreateDirectory); - } - - this.source.afterPropertiesSet(); - } - } } diff --git a/spring-integration-file/src/main/java/org/springframework/integration/file/config/FileToByteArrayTransformerParser.java b/spring-integration-file/src/main/java/org/springframework/integration/file/config/FileToByteArrayTransformerParser.java index 7835e4744f..4821e3f170 100644 --- a/spring-integration-file/src/main/java/org/springframework/integration/file/config/FileToByteArrayTransformerParser.java +++ b/spring-integration-file/src/main/java/org/springframework/integration/file/config/FileToByteArrayTransformerParser.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2008 the original author or authors. + * Copyright 2002-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. diff --git a/spring-integration-file/src/main/java/org/springframework/integration/file/config/FileToStringTransformerParser.java b/spring-integration-file/src/main/java/org/springframework/integration/file/config/FileToStringTransformerParser.java index 0b382699c0..6e36b1d9d3 100644 --- a/spring-integration-file/src/main/java/org/springframework/integration/file/config/FileToStringTransformerParser.java +++ b/spring-integration-file/src/main/java/org/springframework/integration/file/config/FileToStringTransformerParser.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2008 the original author or authors. + * Copyright 2002-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. diff --git a/spring-integration-file/src/main/java/org/springframework/integration/file/config/FileWritingMessageHandlerBeanDefinitionBuilder.java b/spring-integration-file/src/main/java/org/springframework/integration/file/config/FileWritingMessageHandlerBeanDefinitionBuilder.java index fd6d6752da..f473c6c45f 100644 --- a/spring-integration-file/src/main/java/org/springframework/integration/file/config/FileWritingMessageHandlerBeanDefinitionBuilder.java +++ b/spring-integration-file/src/main/java/org/springframework/integration/file/config/FileWritingMessageHandlerBeanDefinitionBuilder.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2009 the original author or authors. + * Copyright 2002-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. diff --git a/spring-integration-file/src/main/java/org/springframework/integration/file/config/FileWritingMessageHandlerFactoryBean.java b/spring-integration-file/src/main/java/org/springframework/integration/file/config/FileWritingMessageHandlerFactoryBean.java index 73b23ecbf9..4256002349 100644 --- a/spring-integration-file/src/main/java/org/springframework/integration/file/config/FileWritingMessageHandlerFactoryBean.java +++ b/spring-integration-file/src/main/java/org/springframework/integration/file/config/FileWritingMessageHandlerFactoryBean.java @@ -32,8 +32,7 @@ import java.io.File; * @author Iwein Fuld * @since 1.0.3 */ -public class FileWritingMessageHandlerFactoryBean implements FactoryBean, - BeanFactoryAware { +public class FileWritingMessageHandlerFactoryBean implements FactoryBean, BeanFactoryAware { private volatile FileWritingMessageHandler handler; @@ -61,6 +60,7 @@ public class FileWritingMessageHandlerFactoryBean implements FactoryBean Date: Fri, 5 Nov 2010 14:50:37 -0400 Subject: [PATCH 63/82] polishing --- .../file/entries/AbstractEntryListFilter.java | 19 +++++---- .../entries/AcceptAllEntryListFilter.java | 11 ++--- .../AcceptOnceEntryFileListFilter.java | 26 ++++++------ .../entries/CompositeEntryListFilter.java | 41 ++++++++++--------- .../file/entries/EntryListFilter.java | 9 ++-- .../integration/file/entries/EntryNamer.java | 6 ++- .../file/entries/FileEntryNamer.java | 12 +++--- .../PatternMatchingEntryListFilter.java | 27 +++++++----- .../SingleEntryAdaptingEntryListFilter.java | 19 +++++---- 9 files changed, 93 insertions(+), 77 deletions(-) diff --git a/spring-integration-file/src/main/java/org/springframework/integration/file/entries/AbstractEntryListFilter.java b/spring-integration-file/src/main/java/org/springframework/integration/file/entries/AbstractEntryListFilter.java index 6925a29b7a..8ec4156798 100644 --- a/spring-integration-file/src/main/java/org/springframework/integration/file/entries/AbstractEntryListFilter.java +++ b/spring-integration-file/src/main/java/org/springframework/integration/file/entries/AbstractEntryListFilter.java @@ -13,6 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.springframework.integration.file.entries; import org.springframework.beans.factory.InitializingBean; @@ -20,7 +21,6 @@ import org.springframework.beans.factory.InitializingBean; import java.util.ArrayList; import java.util.List; - /** * A convenience base class for any {@link EntryListFilter} whose criteria can be * evaluated against each File in isolation. If the entire List of files is @@ -31,14 +31,18 @@ import java.util.List; * @author Josh Long */ public abstract class AbstractEntryListFilter implements InitializingBean, EntryListFilter { - public abstract boolean accept(T t); + + /** + * subclasses may override this if initialization is required + */ + public void afterPropertiesSet() throws Exception { + } /** * {@inheritDoc} */ public List filterEntries(T[] entries) { List accepted = new ArrayList(); - if (entries != null) { for (T t : entries) { if (this.accept(t)) { @@ -46,11 +50,12 @@ public abstract class AbstractEntryListFilter implements InitializingBean, En } } } - return accepted; } - public void afterPropertiesSet() throws Exception { - // its all you! - } + /** + * subclasses must implement this method + */ + public abstract boolean accept(T entry); + } diff --git a/spring-integration-file/src/main/java/org/springframework/integration/file/entries/AcceptAllEntryListFilter.java b/spring-integration-file/src/main/java/org/springframework/integration/file/entries/AcceptAllEntryListFilter.java index deb9c1abf1..2aa2f746fb 100644 --- a/spring-integration-file/src/main/java/org/springframework/integration/file/entries/AcceptAllEntryListFilter.java +++ b/spring-integration-file/src/main/java/org/springframework/integration/file/entries/AcceptAllEntryListFilter.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2008 the original author or authors. + * Copyright 2002-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. @@ -16,18 +16,19 @@ package org.springframework.integration.file.entries; - /** - * Simple NOOP implementation for {@link org.springframework.integration.file.entries.EntryListFilter} implementation. - * Suitable as a default in implementations. + * Simple NO-OP implementation of {@link org.springframework.integration.file.entries.EntryListFilter}. + * Suitable as a default. * * @author Iwein Fuld * @author Josh Long * @param */ public class AcceptAllEntryListFilter extends AbstractEntryListFilter { + @Override - public boolean accept(T t) { + public boolean accept(T entry) { return true; } + } diff --git a/spring-integration-file/src/main/java/org/springframework/integration/file/entries/AcceptOnceEntryFileListFilter.java b/spring-integration-file/src/main/java/org/springframework/integration/file/entries/AcceptOnceEntryFileListFilter.java index 25af970353..fa24d65bd3 100644 --- a/spring-integration-file/src/main/java/org/springframework/integration/file/entries/AcceptOnceEntryFileListFilter.java +++ b/spring-integration-file/src/main/java/org/springframework/integration/file/entries/AcceptOnceEntryFileListFilter.java @@ -13,12 +13,12 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.springframework.integration.file.entries; import java.util.Queue; import java.util.concurrent.LinkedBlockingQueue; - /** * {@link EntryListFilter} that passes files only one time. This can * conveniently be used to prevent duplication of files, as is done in @@ -30,16 +30,18 @@ import java.util.concurrent.LinkedBlockingQueue; * @since 1.0.0 */ public class AcceptOnceEntryFileListFilter extends AbstractEntryListFilter { + private final Queue seen; + private final Object monitor = new Object(); + /** - * Creates an {@link org.springframework.integration.file.entries.AcceptOnceEntryFileListFilter} that is based on a bounded queue. If the - * queue overflows, files that fall out will be passed through this filter - * again if passed to the {@link #filterEntries(Object[])} method. + * Creates an {@link org.springframework.integration.file.entries.AcceptOnceEntryFileListFilter} + * that is based on a bounded queue. If the queue overflows, files that fall out will be passed + * through this filter again if passed to the {@link #filterEntries(Object[])} method. * - * @param maxCapacity the maximum number of Files to maintain in the 'seen' - * queue. + * @param maxCapacity the maximum number of Files to maintain in the 'seen' queue. */ public AcceptOnceEntryFileListFilter(int maxCapacity) { this.seen = new LinkedBlockingQueue(maxCapacity); @@ -52,18 +54,18 @@ public class AcceptOnceEntryFileListFilter extends AbstractEntryListFilter this.seen = new LinkedBlockingQueue(); } + public boolean accept(T pathname) { synchronized (this.monitor) { - if (seen.contains(pathname)) { + if (this.seen.contains(pathname)) { return false; } - - if (!seen.offer(pathname)) { - seen.poll(); - seen.add(pathname); + if (!this.seen.offer(pathname)) { + this.seen.poll(); + this.seen.add(pathname); } - return true; } } + } diff --git a/spring-integration-file/src/main/java/org/springframework/integration/file/entries/CompositeEntryListFilter.java b/spring-integration-file/src/main/java/org/springframework/integration/file/entries/CompositeEntryListFilter.java index fb428f967b..415c5bc1d4 100644 --- a/spring-integration-file/src/main/java/org/springframework/integration/file/entries/CompositeEntryListFilter.java +++ b/spring-integration-file/src/main/java/org/springframework/integration/file/entries/CompositeEntryListFilter.java @@ -13,6 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.springframework.integration.file.entries; import org.springframework.beans.factory.InitializingBean; @@ -30,8 +31,10 @@ import java.util.*; * @param */ public class CompositeEntryListFilter implements EntryListFilter { + private final Set> fileFilters; + public CompositeEntryListFilter() { this.fileFilters = new LinkedHashSet>(); } @@ -40,23 +43,9 @@ public class CompositeEntryListFilter implements EntryListFilter { this.fileFilters = new LinkedHashSet>(fileFilters); } - @SuppressWarnings("unchecked") - public List filterEntries(T[] entries) { - Assert.notNull(entries, "'files' should not be null"); - List leftOver = Arrays.asList(entries); - - for (EntryListFilter fileFilter : this.fileFilters) { - T[] ts = (T[]) leftOver.toArray(); - leftOver = fileFilter.filterEntries(ts); - } - - return leftOver; - } - - @SuppressWarnings("unchecked") //to please the eclipse compiler public CompositeEntryListFilter addFilter(EntryListFilter filter) { - return this.addFilters(filter); + return this.addFilters(Collections.singletonList(filter)); } /** @@ -76,19 +65,31 @@ public class CompositeEntryListFilter implements EntryListFilter { * @param filtersToAdd a list of filters to add * @return this CompositeEntryListFilter instance with the added filters */ - @SuppressWarnings("unchecked") public CompositeEntryListFilter addFilters(Collection> filtersToAdd) { - for (EntryListFilter elf : filtersToAdd) + for (EntryListFilter elf : filtersToAdd) { if (elf instanceof InitializingBean) { try { ((InitializingBean) elf).afterPropertiesSet(); - } catch (Exception e) { + } + catch (Exception e) { throw new RuntimeException(e); } } - + } this.fileFilters.addAll(filtersToAdd); - return this; } + + + @SuppressWarnings("unchecked") + public List filterEntries(T[] entries) { + Assert.notNull(entries, "'files' should not be null"); + List leftOver = Arrays.asList(entries); + for (EntryListFilter fileFilter : this.fileFilters) { + T[] ts = (T[]) leftOver.toArray(); + leftOver = fileFilter.filterEntries(ts); + } + return leftOver; + } + } diff --git a/spring-integration-file/src/main/java/org/springframework/integration/file/entries/EntryListFilter.java b/spring-integration-file/src/main/java/org/springframework/integration/file/entries/EntryListFilter.java index 58d4e0d11f..9a49b253e1 100644 --- a/spring-integration-file/src/main/java/org/springframework/integration/file/entries/EntryListFilter.java +++ b/spring-integration-file/src/main/java/org/springframework/integration/file/entries/EntryListFilter.java @@ -13,11 +13,11 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.springframework.integration.file.entries; import java.util.List; - /** * Strategy interface for filtering entries representing files on a local or remote file system. This is a generic * variant of FileListFilter that also works with references to remote files. @@ -26,16 +26,15 @@ import java.util.List; * * @author Josh Long * @author Iwein Fuld - * - * @since 2.0.0 - * + * @since 2.0 * @see org.springframework.integration.file.filters.FileListFilter */ public interface EntryListFilter { /** * Filters out entries and returns the entries that are left in a list, or an - * empty list when a null is passed in. + * empty list when null is passed in. */ List filterEntries(T[] entries); + } diff --git a/spring-integration-file/src/main/java/org/springframework/integration/file/entries/EntryNamer.java b/spring-integration-file/src/main/java/org/springframework/integration/file/entries/EntryNamer.java index 4610f90157..093ba6f063 100644 --- a/spring-integration-file/src/main/java/org/springframework/integration/file/entries/EntryNamer.java +++ b/spring-integration-file/src/main/java/org/springframework/integration/file/entries/EntryNamer.java @@ -13,22 +13,24 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.springframework.integration.file.entries; /** * Responsible for coercing a String identification out of the T entry. * * @author Josh Long - * @param the type of entry (there's an implementation for FTP, SFTP, and plain-old java.io.Files) + * @param the type of entry (there's an implementation for FTP, SFTP, and plain-old java.io.Files) */ public interface EntryNamer { /** * This is the one place I couldn't spackle over the interface differences between an FTPFile (FTP adapter), File (File adapter), and LsEntry (SFTP adapter) - * with generics alone. So we have a typed strategy implementation for accessing a property .... + * with generics alone. So we have a typed strategy implementation for accessing a property.... * * @param entry the entry in a file system listing * @return the String name that might be used to reference that entry or to do regular expression checks against */ String nameOf(T entry); + } diff --git a/spring-integration-file/src/main/java/org/springframework/integration/file/entries/FileEntryNamer.java b/spring-integration-file/src/main/java/org/springframework/integration/file/entries/FileEntryNamer.java index 3417cb7149..995b41a9bf 100644 --- a/spring-integration-file/src/main/java/org/springframework/integration/file/entries/FileEntryNamer.java +++ b/spring-integration-file/src/main/java/org/springframework/integration/file/entries/FileEntryNamer.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2008 the original author or authors. + * Copyright 2002-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. @@ -18,16 +18,16 @@ package org.springframework.integration.file.entries; import java.io.File; - /** - * {@link java.io.File} implementation of the {@link org.springframework.integration.file.entries.EntryNamer} strategy. - *

- * This part feels a little over-engineered... - * + * {@link java.io.File}-based implementation of the {@link EntryNamer} strategy. + * * @author Josh Long + * @since 2.0 */ public class FileEntryNamer implements EntryNamer { + public String nameOf(File entry) { return (entry != null) ? entry.getName() : null; } + } diff --git a/spring-integration-file/src/main/java/org/springframework/integration/file/entries/PatternMatchingEntryListFilter.java b/spring-integration-file/src/main/java/org/springframework/integration/file/entries/PatternMatchingEntryListFilter.java index df5df2c3bb..27cc840c01 100644 --- a/spring-integration-file/src/main/java/org/springframework/integration/file/entries/PatternMatchingEntryListFilter.java +++ b/spring-integration-file/src/main/java/org/springframework/integration/file/entries/PatternMatchingEntryListFilter.java @@ -13,6 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.springframework.integration.file.entries; import org.springframework.beans.factory.InitializingBean; @@ -21,7 +22,6 @@ import org.springframework.util.StringUtils; import java.util.regex.Pattern; - /** * Filters a listing of entries (T) by qualifying their 'name' (as determined by {@link org.springframework.integration.file.entries.EntryNamer}) * against a regular expression (an instance of {@link java.util.regex.Pattern}) @@ -29,13 +29,16 @@ import java.util.regex.Pattern; * @author Iwein Fuld * @author Josh Long * @param the type of entry - * - * @since 2.0.0 + * @since 2.0 */ public class PatternMatchingEntryListFilter extends AbstractEntryListFilter implements InitializingBean { - private Pattern pattern; - private String patternExpression; - private EntryNamer entryNamer; + + private volatile EntryNamer entryNamer; + + private volatile Pattern pattern; + + private volatile String patternExpression; + public PatternMatchingEntryListFilter(EntryNamer en, String p) { this.entryNamer = en; @@ -47,6 +50,11 @@ public class PatternMatchingEntryListFilter extends AbstractEntryListFilter entryNamer) { + this.entryNamer = entryNamer; + } + public void setPattern(Pattern pattern) { this.pattern = pattern; } @@ -64,11 +72,8 @@ public class PatternMatchingEntryListFilter extends AbstractEntryListFilter entryNamer) { - this.entryNamer = entryNamer; - } } diff --git a/spring-integration-file/src/main/java/org/springframework/integration/file/entries/SingleEntryAdaptingEntryListFilter.java b/spring-integration-file/src/main/java/org/springframework/integration/file/entries/SingleEntryAdaptingEntryListFilter.java index 5aadb3e9d1..fc985ff083 100644 --- a/spring-integration-file/src/main/java/org/springframework/integration/file/entries/SingleEntryAdaptingEntryListFilter.java +++ b/spring-integration-file/src/main/java/org/springframework/integration/file/entries/SingleEntryAdaptingEntryListFilter.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2008 the original author or authors. + * Copyright 2002-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. @@ -18,10 +18,9 @@ package org.springframework.integration.file.entries; import org.springframework.util.Assert; - /** - * this simply takes an {@link org.springframework.integration.file.entries.EntryListFilter} - * and produces an object that can field just one argument instea of an array + * This simply takes an {@link org.springframework.integration.file.entries.EntryListFilter} + * and produces an object that can field just one argument instead of an array. * * @author Josh Long */ @@ -30,17 +29,19 @@ public class SingleEntryAdaptingEntryListFilter extends AbstractEntryListFilt /** * the {@link org.springframework.integration.file.entries.EntryListFilter} that you'd like to delegate to */ - private volatile EntryListFilter entryFilter; + private volatile EntryListFilter entryListFilter; - public SingleEntryAdaptingEntryListFilter(EntryListFilter ef) { - this.entryFilter = ef; - Assert.notNull(this.entryFilter, "the entryFilter can't be null"); + public SingleEntryAdaptingEntryListFilter(EntryListFilter entryListFilter) { + Assert.notNull(entryListFilter, "entryListFilter must not be null"); + this.entryListFilter = entryListFilter; } + @Override @SuppressWarnings("unchecked") public boolean accept(T t) { T[] ts = (T[]) new Object[]{t}; - return this.entryFilter.filterEntries(ts).size() == 1; + return this.entryListFilter.filterEntries(ts).size() == 1; } + } From d020387d7e47c1cd81147e98b4ecfee689a47e64 Mon Sep 17 00:00:00 2001 From: Mark Fisher Date: Fri, 5 Nov 2010 14:58:24 -0400 Subject: [PATCH 64/82] polishing --- .../file/FileReadingMessageSourceTests.java | 5 +-- .../FileInboundChannelAdapterParserTests.java | 2 +- ...dChannelAdapterWithPatternParserTests.java | 5 +-- ...AdapterWithPreventDuplicatesFlagTests.java | 40 +++++++++---------- .../FileListFilterFactoryBeanTests.java | 13 +++--- 5 files changed, 32 insertions(+), 33 deletions(-) diff --git a/spring-integration-file/src/test/java/org/springframework/integration/file/FileReadingMessageSourceTests.java b/spring-integration-file/src/test/java/org/springframework/integration/file/FileReadingMessageSourceTests.java index d064041378..3fc29efdf0 100644 --- a/spring-integration-file/src/test/java/org/springframework/integration/file/FileReadingMessageSourceTests.java +++ b/spring-integration-file/src/test/java/org/springframework/integration/file/FileReadingMessageSourceTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2009 the original author or authors. + * Copyright 2002-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. @@ -35,7 +35,6 @@ import static org.mockito.Mockito.*; * @author Iwein Fuld * @author Mark Fisher */ -@SuppressWarnings("unchecked") @RunWith(MockitoJUnitRunner.class) public class FileReadingMessageSourceTests { @@ -76,7 +75,7 @@ public class FileReadingMessageSourceTests { @Test public void requeueOnFailure() throws Exception { when(inputDirectoryMock.listFiles()).thenReturn(new File[]{fileMock}); - Message received = source.receive(); + Message received = source.receive(); assertNotNull(received); source.onFailure(received); assertEquals(received.getPayload(), source.receive().getPayload()); diff --git a/spring-integration-file/src/test/java/org/springframework/integration/file/config/FileInboundChannelAdapterParserTests.java b/spring-integration-file/src/test/java/org/springframework/integration/file/config/FileInboundChannelAdapterParserTests.java index caedf9aa4d..2a3ff7ea19 100644 --- a/spring-integration-file/src/test/java/org/springframework/integration/file/config/FileInboundChannelAdapterParserTests.java +++ b/spring-integration-file/src/test/java/org/springframework/integration/file/config/FileInboundChannelAdapterParserTests.java @@ -58,7 +58,7 @@ public class FileInboundChannelAdapterParserTests { @Test public void channelName() throws Exception { - Object adapter = context.getBean("inputDirPoller"); + context.getBean("inputDirPoller"); AbstractMessageChannel channel = context.getBean("inputDirPoller", AbstractMessageChannel.class); assertEquals("Channel should be available under specified id", "inputDirPoller", channel.getComponentName()); } diff --git a/spring-integration-file/src/test/java/org/springframework/integration/file/config/FileInboundChannelAdapterWithPatternParserTests.java b/spring-integration-file/src/test/java/org/springframework/integration/file/config/FileInboundChannelAdapterWithPatternParserTests.java index f8af5f78b2..c4b8fedc36 100644 --- a/spring-integration-file/src/test/java/org/springframework/integration/file/config/FileInboundChannelAdapterWithPatternParserTests.java +++ b/spring-integration-file/src/test/java/org/springframework/integration/file/config/FileInboundChannelAdapterWithPatternParserTests.java @@ -116,11 +116,10 @@ public class FileInboundChannelAdapterWithPatternParserTests { @SuppressWarnings("unchecked") public void patternFilter() { DirectFieldAccessor scannerAccessor = new DirectFieldAccessor(accessor.getPropertyValue("scanner")); - - Set filters = (Set) new DirectFieldAccessor( + Set> filters = (Set>) new DirectFieldAccessor( scannerAccessor.getPropertyValue("filter")).getPropertyValue("fileFilters"); String pattern = null; - for (EntryListFilter filter : filters) { + for (EntryListFilter filter : filters) { if (filter instanceof SimplePatternFileListFilter) { pattern = (String) new DirectFieldAccessor(filter).getPropertyValue("path"); } diff --git a/spring-integration-file/src/test/java/org/springframework/integration/file/config/FileInboundChannelAdapterWithPreventDuplicatesFlagTests.java b/spring-integration-file/src/test/java/org/springframework/integration/file/config/FileInboundChannelAdapterWithPreventDuplicatesFlagTests.java index 6a68e7cd00..a3ba2ce586 100644 --- a/spring-integration-file/src/test/java/org/springframework/integration/file/config/FileInboundChannelAdapterWithPreventDuplicatesFlagTests.java +++ b/spring-integration-file/src/test/java/org/springframework/integration/file/config/FileInboundChannelAdapterWithPreventDuplicatesFlagTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2009 the original author or authors. + * Copyright 2002-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. @@ -13,6 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.springframework.integration.file.config; import org.junit.Test; @@ -43,33 +44,34 @@ import static org.junit.Assert.*; @ContextConfiguration @RunWith(SpringJUnit4ClassRunner.class) public class FileInboundChannelAdapterWithPreventDuplicatesFlagTests { + @Autowired private ApplicationContext context; + @Autowired @Qualifier("testFilter") private TestFileListFilter testFilter; + @Test public void filterAndNull() { - EntryListFilter filter = this.extractFilter("filterAndNull"); + EntryListFilter filter = this.extractFilter("filterAndNull"); assertFalse(filter instanceof CompositeEntryListFilter); assertSame(testFilter, filter); } @Test - @SuppressWarnings("unchecked") public void filterAndTrue() { - EntryListFilter filter = this.extractFilter("filterAndTrue"); + EntryListFilter filter = this.extractFilter("filterAndTrue"); assertTrue(filter instanceof CompositeEntryListFilter); - - Collection filters = (Collection) new DirectFieldAccessor(filter).getPropertyValue("fileFilters"); + Collection filters = (Collection) new DirectFieldAccessor(filter).getPropertyValue("fileFilters"); assertTrue(filters.iterator().next() instanceof AcceptOnceEntryFileListFilter); assertTrue(filters.contains(testFilter)); } @Test public void filterAndFalse() throws Exception { - EntryListFilter filter = this.extractFilter("filterAndFalse"); + EntryListFilter filter = this.extractFilter("filterAndFalse"); assertFalse(filter instanceof CompositeEntryListFilter); assertSame(testFilter, filter); } @@ -77,10 +79,10 @@ public class FileInboundChannelAdapterWithPreventDuplicatesFlagTests { @Test @SuppressWarnings("unchecked") public void patternAndNull() throws Exception { - EntryListFilter filter = this.extractFilter("patternAndNull"); + EntryListFilter filter = this.extractFilter("patternAndNull"); assertTrue(filter instanceof CompositeEntryListFilter); - - Collection filters = (Collection) new DirectFieldAccessor(filter).getPropertyValue("fileFilters"); + Collection> filters = (Collection>) + new DirectFieldAccessor(filter).getPropertyValue("fileFilters"); Iterator> iterator = filters.iterator(); assertTrue(iterator.next() instanceof AcceptOnceEntryFileListFilter); assertThat(iterator.next(), is(SimplePatternFileListFilter.class)); @@ -89,11 +91,11 @@ public class FileInboundChannelAdapterWithPreventDuplicatesFlagTests { @Test @SuppressWarnings("unchecked") public void patternAndTrue() throws Exception { - EntryListFilter filter = this.extractFilter("patternAndTrue"); + EntryListFilter filter = this.extractFilter("patternAndTrue"); assertTrue(filter instanceof CompositeEntryListFilter); - - Collection filters = (Collection) new DirectFieldAccessor(filter).getPropertyValue("fileFilters"); - Iterator iterator = filters.iterator(); + Collection> filters = (Collection>) + new DirectFieldAccessor(filter).getPropertyValue("fileFilters"); + Iterator> iterator = filters.iterator(); assertTrue(iterator.next() instanceof AcceptOnceEntryFileListFilter); assertThat(iterator.next(), is(SimplePatternFileListFilter.class)); } @@ -119,12 +121,10 @@ public class FileInboundChannelAdapterWithPreventDuplicatesFlagTests { } @Test - @SuppressWarnings("unchecked") public void defaultAndTrue() throws Exception { - EntryListFilter filter = this.extractFilter("defaultAndTrue"); + EntryListFilter filter = this.extractFilter("defaultAndTrue"); assertFalse(filter instanceof CompositeEntryListFilter); assertTrue(filter instanceof AcceptOnceEntryFileListFilter); - File testFile = new File("test"); File[] files = new File[] { testFile, testFile, testFile }; List result = filter.filterEntries(files); @@ -132,19 +132,18 @@ public class FileInboundChannelAdapterWithPreventDuplicatesFlagTests { } @Test - @SuppressWarnings("unchecked") public void defaultAndFalse() throws Exception { - EntryListFilter filter = this.extractFilter("defaultAndFalse"); + EntryListFilter filter = this.extractFilter("defaultAndFalse"); assertNotNull(filter); assertFalse(filter instanceof CompositeEntryListFilter); assertFalse(filter instanceof AcceptOnceEntryFileListFilter); - File testFile = new File("test"); File[] files = new File[] { testFile, testFile, testFile }; List result = filter.filterEntries(files); assertEquals(3, result.size()); } + @SuppressWarnings("unchecked") private EntryListFilter extractFilter(String beanName) { return (EntryListFilter) @@ -155,4 +154,5 @@ public class FileInboundChannelAdapterWithPreventDuplicatesFlagTests { .getPropertyValue("scanner")) .getPropertyValue("filter"); } + } diff --git a/spring-integration-file/src/test/java/org/springframework/integration/file/config/FileListFilterFactoryBeanTests.java b/spring-integration-file/src/test/java/org/springframework/integration/file/config/FileListFilterFactoryBeanTests.java index 582d05e9c0..dbb93dcf0e 100644 --- a/spring-integration-file/src/test/java/org/springframework/integration/file/config/FileListFilterFactoryBeanTests.java +++ b/spring-integration-file/src/test/java/org/springframework/integration/file/config/FileListFilterFactoryBeanTests.java @@ -53,7 +53,6 @@ public class FileListFilterFactoryBeanTests { } @Test - @SuppressWarnings("unchecked") public void customFilterAndPreventDuplicatesTrue() throws Exception { FileListFilterFactoryBean factory = new FileListFilterFactoryBean(); TestFilter testFilter = new TestFilter(); @@ -61,7 +60,7 @@ public class FileListFilterFactoryBeanTests { factory.setPreventDuplicates(Boolean.TRUE); EntryListFilter result = factory.getObject(); assertTrue(result instanceof CompositeEntryListFilter); - Collection filters = (Collection) new DirectFieldAccessor(result).getPropertyValue("fileFilters"); + Collection filters = (Collection) new DirectFieldAccessor(result).getPropertyValue("fileFilters"); assertTrue(filters.iterator().next() instanceof AcceptOnceEntryFileListFilter); assertTrue(filters.contains(testFilter)); } @@ -84,8 +83,9 @@ public class FileListFilterFactoryBeanTests { factory.setFilenamePattern("foo"); EntryListFilter result = factory.getObject(); assertTrue(result instanceof CompositeEntryListFilter); - Collection filters = (Collection) new DirectFieldAccessor(result).getPropertyValue("fileFilters"); - Iterator iterator = filters.iterator(); + Collection> filters = (Collection>) + new DirectFieldAccessor(result).getPropertyValue("fileFilters"); + Iterator> iterator = filters.iterator(); assertTrue(iterator.next() instanceof AcceptOnceEntryFileListFilter); assertThat(iterator.next(), is(SimplePatternFileListFilter.class)); } @@ -98,8 +98,9 @@ public class FileListFilterFactoryBeanTests { factory.setPreventDuplicates(Boolean.TRUE); EntryListFilter result = factory.getObject(); assertTrue(result instanceof CompositeEntryListFilter); - Collection filters = (Collection) new DirectFieldAccessor(result).getPropertyValue("fileFilters"); - Iterator iterator = filters.iterator(); + Collection> filters = (Collection>) + new DirectFieldAccessor(result).getPropertyValue("fileFilters"); + Iterator> iterator = filters.iterator(); assertTrue(iterator.next() instanceof AcceptOnceEntryFileListFilter); assertThat(iterator.next(), is(SimplePatternFileListFilter.class)); } From da178c16157b3d3228a8f7426cb733547fc39a38 Mon Sep 17 00:00:00 2001 From: Mark Fisher Date: Fri, 5 Nov 2010 15:28:18 -0400 Subject: [PATCH 65/82] getting rid of warnings --- .../integration/ftp/FtpClientPool.java | 2 +- .../FtpSendingMessageHandlerFactoryBean.java | 21 +----------------- .../ftp/FtpMessageHistoryTests.java | 1 + .../ftp/FtpParserOutboundTests.java | 22 ++++++------------- .../integration/ftp/OutboundFtpExample.java | 20 ++++++++++++++++- .../integration/ftp/OutboundFtpsExample.java | 20 ++++++++++++++++- 6 files changed, 48 insertions(+), 38 deletions(-) diff --git a/spring-integration-ftp/src/main/java/org/springframework/integration/ftp/FtpClientPool.java b/spring-integration-ftp/src/main/java/org/springframework/integration/ftp/FtpClientPool.java index fba9db74ec..ebf0c816f8 100644 --- a/spring-integration-ftp/src/main/java/org/springframework/integration/ftp/FtpClientPool.java +++ b/spring-integration-ftp/src/main/java/org/springframework/integration/ftp/FtpClientPool.java @@ -24,7 +24,7 @@ import org.apache.commons.net.ftp.FTPClient; * * @author Iwein Fuld */ -public interface FtpClientPool extends FtpClientFactory { +public interface FtpClientPool extends FtpClientFactory { /** * Releases the client back to the pool. When calling this method the caller diff --git a/spring-integration-ftp/src/main/java/org/springframework/integration/ftp/FtpSendingMessageHandlerFactoryBean.java b/spring-integration-ftp/src/main/java/org/springframework/integration/ftp/FtpSendingMessageHandlerFactoryBean.java index f439089e06..25321e32a0 100644 --- a/spring-integration-ftp/src/main/java/org/springframework/integration/ftp/FtpSendingMessageHandlerFactoryBean.java +++ b/spring-integration-ftp/src/main/java/org/springframework/integration/ftp/FtpSendingMessageHandlerFactoryBean.java @@ -16,14 +16,8 @@ package org.springframework.integration.ftp; -import org.springframework.beans.BeansException; import org.springframework.beans.factory.config.AbstractFactoryBean; -import org.springframework.context.ApplicationContext; -import org.springframework.context.ApplicationContextAware; -import org.springframework.context.ResourceLoaderAware; - -import org.springframework.core.io.ResourceLoader; import org.springframework.integration.file.FileNameGenerator; /** @@ -33,8 +27,7 @@ import org.springframework.integration.file.FileNameGenerator; * @author Iwein Fuld * @author Josh Long */ -public class FtpSendingMessageHandlerFactoryBean extends AbstractFactoryBean - implements ResourceLoaderAware, ApplicationContextAware { +public class FtpSendingMessageHandlerFactoryBean extends AbstractFactoryBean { protected int port; @@ -52,12 +45,8 @@ public class FtpSendingMessageHandlerFactoryBean extends AbstractFactoryBean getObjectType() { return FtpSendingMessageHandler.class; diff --git a/spring-integration-ftp/src/test/java/org/springframework/integration/ftp/FtpMessageHistoryTests.java b/spring-integration-ftp/src/test/java/org/springframework/integration/ftp/FtpMessageHistoryTests.java index 7c9d4a474c..dff651b82f 100644 --- a/spring-integration-ftp/src/test/java/org/springframework/integration/ftp/FtpMessageHistoryTests.java +++ b/spring-integration-ftp/src/test/java/org/springframework/integration/ftp/FtpMessageHistoryTests.java @@ -13,6 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.springframework.integration.ftp; import static junit.framework.Assert.assertEquals; diff --git a/spring-integration-ftp/src/test/java/org/springframework/integration/ftp/FtpParserOutboundTests.java b/spring-integration-ftp/src/test/java/org/springframework/integration/ftp/FtpParserOutboundTests.java index 4a59d2e96a..73820956ff 100644 --- a/spring-integration-ftp/src/test/java/org/springframework/integration/ftp/FtpParserOutboundTests.java +++ b/spring-integration-ftp/src/test/java/org/springframework/integration/ftp/FtpParserOutboundTests.java @@ -13,22 +13,17 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.springframework.integration.ftp; import static junit.framework.Assert.assertNotNull; -import static junit.framework.Assert.assertTrue; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; -import java.io.File; - -import org.junit.After; -import org.junit.Before; import org.junit.Test; import org.mockito.Mockito; -import org.springframework.beans.factory.BeanCreationException; -import org.springframework.context.ApplicationContext; + import org.springframework.context.support.ClassPathXmlApplicationContext; import org.springframework.integration.Message; import org.springframework.integration.endpoint.EventDrivenConsumer; @@ -38,29 +33,26 @@ import org.springframework.integration.test.util.TestUtils; /** * @author Oleg Zhurakousky - * */ public class FtpParserOutboundTests { - @Test public void testFtpOutboundWithFileGenerator() throws Exception{ ClassPathXmlApplicationContext context = - new ClassPathXmlApplicationContext("FtpParserOutboundTests-context.xml", this.getClass()); - + new ClassPathXmlApplicationContext("FtpParserOutboundTests-context.xml", this.getClass()); FileNameGenerator fileNameGenerator = context.getBean("fileNameGenerator", FileNameGenerator.class); assertNotNull(fileNameGenerator); when(fileNameGenerator.generateFileName(Mockito.any(Message.class))).thenReturn("oleg-ftp-test.txt"); - EventDrivenConsumer fileOutboundEndpoint = context.getBean("ftpOutboundAdapter", EventDrivenConsumer.class); FtpSendingMessageHandler handler = (FtpSendingMessageHandler) TestUtils.getPropertyValue(fileOutboundEndpoint, "handler"); Message message = new GenericMessage("ftp file generator test"); try { handler.handleMessage(message); - } catch (Exception e) { + } + catch (Exception e) { // ignore } verify(fileNameGenerator, times(1)).generateFileName(message); } - -} \ No newline at end of file + +} diff --git a/spring-integration-ftp/src/test/java/org/springframework/integration/ftp/OutboundFtpExample.java b/spring-integration-ftp/src/test/java/org/springframework/integration/ftp/OutboundFtpExample.java index 9a01ff1100..7eaf49f808 100644 --- a/spring-integration-ftp/src/test/java/org/springframework/integration/ftp/OutboundFtpExample.java +++ b/spring-integration-ftp/src/test/java/org/springframework/integration/ftp/OutboundFtpExample.java @@ -1,3 +1,19 @@ +/* + * Copyright 2002-2010 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package org.springframework.integration.ftp; import org.springframework.context.support.ClassPathXmlApplicationContext; @@ -10,7 +26,9 @@ import org.springframework.context.support.ClassPathXmlApplicationContext; * @author Josh Long */ public class OutboundFtpExample { + public static void main(String[] args) throws Throwable { - ClassPathXmlApplicationContext classPathXmlApplicationContext = new ClassPathXmlApplicationContext("outbound-ftp-context.xml"); + new ClassPathXmlApplicationContext("outbound-ftp-context.xml"); } + } diff --git a/spring-integration-ftp/src/test/java/org/springframework/integration/ftp/OutboundFtpsExample.java b/spring-integration-ftp/src/test/java/org/springframework/integration/ftp/OutboundFtpsExample.java index 3fe0060c53..73829b24df 100644 --- a/spring-integration-ftp/src/test/java/org/springframework/integration/ftp/OutboundFtpsExample.java +++ b/spring-integration-ftp/src/test/java/org/springframework/integration/ftp/OutboundFtpsExample.java @@ -1,3 +1,19 @@ +/* + * Copyright 2002-2010 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package org.springframework.integration.ftp; import org.springframework.context.support.ClassPathXmlApplicationContext; @@ -10,7 +26,9 @@ import org.springframework.context.support.ClassPathXmlApplicationContext; * @author Josh Long */ public class OutboundFtpsExample { + public static void main(String[] args) throws Throwable { - ClassPathXmlApplicationContext classPathXmlApplicationContext = new ClassPathXmlApplicationContext("outbound-ftps-context.xml"); + new ClassPathXmlApplicationContext("outbound-ftps-context.xml"); } + } From fae066e48e411076afe059d103685e684d0cd65f Mon Sep 17 00:00:00 2001 From: Oleg Zhurakousky Date: Fri, 5 Nov 2010 15:35:02 -0400 Subject: [PATCH 66/82] INT-1553, Initial overhaul and simplification to the OAuth package, tests --- .../twitter/config/ConnectionParser.java | 32 ++-- .../TwitterReceivingMessageSourceParser.java | 2 +- .../TwitterSendingMessageHandlerParser.java | 2 +- .../inbound/AbstractTwitterMessageSource.java | 20 +- .../DirectMessageReceivingMessageSource.java | 5 + .../MentionReceivingMessageSource.java | 4 + .../TimelineUpdateReceivingMessageSource.java | 6 +- ...tractOAuthAccessTokenBasedFactoryBean.java | 176 ------------------ ...essTokenInitialRequestProcessListener.java | 36 ---- ...uthAccessTokenBasedTwitterFactoryBean.java | 66 ------- .../twitter/oauth/OAuthConfiguration.java | 88 --------- .../oauth/OAuthConfigurationFactoryBean.java | 101 ---------- .../oauth/OAuthTwitterFactoryBean.java | 68 +++++++ ...bstractOutboundTwitterEndpointSupport.java | 25 +-- .../DirectMessageSendingMessageHandler.java | 5 + .../TimelineUpdateSendingMessageHandler.java | 6 + ...stReceivingMessageSourceParser-context.xml | 14 +- ...estSendingMessageHandlerParser-context.xml | 15 +- .../TestSendingMessageHandlerParserTests.java | 25 --- .../TwitterConnectionParserTests-context.xml | 22 +++ .../config/TwitterConnectionParserTests.java | 50 +++++ ...boundDirectMessageStatusEndpointTests.java | 46 ++--- ...essTokenInitialRequestProcessListener.java | 121 ------------ ...boundDirectMessageMessageHandlerTests.java | 17 +- 24 files changed, 250 insertions(+), 702 deletions(-) delete mode 100644 spring-integration-twitter/src/main/java/org/springframework/integration/twitter/oauth/AbstractOAuthAccessTokenBasedFactoryBean.java delete mode 100644 spring-integration-twitter/src/main/java/org/springframework/integration/twitter/oauth/AccessTokenInitialRequestProcessListener.java delete mode 100644 spring-integration-twitter/src/main/java/org/springframework/integration/twitter/oauth/OAuthAccessTokenBasedTwitterFactoryBean.java delete mode 100644 spring-integration-twitter/src/main/java/org/springframework/integration/twitter/oauth/OAuthConfiguration.java delete mode 100644 spring-integration-twitter/src/main/java/org/springframework/integration/twitter/oauth/OAuthConfigurationFactoryBean.java create mode 100644 spring-integration-twitter/src/main/java/org/springframework/integration/twitter/oauth/OAuthTwitterFactoryBean.java create mode 100644 spring-integration-twitter/src/test/java/org/springframework/integration/twitter/config/TwitterConnectionParserTests-context.xml create mode 100644 spring-integration-twitter/src/test/java/org/springframework/integration/twitter/config/TwitterConnectionParserTests.java delete mode 100644 spring-integration-twitter/src/test/java/org/springframework/integration/twitter/oauth/ConsoleBasedAccessTokenInitialRequestProcessListener.java diff --git a/spring-integration-twitter/src/main/java/org/springframework/integration/twitter/config/ConnectionParser.java b/spring-integration-twitter/src/main/java/org/springframework/integration/twitter/config/ConnectionParser.java index cf4221291b..17f5f3da90 100644 --- a/spring-integration-twitter/src/main/java/org/springframework/integration/twitter/config/ConnectionParser.java +++ b/spring-integration-twitter/src/main/java/org/springframework/integration/twitter/config/ConnectionParser.java @@ -18,13 +18,10 @@ package org.springframework.integration.twitter.config; import static org.springframework.integration.twitter.config.TwitterNamespaceHandler.BASE_PACKAGE; -import org.w3c.dom.Element; - import org.springframework.beans.factory.support.BeanDefinitionBuilder; import org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser; import org.springframework.beans.factory.xml.ParserContext; -import org.springframework.integration.config.xml.IntegrationNamespaceUtils; -import org.springframework.util.StringUtils; +import org.w3c.dom.Element; /** * Parser for the 'twitter-connection' element. @@ -37,7 +34,7 @@ public class ConnectionParser extends AbstractSingleBeanDefinitionParser { @Override protected String getBeanClassName(Element element) { - return BASE_PACKAGE + ".oauth.OAuthConfigurationFactoryBean"; + return BASE_PACKAGE + ".oauth.OAuthTwitterFactoryBean"; } @Override @@ -47,15 +44,22 @@ public class ConnectionParser extends AbstractSingleBeanDefinitionParser { @Override protected void doParse(Element element, ParserContext parserContext, BeanDefinitionBuilder builder) { - String ref = element.getAttribute("twitter-connection"); - if (StringUtils.hasText(ref)) { - builder.addPropertyReference("twitterConnection", ref); - } - else { - for (String attribute : new String[] { "consumer-key", "consumer-secret", "access-token", "access-token-secret" }) { - IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, attribute); - } - } +// String ref = element.getAttribute("twitter-connection"); +// if (StringUtils.hasText(ref)) { +// builder.addPropertyReference("twitterConnection", ref); +// } +// else { +// for (String attribute : new String[] { "consumer-key", "consumer-secret", "access-token", "access-token-secret" }) { +// IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, attribute); +// } +// } + + BeanDefinitionBuilder accessTokenBuilder = BeanDefinitionBuilder.genericBeanDefinition("twitter4j.http.AccessToken"); + accessTokenBuilder.addConstructorArgValue(element.getAttribute("access-token")); + accessTokenBuilder.addConstructorArgValue(element.getAttribute("access-token-secret")); + builder.addConstructorArgValue(element.getAttribute("consumer-key")); + builder.addConstructorArgValue(element.getAttribute("consumer-secret")); + builder.addConstructorArgValue(accessTokenBuilder.getBeanDefinition()); } } diff --git a/spring-integration-twitter/src/main/java/org/springframework/integration/twitter/config/TwitterReceivingMessageSourceParser.java b/spring-integration-twitter/src/main/java/org/springframework/integration/twitter/config/TwitterReceivingMessageSourceParser.java index ad2f7c9185..6babd4dc9d 100644 --- a/spring-integration-twitter/src/main/java/org/springframework/integration/twitter/config/TwitterReceivingMessageSourceParser.java +++ b/spring-integration-twitter/src/main/java/org/springframework/integration/twitter/config/TwitterReceivingMessageSourceParser.java @@ -53,7 +53,7 @@ public class TwitterReceivingMessageSourceParser extends AbstractPollingInboundC parserContext.getReaderContext().error("element '" + elementName + "' is not supported by this parser.", element); } BeanDefinitionBuilder builder = BeanDefinitionBuilder.rootBeanDefinition(className); - IntegrationNamespaceUtils.setReferenceIfAttributeDefined(builder, element, "twitter-connection", "configuration"); + builder.addConstructorArgReference(element.getAttribute("twitter-connection")); IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, "auto-startup"); String name = BeanDefinitionReaderUtils.registerWithGeneratedName(builder.getBeanDefinition(), parserContext.getRegistry()); return new RuntimeBeanReference(name); diff --git a/spring-integration-twitter/src/main/java/org/springframework/integration/twitter/config/TwitterSendingMessageHandlerParser.java b/spring-integration-twitter/src/main/java/org/springframework/integration/twitter/config/TwitterSendingMessageHandlerParser.java index 196e2622fb..2803f13b42 100644 --- a/spring-integration-twitter/src/main/java/org/springframework/integration/twitter/config/TwitterSendingMessageHandlerParser.java +++ b/spring-integration-twitter/src/main/java/org/springframework/integration/twitter/config/TwitterSendingMessageHandlerParser.java @@ -46,7 +46,7 @@ public class TwitterSendingMessageHandlerParser extends AbstractOutboundChannelA className = BASE_PACKAGE + ".outbound.DirectMessageSendingMessageHandler"; } BeanDefinitionBuilder builder = BeanDefinitionBuilder.rootBeanDefinition(className); - IntegrationNamespaceUtils.setReferenceIfAttributeDefined(builder, element, "twitter-connection", "configuration"); + builder.addConstructorArgReference(element.getAttribute("twitter-connection")); return builder.getBeanDefinition(); } diff --git a/spring-integration-twitter/src/main/java/org/springframework/integration/twitter/inbound/AbstractTwitterMessageSource.java b/spring-integration-twitter/src/main/java/org/springframework/integration/twitter/inbound/AbstractTwitterMessageSource.java index d927bb4738..d3f0611633 100644 --- a/spring-integration-twitter/src/main/java/org/springframework/integration/twitter/inbound/AbstractTwitterMessageSource.java +++ b/spring-integration-twitter/src/main/java/org/springframework/integration/twitter/inbound/AbstractTwitterMessageSource.java @@ -33,7 +33,6 @@ import org.springframework.integration.history.TrackableComponent; import org.springframework.integration.store.MetadataStore; import org.springframework.integration.store.SimpleMetadataStore; import org.springframework.integration.support.MessageBuilder; -import org.springframework.integration.twitter.oauth.OAuthConfiguration; import org.springframework.util.Assert; import org.springframework.util.StringUtils; @@ -62,15 +61,13 @@ public abstract class AbstractTwitterMessageSource extends AbstractEndpoint private volatile String metadataKey; - protected volatile OAuthConfiguration configuration; - protected final Queue tweets = new LinkedBlockingQueue(); protected volatile int prefetchThreshold = 0; protected volatile long markerId = -1; - protected Twitter twitter; + protected final Twitter twitter; private final Object markerGuard = new Object(); @@ -78,10 +75,13 @@ public abstract class AbstractTwitterMessageSource extends AbstractEndpoint private final HistoryWritingMessagePostProcessor historyWritingPostProcessor = new HistoryWritingMessagePostProcessor(); - - public void setConfiguration(OAuthConfiguration configuration) { - this.configuration = configuration; + public AbstractTwitterMessageSource(Twitter twitter){ + this.twitter = twitter; } +// +// public void setConfiguration(OAuthConfiguration configuration) { +// this.configuration = configuration; +// } public void setShouldTrack(boolean shouldTrack) { this.historyWritingPostProcessor.setShouldTrack(shouldTrack); @@ -98,7 +98,7 @@ public abstract class AbstractTwitterMessageSource extends AbstractEndpoint @Override protected void onInit() throws Exception{ super.onInit(); - Assert.notNull(this.configuration, "'configuration' can't be null"); + //Assert.notNull(this.configuration, "'configuration' can't be null"); if (this.metadataStore == null) { // first try to look for a 'messageStore' in the context BeanFactory beanFactory = this.getBeanFactory(); @@ -122,7 +122,7 @@ public abstract class AbstractTwitterMessageSource extends AbstractEndpoint else if (logger.isWarnEnabled()) { logger.warn(this.getClass().getSimpleName() + " has no name. MetadataStore key might not be unique."); } - metadataKeyBuilder.append(this.configuration.getConsumerKey()); + //metadataKeyBuilder.append(this.configuration.getConsumerKey()); this.metadataKey = metadataKeyBuilder.toString(); } @@ -146,7 +146,7 @@ public abstract class AbstractTwitterMessageSource extends AbstractEndpoint @Override protected void doStart(){ - this.twitter = this.configuration.getTwitter(); + //this.twitter = this.configuration.getTwitter(); Assert.notNull(this.twitter, "'twitter' instance can't be null"); historyWritingPostProcessor.setTrackableComponent(this); RateLimitStatusTrigger trigger = new RateLimitStatusTrigger(this.twitter); diff --git a/spring-integration-twitter/src/main/java/org/springframework/integration/twitter/inbound/DirectMessageReceivingMessageSource.java b/spring-integration-twitter/src/main/java/org/springframework/integration/twitter/inbound/DirectMessageReceivingMessageSource.java index 7b50d037c8..6b9d1ff94d 100644 --- a/spring-integration-twitter/src/main/java/org/springframework/integration/twitter/inbound/DirectMessageReceivingMessageSource.java +++ b/spring-integration-twitter/src/main/java/org/springframework/integration/twitter/inbound/DirectMessageReceivingMessageSource.java @@ -22,6 +22,7 @@ import org.springframework.integration.MessagingException; import twitter4j.DirectMessage; import twitter4j.Paging; +import twitter4j.Twitter; /** * This class handles support for receiving DMs (direct messages) using Twitter. @@ -32,6 +33,10 @@ import twitter4j.Paging; */ public class DirectMessageReceivingMessageSource extends AbstractTwitterMessageSource { + public DirectMessageReceivingMessageSource(Twitter twitter){ + super(twitter); + } + @Override public String getComponentType() { return "twitter:inbound-dm-channel-adapter"; diff --git a/spring-integration-twitter/src/main/java/org/springframework/integration/twitter/inbound/MentionReceivingMessageSource.java b/spring-integration-twitter/src/main/java/org/springframework/integration/twitter/inbound/MentionReceivingMessageSource.java index 658bb70d85..44ae57bf5c 100644 --- a/spring-integration-twitter/src/main/java/org/springframework/integration/twitter/inbound/MentionReceivingMessageSource.java +++ b/spring-integration-twitter/src/main/java/org/springframework/integration/twitter/inbound/MentionReceivingMessageSource.java @@ -21,6 +21,7 @@ import org.springframework.integration.MessagingException; import twitter4j.Paging; import twitter4j.Status; +import twitter4j.Twitter; /** * Handles forwarding all new {@link twitter4j.Status} that are 'replies' or 'mentions' to some other tweet. @@ -30,6 +31,9 @@ import twitter4j.Status; */ public class MentionReceivingMessageSource extends AbstractTwitterMessageSource { + public MentionReceivingMessageSource(Twitter twitter){ + super(twitter); + } @Override public String getComponentType() { return "twitter:inbound-mention-channel-adapter"; diff --git a/spring-integration-twitter/src/main/java/org/springframework/integration/twitter/inbound/TimelineUpdateReceivingMessageSource.java b/spring-integration-twitter/src/main/java/org/springframework/integration/twitter/inbound/TimelineUpdateReceivingMessageSource.java index c8a1d9e610..ef63cae268 100644 --- a/spring-integration-twitter/src/main/java/org/springframework/integration/twitter/inbound/TimelineUpdateReceivingMessageSource.java +++ b/spring-integration-twitter/src/main/java/org/springframework/integration/twitter/inbound/TimelineUpdateReceivingMessageSource.java @@ -19,6 +19,7 @@ import org.springframework.integration.MessagingException; import twitter4j.Paging; import twitter4j.Status; +import twitter4j.Twitter; /** @@ -30,7 +31,10 @@ import twitter4j.Status; * @since 2.0 */ public class TimelineUpdateReceivingMessageSource extends AbstractTwitterMessageSource { - + + public TimelineUpdateReceivingMessageSource(Twitter twitter){ + super(twitter); + } @Override public String getComponentType() { return "twitter:inbound-update-channel-adapter"; diff --git a/spring-integration-twitter/src/main/java/org/springframework/integration/twitter/oauth/AbstractOAuthAccessTokenBasedFactoryBean.java b/spring-integration-twitter/src/main/java/org/springframework/integration/twitter/oauth/AbstractOAuthAccessTokenBasedFactoryBean.java deleted file mode 100644 index f5f34acd11..0000000000 --- a/spring-integration-twitter/src/main/java/org/springframework/integration/twitter/oauth/AbstractOAuthAccessTokenBasedFactoryBean.java +++ /dev/null @@ -1,176 +0,0 @@ -/* - * Copyright 2010 the original author or authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.integration.twitter.oauth; - -import java.util.Properties; - -import org.springframework.beans.factory.FactoryBean; -import org.springframework.beans.factory.InitializingBean; -import org.springframework.beans.factory.config.PropertiesFactoryBean; -import org.springframework.core.io.Resource; -import org.springframework.util.Assert; -import org.springframework.util.StringUtils; - -import twitter4j.http.AccessToken; -import twitter4j.http.RequestToken; - - -/** - * base-class for {@link org.springframework.integration.twitter.oauth.OAuthAccessTokenBasedTwitterFactoryBean}. - *

- * Provides hooks so that subclasses able to reference a concrete implementation of the generic type parameter can call methods for us. Most hooks are to handle the case - * of the first time subscription, where no accessToken is present. - * - * @author Josh Long - * @param - * @see org.springframework.integration.twitter.oauth.OAuthAccessTokenBasedTwitterFactoryBean - * @since 2.0 - */ -abstract public class AbstractOAuthAccessTokenBasedFactoryBean implements InitializingBean, FactoryBean { - protected OAuthConfiguration configuration; - protected final Object monitor = new Object(); - protected volatile T twitter; - protected volatile boolean initialized = false; - - /** - * Standard {@link org.springframework.beans.factory.FactoryBean} method. Implementations may override if there's a specific method - * - * @return whether or not this is a singleton - */ - public boolean isSingleton() { - return true; - } - - /** - * Rubber meets the road: builds up a reference to the twitter4j.(Async)Twitter instance - * - * @return the instance - * @throws Exception thrown in case some condition isn't met correctly in construction - */ - public T getObject() throws Exception { - if (!initialized) { - afterPropertiesSet(); - } - - return this.twitter; - } - /** - * provides lifecycle for initiation of the reference. By the time this method is left we should have a fully configured twitter connection that can connect and make calls - * - * @throws Exception - */ - public void afterPropertiesSet() throws Exception { - synchronized (this.monitor) { - - Assert.notNull(this.configuration.getConsumerKey(), "'consumerKey' mustn't be null"); - Assert.notNull(this.configuration.getConsumerSecret(), "'consumerSecret' mustn't be null"); - - AccessToken accessTokenObj=null; - establishTwitterObject(accessTokenObj); - if (StringUtils.hasText(this.configuration.getAccessToken()) && StringUtils.hasText(this.configuration.getAccessTokenSecret())) { - accessTokenObj = new AccessToken(this.configuration.getAccessToken(), this.configuration.getAccessTokenSecret()); - } - establishTwitterObject(accessTokenObj); - - Assert.notNull(accessTokenObj, "'accessTokenObj' can't be null"); - - this.initialized = true; - } - } - /** - * Nasty little bit of circular indirection here: the {@link org.springframework.integration.twitter.oauth.OAuthConfiguration} hosts the String values for authentication, - * which we need to build up this instance, but the {@link org.springframework.integration.twitter.oauth.OAuthConfiguration} in turn needs references to the instances provided by - * this {@link org.springframework.beans.factory.FactoryBean}. So, they collaborate and guard each others state. Ultimately, clients should use {@link org.springframework.integration.twitter.oauth.OAuthConfiguration} - * to correctly any implementations of this factory bean as well as the {@link org.springframework.integration.twitter.oauth.OAuthConfiguration} reference itself. - * - * @param configuration the configuration object - */ - protected AbstractOAuthAccessTokenBasedFactoryBean(OAuthConfiguration configuration) { - this.configuration = configuration; - } - - /** - * This probably doesn't belong here. It's more for support for running the {@link OAuthAccessTokenBasedTwitterFactoryBean} or - * {@link OAuthAccessTokenBasedTwitterFactoryBean} methods that run the user through a command line tool to approve a user for the first - * time if the user hasn't obtained her {@code accessToken } yet - * - * @param resource the resource where properties file lives - * @return returns a fully configured {@link java.util.Properties} instance - * @throws Exception thrown if anythign goes wrong - */ - protected static Properties fromResource(Resource resource) - throws Exception { - PropertiesFactoryBean propertiesFactoryBean = new PropertiesFactoryBean(); - propertiesFactoryBean.setLocation(resource); - propertiesFactoryBean.setSingleton(true); - propertiesFactoryBean.afterPropertiesSet(); - - return propertiesFactoryBean.getObject(); - } - - public abstract void establishTwitterObject(AccessToken accessToken) - throws Exception; - - /** - * because we are not able to dereference the {@link twitter4j.Twitter} or {@link twitter4j.AsyncTwitter} instances, we need to ask subclasses to call - * us how to call {@link twitter4j.AsyncTwitter#getOAuthRequestToken()} or {@link twitter4j.Twitter#getOAuthRequestToken()} for us.This method - * will never be evaluated as long as the {@link org.springframework.integration.twitter.oauth.OAuthConfiguration#accessToken} - * and {@link org.springframework.integration.twitter.oauth.OAuthConfiguration#accessTokenSecret} beans are not null. - * - * @return the {@link twitter4j.http.RequestToken} as vended by the service. Ths will contain a verification URl required to obtain an access key and secret. - * @throws Exception thrown if anything should go wrong - */ - public abstract RequestToken getOAuthRequestToken() - throws Exception; - - /** - * Only used if the impementation is trying to get an {@link twitter4j.http.AccessToken} for the first time. This method - * will never be evaluated as long as the {@link org.springframework.integration.twitter.oauth.OAuthConfiguration#accessToken} - * and {@link org.springframework.integration.twitter.oauth.OAuthConfiguration#accessTokenSecret} beans are not null. - * - * @param token the initiating {@link twitter4j.http.RequestToken} - * @param pin the string returned from the verification URL - * @return returns the {@link twitter4j.http.AccessToken} fetched from the twitter service. - * @throws Exception thrown if anything should go wrong - */ - public abstract AccessToken getOAuthAccessToken(RequestToken token, String pin) - throws Exception; - - /** - * Only used if the impementation is trying to get an {@link twitter4j.http.AccessToken} for the first time. This method - * will never be evaluated as long as the {@link org.springframework.integration.twitter.oauth.OAuthConfiguration#accessToken} - * and {@link org.springframework.integration.twitter.oauth.OAuthConfiguration#accessTokenSecret} beans are not null. - * - * @return returns the {@link twitter4j.http.AccessToken} fetched from the twitter service. - * @throws Exception thrown if anything should go wrong - */ - public abstract AccessToken getOAuthAccessToken() throws Exception; - - /** - * Responsibility of subclasses to call this because we cant dereference the generic type appropriately. The responsibility is - * to call {@link twitter4j.Twitter#verifyCredentials()} or {@link twitter4j.AsyncTwitter#verifyCredentials()} as appropriate - * - * @throws Exception if there's an inability to authenticate - */ - public abstract void verifyCredentials() throws Exception; - - /** - * this method is delegated to implementations because we can't correctly dereference the generic type's class - * - * @return a class - */ - abstract public Class getObjectType(); -} diff --git a/spring-integration-twitter/src/main/java/org/springframework/integration/twitter/oauth/AccessTokenInitialRequestProcessListener.java b/spring-integration-twitter/src/main/java/org/springframework/integration/twitter/oauth/AccessTokenInitialRequestProcessListener.java deleted file mode 100644 index 3f40a34425..0000000000 --- a/spring-integration-twitter/src/main/java/org/springframework/integration/twitter/oauth/AccessTokenInitialRequestProcessListener.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright 2010 the original author or authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.integration.twitter.oauth; - -import twitter4j.http.AccessToken; - - -/** - * if the factory bean isn't provided a 'accesstoken' and 'accesstokensecret', then it will try to obtain those bits of informatio on the users behalf. - *

- * In doing so it will need input fro the user (automatic or human intervention is required) - * - * @author Josh Long - * @since 2.0 - */ -public interface AccessTokenInitialRequestProcessListener { - - String openUrlAndReturnPin(String urlToOpen) throws Exception; - - void persistReturnedAccessToken(AccessToken accessToken) throws Exception; - - void failure(Throwable t); -} diff --git a/spring-integration-twitter/src/main/java/org/springframework/integration/twitter/oauth/OAuthAccessTokenBasedTwitterFactoryBean.java b/spring-integration-twitter/src/main/java/org/springframework/integration/twitter/oauth/OAuthAccessTokenBasedTwitterFactoryBean.java deleted file mode 100644 index 9b99bb7e26..0000000000 --- a/spring-integration-twitter/src/main/java/org/springframework/integration/twitter/oauth/OAuthAccessTokenBasedTwitterFactoryBean.java +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright 2010 the original author or authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.integration.twitter.oauth; - -import twitter4j.Twitter; -import twitter4j.TwitterFactory; -import twitter4j.http.AccessToken; -import twitter4j.http.RequestToken; - -/** - * - * @author Josh Long - * @since 2.0 - */ -public class OAuthAccessTokenBasedTwitterFactoryBean extends AbstractOAuthAccessTokenBasedFactoryBean { - protected OAuthAccessTokenBasedTwitterFactoryBean(OAuthConfiguration configuration) { - super(configuration); - } - - @Override - public void establishTwitterObject(AccessToken accessToken) - throws Exception { - this.twitter = new TwitterFactory().getOAuthAuthorizedInstance(this.configuration.getConsumerKey(), this.configuration.getConsumerSecret(), accessToken); - } - - @Override - public RequestToken getOAuthRequestToken() throws Exception { - return twitter.getOAuthRequestToken(); - } - - @Override - public void verifyCredentials() throws Exception { - this.twitter.verifyCredentials(); - } - - @Override - public AccessToken getOAuthAccessToken(RequestToken token, String pin) - throws Exception { - return this.twitter.getOAuthAccessToken(token, pin); - } - - @Override - public AccessToken getOAuthAccessToken() throws Exception { - return this.twitter.getOAuthAccessToken(); - } - - @Override - public Class getObjectType() { - return Twitter.class; - } - - -} diff --git a/spring-integration-twitter/src/main/java/org/springframework/integration/twitter/oauth/OAuthConfiguration.java b/spring-integration-twitter/src/main/java/org/springframework/integration/twitter/oauth/OAuthConfiguration.java deleted file mode 100644 index e2857756e7..0000000000 --- a/spring-integration-twitter/src/main/java/org/springframework/integration/twitter/oauth/OAuthConfiguration.java +++ /dev/null @@ -1,88 +0,0 @@ -/* - * Copyright 2010 the original author or authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.integration.twitter.oauth; - -import twitter4j.Twitter; - - -/** - * Simple bean we can use to store the configuration and store shared references to both an {@link twitter4j.AsyncTwitter} - * and an {@link twitter4j.Twitter} instance. - *

- * client should store this bean and simply lookup the Twitter configuration from there - * @author Josh Long - * @since 2.0 - */ -public class OAuthConfiguration { - - private Twitter twitter; - private volatile String consumerKey; - private volatile String consumerSecret; - private volatile String accessToken; - private volatile String accessTokenSecret; - - public OAuthConfiguration(String consumerKey, String consumerSecret, String accessToken, String accessTokenSecret) { - this.consumerKey = consumerKey; - this.consumerSecret = consumerSecret; - this.accessToken = accessToken; - this.accessTokenSecret = accessTokenSecret; - } - - void setTwitter(Twitter twitter) { - this.twitter = twitter; - } - - /** - * @return - */ - public Twitter getTwitter() { - return twitter; - } - - - - public String getConsumerKey() { - return consumerKey; - } - - public void setConsumerKey(String consumerKey) { - this.consumerKey = consumerKey; - } - - public String getConsumerSecret() { - return consumerSecret; - } - - public void setConsumerSecret(String consumerSecret) { - this.consumerSecret = consumerSecret; - } - - public String getAccessToken() { - return accessToken; - } - - public void setAccessToken(String accessToken) { - this.accessToken = accessToken; - } - - public String getAccessTokenSecret() { - return accessTokenSecret; - } - - public void setAccessTokenSecret(String accessTokenSecret) { - this.accessTokenSecret = accessTokenSecret; - } -} diff --git a/spring-integration-twitter/src/main/java/org/springframework/integration/twitter/oauth/OAuthConfigurationFactoryBean.java b/spring-integration-twitter/src/main/java/org/springframework/integration/twitter/oauth/OAuthConfigurationFactoryBean.java deleted file mode 100644 index c34c1fcbb2..0000000000 --- a/spring-integration-twitter/src/main/java/org/springframework/integration/twitter/oauth/OAuthConfigurationFactoryBean.java +++ /dev/null @@ -1,101 +0,0 @@ -/* - * Copyright 2010 the original author or authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.integration.twitter.oauth; - -import org.springframework.beans.factory.FactoryBean; -import org.springframework.util.Assert; -import twitter4j.Twitter; - -import java.util.Properties; - - -/** - * Center piece for configuration for all the twitter adapters - * - * @author Josh Long - * @since 2.0 - */ -public class OAuthConfigurationFactoryBean implements FactoryBean { - public static final String WELL_KNOWN_CONSUMER_KEY = "twitter.oauth.consumerKey"; - public static final String WELL_KNOWN_CONSUMER_KEY_SECRET = "twitter.oauth.consumerSecret"; - public static final String WELL_KNOWN_CONSUMER_ACCESS_TOKEN = "twitter.oauth.accessToken"; - public static final String WELL_KNOWN_CONSUMER_ACCESS_TOKEN_SECRET = "twitter.oauth.accessTokenSecret"; - private volatile String consumerKey; - private volatile String consumerSecret; - private volatile String accessToken; - private volatile String accessTokenSecret; - private Twitter twitter; - private volatile OAuthConfiguration oAuthConfiguration; - private final Object guard = new Object(); - - private Twitter twitter(OAuthConfiguration oAuthConfiguration) - throws Exception { - OAuthAccessTokenBasedTwitterFactoryBean twitterFactoryBean = new OAuthAccessTokenBasedTwitterFactoryBean(oAuthConfiguration); - twitterFactoryBean.afterPropertiesSet(); - twitterFactoryBean.verifyCredentials(); - - return twitterFactoryBean.getObject(); - } - - protected void bootstrapFromProperties(Properties props) - throws Throwable { - Assert.notNull(props, "'properties' must not be null"); - this.setAccessToken(props.getProperty(WELL_KNOWN_CONSUMER_ACCESS_TOKEN)); - this.setAccessTokenSecret(props.getProperty(WELL_KNOWN_CONSUMER_ACCESS_TOKEN_SECRET)); - this.setConsumerKey(props.getProperty(WELL_KNOWN_CONSUMER_KEY)); - this.setConsumerSecret(props.getProperty(WELL_KNOWN_CONSUMER_KEY_SECRET)); - } - - public OAuthConfiguration getObject() throws Exception { - return build(); - } - - public Class getObjectType() { - return OAuthConfiguration.class; - } - - public boolean isSingleton() { - return true; - } - - public void setConsumerKey(String consumerKey) { - this.consumerKey = consumerKey; - } - - public void setConsumerSecret(String consumerSecret) { - this.consumerSecret = consumerSecret; - } - - public void setAccessToken(String accessToken) { - this.accessToken = accessToken; - } - - public void setAccessTokenSecret(String accessTokenSecret) { - this.accessTokenSecret = accessTokenSecret; - } - - private OAuthConfiguration build() throws Exception { - synchronized (this.guard) { - if (oAuthConfiguration == null) { - oAuthConfiguration = new OAuthConfiguration(this.consumerKey, this.consumerSecret, this.accessToken, this.accessTokenSecret); - twitter = this.twitter(oAuthConfiguration); - oAuthConfiguration.setTwitter(twitter); - } - } - - return this.oAuthConfiguration; - } -} diff --git a/spring-integration-twitter/src/main/java/org/springframework/integration/twitter/oauth/OAuthTwitterFactoryBean.java b/spring-integration-twitter/src/main/java/org/springframework/integration/twitter/oauth/OAuthTwitterFactoryBean.java new file mode 100644 index 0000000000..4cf1c5e748 --- /dev/null +++ b/spring-integration-twitter/src/main/java/org/springframework/integration/twitter/oauth/OAuthTwitterFactoryBean.java @@ -0,0 +1,68 @@ +/* + * Copyright 2002-2010 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.integration.twitter.oauth; + +import org.springframework.beans.factory.FactoryBean; +import org.springframework.beans.factory.InitializingBean; +import org.springframework.util.Assert; + +import twitter4j.Twitter; +import twitter4j.TwitterFactory; +import twitter4j.http.AccessToken; + +/** + * Will create an OAuth-Authorized instance of Twitter object. + * + * @author Oleg Zhurakousky + * @since 2.0 + */ +public class OAuthTwitterFactoryBean implements FactoryBean, InitializingBean { + private final String consumerKey; + private final String consumerSecret; + private final AccessToken accessToken; + + private volatile Twitter twitter; + + public OAuthTwitterFactoryBean(String consumerKey, String consumerSecret, AccessToken accessToken){ + Assert.hasText(consumerKey, "'consumerKey' must be provided"); + Assert.hasText(consumerSecret, "'consumerSecret' must be provided"); + Assert.notNull(accessToken, "'accessToken' must be provided"); + this.consumerKey = consumerKey; + this.consumerSecret = consumerSecret; + this.accessToken = accessToken; + } + @Override + public Twitter getObject() throws Exception { + Assert.notNull(this.twitter, "OAuthTwitterFactoryBean must be initialized. Invoke afterPropertiesSet() method"); + return twitter; + } + + @Override + public Class getObjectType() { + return Twitter.class; + } + + @Override + public boolean isSingleton() { + return true; + } + + @Override + public void afterPropertiesSet() throws Exception { + this.twitter = new TwitterFactory().getOAuthAuthorizedInstance(consumerKey, consumerSecret, accessToken); + } + +} diff --git a/spring-integration-twitter/src/main/java/org/springframework/integration/twitter/outbound/AbstractOutboundTwitterEndpointSupport.java b/spring-integration-twitter/src/main/java/org/springframework/integration/twitter/outbound/AbstractOutboundTwitterEndpointSupport.java index 8b837488ad..2193fb0612 100644 --- a/spring-integration-twitter/src/main/java/org/springframework/integration/twitter/outbound/AbstractOutboundTwitterEndpointSupport.java +++ b/spring-integration-twitter/src/main/java/org/springframework/integration/twitter/outbound/AbstractOutboundTwitterEndpointSupport.java @@ -16,7 +16,6 @@ package org.springframework.integration.twitter.outbound; import org.springframework.integration.handler.AbstractMessageHandler; -import org.springframework.integration.twitter.oauth.OAuthConfiguration; import org.springframework.util.Assert; import twitter4j.Twitter; @@ -29,19 +28,23 @@ import twitter4j.Twitter; * @since 2.0 */ public abstract class AbstractOutboundTwitterEndpointSupport extends AbstractMessageHandler { - protected volatile OAuthConfiguration configuration; - protected volatile Twitter twitter; + //protected volatile OAuthConfiguration configuration; + protected final Twitter twitter; protected final OutboundStatusUpdateMessageMapper supportStatusUpdate = new OutboundStatusUpdateMessageMapper(); - public void setConfiguration(OAuthConfiguration configuration) { - this.configuration = configuration; + public AbstractOutboundTwitterEndpointSupport(Twitter twitter){ + Assert.notNull(twitter, "'twitter' must not be null"); + this.twitter = twitter; } +// public void setConfiguration(OAuthConfiguration configuration) { +// this.configuration = configuration; +// } - @Override - protected void onInit() throws Exception { - Assert.notNull(this.configuration, "'configuration' can't be null"); - this.twitter = this.configuration.getTwitter(); - Assert.notNull(this.twitter, "'twitter' can't be null"); - } +// @Override +// protected void onInit() throws Exception { +// Assert.notNull(this.configuration, "'configuration' can't be null"); +// this.twitter = this.configuration.getTwitter(); +// Assert.notNull(this.twitter, "'twitter' can't be null"); +// } } diff --git a/spring-integration-twitter/src/main/java/org/springframework/integration/twitter/outbound/DirectMessageSendingMessageHandler.java b/spring-integration-twitter/src/main/java/org/springframework/integration/twitter/outbound/DirectMessageSendingMessageHandler.java index 157cdedd10..3832523ff7 100644 --- a/spring-integration-twitter/src/main/java/org/springframework/integration/twitter/outbound/DirectMessageSendingMessageHandler.java +++ b/spring-integration-twitter/src/main/java/org/springframework/integration/twitter/outbound/DirectMessageSendingMessageHandler.java @@ -21,6 +21,7 @@ import org.springframework.integration.MessageHandlingException; import org.springframework.integration.twitter.core.TwitterHeaders; import org.springframework.util.Assert; +import twitter4j.Twitter; import twitter4j.TwitterException; /** @@ -32,6 +33,10 @@ import twitter4j.TwitterException; */ public class DirectMessageSendingMessageHandler extends AbstractOutboundTwitterEndpointSupport { + public DirectMessageSendingMessageHandler(Twitter twitter){ + super(twitter); + } + @Override protected void handleMessageInternal(Message message) throws Exception { if (this.twitter == null) { diff --git a/spring-integration-twitter/src/main/java/org/springframework/integration/twitter/outbound/TimelineUpdateSendingMessageHandler.java b/spring-integration-twitter/src/main/java/org/springframework/integration/twitter/outbound/TimelineUpdateSendingMessageHandler.java index 170e920eca..a8813f035c 100644 --- a/spring-integration-twitter/src/main/java/org/springframework/integration/twitter/outbound/TimelineUpdateSendingMessageHandler.java +++ b/spring-integration-twitter/src/main/java/org/springframework/integration/twitter/outbound/TimelineUpdateSendingMessageHandler.java @@ -19,6 +19,7 @@ import org.springframework.integration.Message; import org.springframework.util.Assert; import twitter4j.StatusUpdate; +import twitter4j.Twitter; /** @@ -28,6 +29,11 @@ import twitter4j.StatusUpdate; * @since 2.0 */ public class TimelineUpdateSendingMessageHandler extends AbstractOutboundTwitterEndpointSupport { + + public TimelineUpdateSendingMessageHandler(Twitter twitter){ + super(twitter); + } + @Override protected void handleMessageInternal(Message message) throws Exception { StatusUpdate statusUpdate = this.supportStatusUpdate.fromMessage(message); diff --git a/spring-integration-twitter/src/test/java/org/springframework/integration/twitter/config/TestReceivingMessageSourceParser-context.xml b/spring-integration-twitter/src/test/java/org/springframework/integration/twitter/config/TestReceivingMessageSourceParser-context.xml index 2657da899a..57bdc3ade0 100644 --- a/spring-integration-twitter/src/test/java/org/springframework/integration/twitter/config/TestReceivingMessageSourceParser-context.xml +++ b/spring-integration-twitter/src/test/java/org/springframework/integration/twitter/config/TestReceivingMessageSourceParser-context.xml @@ -17,27 +17,29 @@ http://www.springframework.org/schema/lang http://www.springframework.org/schema/lang/spring-lang-3.0.xsd http://www.springframework.org/schema/integration/twitter http://www.springframework.org/schema/integration/twitter/spring-integration-twitter.xsd"> - - - + diff --git a/spring-integration-twitter/src/test/java/org/springframework/integration/twitter/config/TestSendingMessageHandlerParser-context.xml b/spring-integration-twitter/src/test/java/org/springframework/integration/twitter/config/TestSendingMessageHandlerParser-context.xml index 2a7d551034..044982aea1 100644 --- a/spring-integration-twitter/src/test/java/org/springframework/integration/twitter/config/TestSendingMessageHandlerParser-context.xml +++ b/spring-integration-twitter/src/test/java/org/springframework/integration/twitter/config/TestSendingMessageHandlerParser-context.xml @@ -14,18 +14,23 @@ http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.0.xsd http://www.springframework.org/schema/tool http://www.springframework.org/schema/tool/spring-tool-3.0.xsd - http://www.springframework.org/schema/lang http://www.springframework.org/schema/lang/spring-lang-3.0.xsd http://www.springframework.org/schema/integration/twitter http://www.springframework.org/schema/integration/twitter/spring-integration-twitter.xsd"> + http://www.springframework.org/schema/lang http://www.springframework.org/schema/lang/spring-lang-3.0.xsd + http://www.springframework.org/schema/integration/twitter http://www.springframework.org/schema/integration/twitter/spring-integration-twitter-2.0.xsd"> - - + + - + - + diff --git a/spring-integration-twitter/src/test/java/org/springframework/integration/twitter/config/TestSendingMessageHandlerParserTests.java b/spring-integration-twitter/src/test/java/org/springframework/integration/twitter/config/TestSendingMessageHandlerParserTests.java index cffd64cfc3..946193f0ab 100644 --- a/spring-integration-twitter/src/test/java/org/springframework/integration/twitter/config/TestSendingMessageHandlerParserTests.java +++ b/spring-integration-twitter/src/test/java/org/springframework/integration/twitter/config/TestSendingMessageHandlerParserTests.java @@ -15,15 +15,8 @@ */ package org.springframework.integration.twitter.config; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; - import org.junit.Test; -import org.springframework.beans.factory.FactoryBean; import org.springframework.context.support.ClassPathXmlApplicationContext; -import org.springframework.integration.twitter.oauth.OAuthConfiguration; - -import twitter4j.Twitter; /** * @author Oleg Zhurakousky @@ -36,22 +29,4 @@ public class TestSendingMessageHandlerParserTests { new ClassPathXmlApplicationContext("TestSendingMessageHandlerParser-context.xml", this.getClass()); // the fact that no exception was thrown satisfies this test } - - public static class MockOathConfigurationFactoryBean implements FactoryBean{ - - public OAuthConfiguration getObject() throws Exception { - OAuthConfiguration config = mock(OAuthConfiguration.class); - Twitter twitter = mock(Twitter.class); - when(config.getTwitter()).thenReturn(twitter); - return config; - } - - public Class getObjectType() { - return OAuthConfiguration.class; - } - - public boolean isSingleton() { - return true; - } - } } diff --git a/spring-integration-twitter/src/test/java/org/springframework/integration/twitter/config/TwitterConnectionParserTests-context.xml b/spring-integration-twitter/src/test/java/org/springframework/integration/twitter/config/TwitterConnectionParserTests-context.xml new file mode 100644 index 0000000000..20ef2561b1 --- /dev/null +++ b/spring-integration-twitter/src/test/java/org/springframework/integration/twitter/config/TwitterConnectionParserTests-context.xml @@ -0,0 +1,22 @@ + + + + + + + + + diff --git a/spring-integration-twitter/src/test/java/org/springframework/integration/twitter/config/TwitterConnectionParserTests.java b/spring-integration-twitter/src/test/java/org/springframework/integration/twitter/config/TwitterConnectionParserTests.java new file mode 100644 index 0000000000..0cbf5b1900 --- /dev/null +++ b/spring-integration-twitter/src/test/java/org/springframework/integration/twitter/config/TwitterConnectionParserTests.java @@ -0,0 +1,50 @@ +/* + * Copyright 2002-2010 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.integration.twitter.config; + +import static junit.framework.Assert.assertEquals; +import static junit.framework.Assert.assertNotNull; +import static junit.framework.Assert.assertTrue; + +import org.junit.Test; +import org.springframework.context.ApplicationContext; +import org.springframework.context.support.ClassPathXmlApplicationContext; +import org.springframework.integration.test.util.TestUtils; +import org.springframework.integration.twitter.oauth.OAuthTwitterFactoryBean; + +import twitter4j.Twitter; +import twitter4j.http.AccessToken; + +/** + * @author Oleg Zhurakousky + * @since 2.0 + * + */ +public class TwitterConnectionParserTests { + + @Test + public void testOAuthTwitterFactoryBean(){ + ApplicationContext ac = new ClassPathXmlApplicationContext("TwitterConnectionParserTests-context.xml", this.getClass()); + OAuthTwitterFactoryBean twitterFb = ac.getBean("&twitter", OAuthTwitterFactoryBean.class); + assertEquals("consumerKey", TestUtils.getPropertyValue(twitterFb, "consumerKey")); + assertEquals("consumerSecret", TestUtils.getPropertyValue(twitterFb, "consumerSecret")); + AccessToken accessToken = (AccessToken) TestUtils.getPropertyValue(twitterFb, "accessToken"); + assertEquals("accessToken", accessToken.getToken()); + assertEquals("accessTokenSecret", accessToken.getTokenSecret()); + Twitter twitter = ac.getBean("twitter", Twitter.class); + assertTrue(twitter.isOAuthEnabled()); + } +} diff --git a/spring-integration-twitter/src/test/java/org/springframework/integration/twitter/inbound/InboundDirectMessageStatusEndpointTests.java b/spring-integration-twitter/src/test/java/org/springframework/integration/twitter/inbound/InboundDirectMessageStatusEndpointTests.java index b10ba5a982..b3d99c2162 100644 --- a/spring-integration-twitter/src/test/java/org/springframework/integration/twitter/inbound/InboundDirectMessageStatusEndpointTests.java +++ b/spring-integration-twitter/src/test/java/org/springframework/integration/twitter/inbound/InboundDirectMessageStatusEndpointTests.java @@ -16,9 +16,6 @@ package org.springframework.integration.twitter.inbound; -import static junit.framework.Assert.assertEquals; -import static junit.framework.Assert.assertNotNull; -import static junit.framework.Assert.assertNull; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; @@ -30,11 +27,6 @@ import org.junit.Before; import org.junit.Test; import org.mockito.Mockito; -import org.springframework.integration.Message; -import org.springframework.integration.channel.QueueChannel; -import org.springframework.integration.twitter.oauth.OAuthConfiguration; -import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler; - import twitter4j.DirectMessage; import twitter4j.Paging; import twitter4j.RateLimitStatus; @@ -86,24 +78,24 @@ public class InboundDirectMessageStatusEndpointTests { } - @SuppressWarnings("unchecked") - private OAuthConfiguration getTestConfigurationForDirectMessages() throws Exception{ - OAuthConfiguration configuration = mock(OAuthConfiguration.class); - RateLimitStatus rateLimitStatus = mock(RateLimitStatus.class); - when(twitter.getRateLimitStatus()).thenReturn(rateLimitStatus); - when(configuration.getTwitter()).thenReturn(twitter); - when(rateLimitStatus.getSecondsUntilReset()).thenReturn(2464); - when(rateLimitStatus.getRemainingHits()).thenReturn(250); - - ResponseList responses = mock(ResponseList.class); - List testMessages = new ArrayList(); - testMessages.add(firstMessage); - testMessages.add(secondMessage); - - when(responses.iterator()).thenReturn(testMessages.iterator()); - when(twitter.getDirectMessages()).thenReturn(responses); - when(twitter.getDirectMessages(Mockito.any(Paging.class))).thenReturn(responses); - return configuration; - } +// @SuppressWarnings("unchecked") +// private OAuthConfiguration getTestConfigurationForDirectMessages() throws Exception{ +// OAuthConfiguration configuration = mock(OAuthConfiguration.class); +// RateLimitStatus rateLimitStatus = mock(RateLimitStatus.class); +// when(twitter.getRateLimitStatus()).thenReturn(rateLimitStatus); +// when(configuration.getTwitter()).thenReturn(twitter); +// when(rateLimitStatus.getSecondsUntilReset()).thenReturn(2464); +// when(rateLimitStatus.getRemainingHits()).thenReturn(250); +// +// ResponseList responses = mock(ResponseList.class); +// List testMessages = new ArrayList(); +// testMessages.add(firstMessage); +// testMessages.add(secondMessage); +// +// when(responses.iterator()).thenReturn(testMessages.iterator()); +// when(twitter.getDirectMessages()).thenReturn(responses); +// when(twitter.getDirectMessages(Mockito.any(Paging.class))).thenReturn(responses); +// return configuration; +// } } diff --git a/spring-integration-twitter/src/test/java/org/springframework/integration/twitter/oauth/ConsoleBasedAccessTokenInitialRequestProcessListener.java b/spring-integration-twitter/src/test/java/org/springframework/integration/twitter/oauth/ConsoleBasedAccessTokenInitialRequestProcessListener.java deleted file mode 100644 index 726eb4b871..0000000000 --- a/spring-integration-twitter/src/test/java/org/springframework/integration/twitter/oauth/ConsoleBasedAccessTokenInitialRequestProcessListener.java +++ /dev/null @@ -1,121 +0,0 @@ -/* - * Copyright 2010 the original author or authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.integration.twitter.oauth; - -import org.apache.commons.io.IOUtils; -import org.apache.commons.lang.StringUtils; -import org.apache.commons.lang.SystemUtils; -import org.apache.commons.lang.exception.ExceptionUtils; - -import org.springframework.beans.factory.config.PropertiesFactoryBean; - -import org.springframework.core.io.FileSystemResource; - -import twitter4j.Twitter; -import twitter4j.TwitterException; -import twitter4j.TwitterFactory; - -import twitter4j.http.AccessToken; -import twitter4j.http.RequestToken; - -import java.io.BufferedReader; -import java.io.File; -import java.io.FileOutputStream; -import java.io.InputStreamReader; - -import java.util.HashMap; -import java.util.Map; -import java.util.Properties; - - -/** - * Default System.(out|in) based implementation of the {@link org.springframework.integration.twitter.oauth.AccessTokenInitialRequestProcessListener} interface - * - * @author Josh Long - */ -public class ConsoleBasedAccessTokenInitialRequestProcessListener implements AccessTokenInitialRequestProcessListener { - public String openUrlAndReturnPin(String urlToOpen) - throws Exception { - BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); - System.out.println("Open the following URL and grant access to your account:"); - System.out.println(urlToOpen); - System.out.print("Enter the PIN(if aviailable) or just hit enter.[PIN]:"); - - return StringUtils.trim(br.readLine()); - } - - public void persistReturnedAccessToken(AccessToken accessToken) - throws Exception { - Map output = new HashMap(); - output.put(OAuthConfigurationFactoryBean.WELL_KNOWN_CONSUMER_ACCESS_TOKEN, accessToken.getToken()); - output.put(OAuthConfigurationFactoryBean.WELL_KNOWN_CONSUMER_ACCESS_TOKEN_SECRET, accessToken.getTokenSecret()); - - File accessTokenCreds = new File(SystemUtils.getJavaIoTmpDir(), "twitter-accesstoken.properties"); - FileOutputStream fileOutputStream = new FileOutputStream(accessTokenCreds); - Properties props = new Properties(); - props.putAll(output); - props.store(fileOutputStream, "oauth-access-token"); - IOUtils.closeQuietly(fileOutputStream); - - System.out.println("The oauth accesstoken credentials have been written to " + accessTokenCreds.getAbsolutePath()); - } - - public void failure(Throwable t) { - System.err.println("Exception occurred when trying to retrieve credentials: " + ExceptionUtils.getFullStackTrace(t)); - } - - public static void main(String[] args) throws Exception { - File twitterProps = new File(SystemUtils.getUserHome(), "Desktop/twitter.properties"); - - PropertiesFactoryBean propertiesFactoryBean = new PropertiesFactoryBean(); - propertiesFactoryBean.setLocation(new FileSystemResource(twitterProps)); - propertiesFactoryBean.afterPropertiesSet() ; - Properties props = propertiesFactoryBean.getObject(); - - String key = StringUtils.trim(props.getProperty("twitter.oauth.consumerKey")); - String secret = StringUtils.trim( props.getProperty("twitter.oauth.consumerSecret") ) ; - - ConsoleBasedAccessTokenInitialRequestProcessListener consoleBasedAccessTokenInitialRequestProcessListener = - new ConsoleBasedAccessTokenInitialRequestProcessListener(); - - Twitter twitter = new TwitterFactory().getOAuthAuthorizedInstance( key, secret); - - RequestToken requestToken = twitter.getOAuthRequestToken(); - AccessToken accessToken = null; - BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); - - while (null == accessToken) { - String pin = consoleBasedAccessTokenInitialRequestProcessListener.openUrlAndReturnPin(requestToken.getAuthorizationURL()); - - try { - if (pin.length() > 0) { - accessToken = twitter.getOAuthAccessToken(requestToken, pin); - } else { - accessToken = twitter.getOAuthAccessToken(); - } - } catch (TwitterException te) { - if (401 == te.getStatusCode()) { - System.out.println("Unable to get the access token."); - } else { - te.printStackTrace(); - } - } - } - - consoleBasedAccessTokenInitialRequestProcessListener.persistReturnedAccessToken(accessToken); - - } -} diff --git a/spring-integration-twitter/src/test/java/org/springframework/integration/twitter/outbound/OutboundDirectMessageMessageHandlerTests.java b/spring-integration-twitter/src/test/java/org/springframework/integration/twitter/outbound/OutboundDirectMessageMessageHandlerTests.java index 8f462ac938..33ec445f76 100644 --- a/spring-integration-twitter/src/test/java/org/springframework/integration/twitter/outbound/OutboundDirectMessageMessageHandlerTests.java +++ b/spring-integration-twitter/src/test/java/org/springframework/integration/twitter/outbound/OutboundDirectMessageMessageHandlerTests.java @@ -19,22 +19,22 @@ package org.springframework.integration.twitter.outbound; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; import org.junit.Test; import org.springframework.integration.support.MessageBuilder; import org.springframework.integration.twitter.core.TwitterHeaders; -import org.springframework.integration.twitter.oauth.OAuthConfiguration; +import org.springframework.integration.twitter.oauth.OAuthTwitterFactoryBean; import twitter4j.GeoLocation; import twitter4j.Twitter; +import twitter4j.http.AccessToken; /** * @author Oleg Zhurakousky */ public class OutboundDirectMessageMessageHandlerTests { - private Twitter twitter; + private Twitter twitter = mock(Twitter.class); @Test public void validateSendDirectMessage() throws Exception{ @@ -43,8 +43,7 @@ public class OutboundDirectMessageMessageHandlerTests { .setHeader(TwitterHeaders.DISPLAY_COORDINATES, true) .setHeader(TwitterHeaders.DM_TARGET_USER_ID, "foo"); - DirectMessageSendingMessageHandler handler = new DirectMessageSendingMessageHandler(); - handler.setConfiguration(this.getTestConfiguration()); + DirectMessageSendingMessageHandler handler = new DirectMessageSendingMessageHandler(twitter); handler.afterPropertiesSet(); handler.handleMessage(mb.build()); @@ -59,12 +58,4 @@ public class OutboundDirectMessageMessageHandlerTests { verify(twitter, times(1)).sendDirectMessage(123, "hello"); } - - private OAuthConfiguration getTestConfiguration() throws Exception { - twitter = mock(Twitter.class); - OAuthConfiguration configuration = mock(OAuthConfiguration.class); - when(configuration.getTwitter()).thenReturn(twitter); - return configuration; - } - } From 387c2979be11e8a57d1e07f6638ec97757996bb1 Mon Sep 17 00:00:00 2001 From: Oleg Zhurakousky Date: Fri, 5 Nov 2010 16:01:55 -0400 Subject: [PATCH 67/82] INT-1553, fixed more tests, added new loguc to build metadataKey in the inbound adapters, tested new Twitter connectivity with real account --- .../inbound/AbstractTwitterMessageSource.java | 11 ++++------- .../TestReceivingUsingNamespace-context.xml | 2 +- ...InboundDirectMessageStatusEndpointTests.java | 17 +++++++---------- ...utboundDirectMessageMessageHandlerTests.java | 2 -- 4 files changed, 12 insertions(+), 20 deletions(-) diff --git a/spring-integration-twitter/src/main/java/org/springframework/integration/twitter/inbound/AbstractTwitterMessageSource.java b/spring-integration-twitter/src/main/java/org/springframework/integration/twitter/inbound/AbstractTwitterMessageSource.java index d3f0611633..cf4d6870f5 100644 --- a/spring-integration-twitter/src/main/java/org/springframework/integration/twitter/inbound/AbstractTwitterMessageSource.java +++ b/spring-integration-twitter/src/main/java/org/springframework/integration/twitter/inbound/AbstractTwitterMessageSource.java @@ -39,6 +39,7 @@ import org.springframework.util.StringUtils; import twitter4j.DirectMessage; import twitter4j.Status; import twitter4j.Twitter; +import twitter4j.http.OAuthAuthorization; /** * Abstract class that defines common operations for receiving various types of @@ -78,10 +79,6 @@ public abstract class AbstractTwitterMessageSource extends AbstractEndpoint public AbstractTwitterMessageSource(Twitter twitter){ this.twitter = twitter; } -// -// public void setConfiguration(OAuthConfiguration configuration) { -// this.configuration = configuration; -// } public void setShouldTrack(boolean shouldTrack) { this.historyWritingPostProcessor.setShouldTrack(shouldTrack); @@ -98,7 +95,7 @@ public abstract class AbstractTwitterMessageSource extends AbstractEndpoint @Override protected void onInit() throws Exception{ super.onInit(); - //Assert.notNull(this.configuration, "'configuration' can't be null"); + if (this.metadataStore == null) { // first try to look for a 'messageStore' in the context BeanFactory beanFactory = this.getBeanFactory(); @@ -122,7 +119,8 @@ public abstract class AbstractTwitterMessageSource extends AbstractEndpoint else if (logger.isWarnEnabled()) { logger.warn(this.getClass().getSimpleName() + " has no name. MetadataStore key might not be unique."); } - //metadataKeyBuilder.append(this.configuration.getConsumerKey()); + String accessToken = ((OAuthAuthorization)twitter.getAuthorization()).getOAuthAccessToken().getToken(); + metadataKeyBuilder.append(accessToken); this.metadataKey = metadataKeyBuilder.toString(); } @@ -146,7 +144,6 @@ public abstract class AbstractTwitterMessageSource extends AbstractEndpoint @Override protected void doStart(){ - //this.twitter = this.configuration.getTwitter(); Assert.notNull(this.twitter, "'twitter' instance can't be null"); historyWritingPostProcessor.setTrackableComponent(this); RateLimitStatusTrigger trigger = new RateLimitStatusTrigger(this.twitter); diff --git a/spring-integration-twitter/src/test/java/org/springframework/integration/twitter/ignored/TestReceivingUsingNamespace-context.xml b/spring-integration-twitter/src/test/java/org/springframework/integration/twitter/ignored/TestReceivingUsingNamespace-context.xml index 36e2552b78..45e21595a1 100644 --- a/spring-integration-twitter/src/test/java/org/springframework/integration/twitter/ignored/TestReceivingUsingNamespace-context.xml +++ b/spring-integration-twitter/src/test/java/org/springframework/integration/twitter/ignored/TestReceivingUsingNamespace-context.xml @@ -48,7 +48,7 @@ - + diff --git a/spring-integration-twitter/src/test/java/org/springframework/integration/twitter/inbound/InboundDirectMessageStatusEndpointTests.java b/spring-integration-twitter/src/test/java/org/springframework/integration/twitter/inbound/InboundDirectMessageStatusEndpointTests.java index b3d99c2162..e51cfd2bfc 100644 --- a/spring-integration-twitter/src/test/java/org/springframework/integration/twitter/inbound/InboundDirectMessageStatusEndpointTests.java +++ b/spring-integration-twitter/src/test/java/org/springframework/integration/twitter/inbound/InboundDirectMessageStatusEndpointTests.java @@ -19,18 +19,15 @@ package org.springframework.integration.twitter.inbound; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; -import java.util.ArrayList; import java.util.Date; -import java.util.List; import org.junit.Before; import org.junit.Test; -import org.mockito.Mockito; +import org.springframework.integration.Message; +import org.springframework.integration.channel.QueueChannel; +import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler; import twitter4j.DirectMessage; -import twitter4j.Paging; -import twitter4j.RateLimitStatus; -import twitter4j.ResponseList; import twitter4j.Twitter; /** @@ -42,7 +39,7 @@ public class InboundDirectMessageStatusEndpointTests { private DirectMessage secondMessage; - private Twitter twitter; + private Twitter twitter = mock(Twitter.class); @Before @@ -60,12 +57,12 @@ public class InboundDirectMessageStatusEndpointTests { @Test public void testTwitterMockedUpdates() throws Exception{ // QueueChannel channel = new QueueChannel(); -// InboundDirectMessageEndpoint endpoint = new InboundDirectMessageEndpoint(); -// endpoint.setOutputChannel(channel); +// DirectMessageReceivingMessageSource endpoint = new DirectMessageReceivingMessageSource(twitter); +// //endpoint.setOutputChannel(channel); // ThreadPoolTaskScheduler scheduler = new ThreadPoolTaskScheduler(); // scheduler.afterPropertiesSet(); // endpoint.setTaskScheduler(scheduler); -// endpoint.setConfiguration(this.getTestConfigurationForDirectMessages()); +// //endpoint.setConfiguration(this.getTestConfigurationForDirectMessages()); // endpoint.setBeanName("twitterEndpoint"); // endpoint.afterPropertiesSet(); // endpoint.start(); diff --git a/spring-integration-twitter/src/test/java/org/springframework/integration/twitter/outbound/OutboundDirectMessageMessageHandlerTests.java b/spring-integration-twitter/src/test/java/org/springframework/integration/twitter/outbound/OutboundDirectMessageMessageHandlerTests.java index 33ec445f76..34353bb45d 100644 --- a/spring-integration-twitter/src/test/java/org/springframework/integration/twitter/outbound/OutboundDirectMessageMessageHandlerTests.java +++ b/spring-integration-twitter/src/test/java/org/springframework/integration/twitter/outbound/OutboundDirectMessageMessageHandlerTests.java @@ -23,11 +23,9 @@ import static org.mockito.Mockito.verify; import org.junit.Test; import org.springframework.integration.support.MessageBuilder; import org.springframework.integration.twitter.core.TwitterHeaders; -import org.springframework.integration.twitter.oauth.OAuthTwitterFactoryBean; import twitter4j.GeoLocation; import twitter4j.Twitter; -import twitter4j.http.AccessToken; /** * @author Oleg Zhurakousky From ae2413e68af2bf24bd736230faf64e0e91aef882 Mon Sep 17 00:00:00 2001 From: Oleg Zhurakousky Date: Fri, 5 Nov 2010 17:17:49 -0400 Subject: [PATCH 68/82] INT-1553, added more test for the Inbound side --- .../inbound/AbstractTwitterMessageSource.java | 8 +- .../DirectMessageReceivingMessageSource.java | 5 +- ...ectMessageReceivingMessageSourceTests.java | 134 ++++++++++++++++++ ...boundDirectMessageStatusEndpointTests.java | 98 ------------- 4 files changed, 144 insertions(+), 101 deletions(-) create mode 100644 spring-integration-twitter/src/test/java/org/springframework/integration/twitter/inbound/DirectMessageReceivingMessageSourceTests.java delete mode 100644 spring-integration-twitter/src/test/java/org/springframework/integration/twitter/inbound/InboundDirectMessageStatusEndpointTests.java diff --git a/spring-integration-twitter/src/main/java/org/springframework/integration/twitter/inbound/AbstractTwitterMessageSource.java b/spring-integration-twitter/src/main/java/org/springframework/integration/twitter/inbound/AbstractTwitterMessageSource.java index cf4d6870f5..73ddc759df 100644 --- a/spring-integration-twitter/src/main/java/org/springframework/integration/twitter/inbound/AbstractTwitterMessageSource.java +++ b/spring-integration-twitter/src/main/java/org/springframework/integration/twitter/inbound/AbstractTwitterMessageSource.java @@ -33,13 +33,14 @@ import org.springframework.integration.history.TrackableComponent; import org.springframework.integration.store.MetadataStore; import org.springframework.integration.store.SimpleMetadataStore; import org.springframework.integration.support.MessageBuilder; +import org.springframework.scheduling.TaskScheduler; +import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler; import org.springframework.util.Assert; import org.springframework.util.StringUtils; import twitter4j.DirectMessage; import twitter4j.Status; import twitter4j.Twitter; -import twitter4j.http.OAuthAuthorization; /** * Abstract class that defines common operations for receiving various types of @@ -94,6 +95,8 @@ public abstract class AbstractTwitterMessageSource extends AbstractEndpoint @Override protected void onInit() throws Exception{ + Assert.notNull(this.getTaskScheduler(), + "Can not locate TaskScheduler. You must inject one explicitly or define a bean by the name 'taskScheduler'"); super.onInit(); if (this.metadataStore == null) { @@ -119,13 +122,14 @@ public abstract class AbstractTwitterMessageSource extends AbstractEndpoint else if (logger.isWarnEnabled()) { logger.warn(this.getClass().getSimpleName() + " has no name. MetadataStore key might not be unique."); } - String accessToken = ((OAuthAuthorization)twitter.getAuthorization()).getOAuthAccessToken().getToken(); + String accessToken = twitter.getOAuthAccessToken().getToken(); metadataKeyBuilder.append(accessToken); this.metadataKey = metadataKeyBuilder.toString(); } @SuppressWarnings("unchecked") protected void forwardAll(List tResponses) { + Object o = tResponses.iterator(); Collections.sort(tResponses, this.getComparator()); for (T twitterResponse : tResponses) { forward(twitterResponse); diff --git a/spring-integration-twitter/src/main/java/org/springframework/integration/twitter/inbound/DirectMessageReceivingMessageSource.java b/spring-integration-twitter/src/main/java/org/springframework/integration/twitter/inbound/DirectMessageReceivingMessageSource.java index 6b9d1ff94d..a245540ec6 100644 --- a/spring-integration-twitter/src/main/java/org/springframework/integration/twitter/inbound/DirectMessageReceivingMessageSource.java +++ b/spring-integration-twitter/src/main/java/org/springframework/integration/twitter/inbound/DirectMessageReceivingMessageSource.java @@ -19,6 +19,7 @@ import java.util.Comparator; import java.util.List; import org.springframework.integration.MessagingException; +import org.springframework.util.CollectionUtils; import twitter4j.DirectMessage; import twitter4j.Paging; @@ -53,7 +54,9 @@ public class DirectMessageReceivingMessageSource extends AbstractTwitterMessageS ? twitter.getDirectMessages() : twitter.getDirectMessages(new Paging(sinceId)); - forwardAll(dms); + if (!CollectionUtils.isEmpty(dms)){ + forwardAll(dms); + } } } catch (Exception e) { e.printStackTrace(); diff --git a/spring-integration-twitter/src/test/java/org/springframework/integration/twitter/inbound/DirectMessageReceivingMessageSourceTests.java b/spring-integration-twitter/src/test/java/org/springframework/integration/twitter/inbound/DirectMessageReceivingMessageSourceTests.java new file mode 100644 index 0000000000..12c0acd924 --- /dev/null +++ b/spring-integration-twitter/src/test/java/org/springframework/integration/twitter/inbound/DirectMessageReceivingMessageSourceTests.java @@ -0,0 +1,134 @@ +/* + * Copyright 2002-2010 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.integration.twitter.inbound; + +import static junit.framework.Assert.assertEquals; +import static junit.framework.Assert.assertTrue; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import java.util.ArrayList; +import java.util.Date; +import java.util.List; +import java.util.Queue; + +import org.junit.Before; +import org.junit.Test; +import org.mockito.Mockito; +import org.springframework.integration.test.util.TestUtils; +import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler; +import org.springframework.util.CollectionUtils; + +import twitter4j.DirectMessage; +import twitter4j.Paging; +import twitter4j.RateLimitStatus; +import twitter4j.ResponseList; +import twitter4j.Twitter; +import twitter4j.http.AccessToken; + +/** + * @author Oleg Zhurakousky + */ +public class DirectMessageReceivingMessageSourceTests { + + private DirectMessage firstMessage; + + private DirectMessage secondMessage; + + private Twitter twitter = mock(Twitter.class); + + + @Before + public void prepare() throws Exception{ + twitter = mock(Twitter.class); + firstMessage = mock(DirectMessage.class); + when(firstMessage.getCreatedAt()).thenReturn(new Date(5555555555L)); + when(firstMessage.getId()).thenReturn(200); + secondMessage = mock(DirectMessage.class); + when(secondMessage.getCreatedAt()).thenReturn(new Date(2222222222L)); + when(secondMessage.getId()).thenReturn(2000); + + + when(twitter.getOAuthAccessToken()).thenReturn(new AccessToken("token123", "tokenSecret123")); + } + + + @Test + public void testSuccessfullInitialization() throws Exception{ + DirectMessageReceivingMessageSource source = new DirectMessageReceivingMessageSource(twitter); + ThreadPoolTaskScheduler scheduler = new ThreadPoolTaskScheduler(); + scheduler.afterPropertiesSet(); + source.setTaskScheduler(scheduler); + source.setBeanName("twitterEndpoint"); + source.afterPropertiesSet(); + source.start(); + assertEquals("twitter:inbound-dm-channel-adapter.twitterEndpoint.token123", TestUtils.getPropertyValue(source, "metadataKey")); + assertTrue(source.isRunning()); + } + + @Test + public void testSuccessfullInitializationWithMessages() throws Exception{ + this.setUpMockScenarioForMessagePolling(); + + DirectMessageReceivingMessageSource source = new DirectMessageReceivingMessageSource(twitter); + ThreadPoolTaskScheduler scheduler = new ThreadPoolTaskScheduler(); + scheduler.afterPropertiesSet(); + source.setTaskScheduler(scheduler); + source.setBeanName("twitterEndpoint"); + source.afterPropertiesSet(); + source.start(); + Thread.sleep(1000); + System.out.println("Tweets: " + TestUtils.getPropertyValue(source, "tweets")); + Queue msg = (Queue) TestUtils.getPropertyValue(source, "tweets"); + assertTrue(!CollectionUtils.isEmpty(msg)); + assertEquals(1, msg.size()); // because the other message has a older timestamp and is assumed to be read by + DirectMessage message = (DirectMessage) msg.poll(); + assertEquals(secondMessage, message); + + } + + + @SuppressWarnings("unchecked") + private void setUpMockScenarioForMessagePolling() throws Exception{ + RateLimitStatus rateLimitStatus = mock(RateLimitStatus.class); + when(twitter.getRateLimitStatus()).thenReturn(rateLimitStatus); + when(rateLimitStatus.getSecondsUntilReset()).thenReturn(2464); + when(rateLimitStatus.getRemainingHits()).thenReturn(250); + + //ResponseList responses = mock(ResponseList.class); + SampleResoponceList testMessages = new SampleResoponceList(); + testMessages.add(firstMessage); + testMessages.add(secondMessage); + //when(responses.iterator()).thenReturn(testMessages.iterator()); + when(twitter.getDirectMessages()).thenReturn(testMessages); + when(twitter.getDirectMessages(Mockito.any(Paging.class))).thenReturn(testMessages); + } + + public static class SampleResoponceList extends ArrayList implements ResponseList { + + @Override + public RateLimitStatus getRateLimitStatus() { + return mock(RateLimitStatus.class); + } + + @Override + public RateLimitStatus getFeatureSpecificRateLimitStatus() { + return mock(RateLimitStatus.class); + } + + } +} diff --git a/spring-integration-twitter/src/test/java/org/springframework/integration/twitter/inbound/InboundDirectMessageStatusEndpointTests.java b/spring-integration-twitter/src/test/java/org/springframework/integration/twitter/inbound/InboundDirectMessageStatusEndpointTests.java deleted file mode 100644 index e51cfd2bfc..0000000000 --- a/spring-integration-twitter/src/test/java/org/springframework/integration/twitter/inbound/InboundDirectMessageStatusEndpointTests.java +++ /dev/null @@ -1,98 +0,0 @@ -/* - * Copyright 2002-2010 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.integration.twitter.inbound; - -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; - -import java.util.Date; - -import org.junit.Before; -import org.junit.Test; -import org.springframework.integration.Message; -import org.springframework.integration.channel.QueueChannel; -import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler; - -import twitter4j.DirectMessage; -import twitter4j.Twitter; - -/** - * @author Oleg Zhurakousky - */ -public class InboundDirectMessageStatusEndpointTests { - - private DirectMessage firstMessage; - - private DirectMessage secondMessage; - - private Twitter twitter = mock(Twitter.class); - - - @Before - public void prepare() { - twitter = mock(Twitter.class); - firstMessage = mock(DirectMessage.class); - when(firstMessage.getCreatedAt()).thenReturn(new Date(5555555555L)); - when(firstMessage.getId()).thenReturn(200); - secondMessage = mock(DirectMessage.class); - when(secondMessage.getCreatedAt()).thenReturn(new Date(2222222222L)); - when(secondMessage.getId()).thenReturn(2000); - } - - - @Test - public void testTwitterMockedUpdates() throws Exception{ -// QueueChannel channel = new QueueChannel(); -// DirectMessageReceivingMessageSource endpoint = new DirectMessageReceivingMessageSource(twitter); -// //endpoint.setOutputChannel(channel); -// ThreadPoolTaskScheduler scheduler = new ThreadPoolTaskScheduler(); -// scheduler.afterPropertiesSet(); -// endpoint.setTaskScheduler(scheduler); -// //endpoint.setConfiguration(this.getTestConfigurationForDirectMessages()); -// endpoint.setBeanName("twitterEndpoint"); -// endpoint.afterPropertiesSet(); -// endpoint.start(); -// Message message1 = channel.receive(3000); -// assertNotNull(message1); -// // should be second message since its timestamp is newer -// assertEquals(secondMessage.getId(), ((DirectMessage)message1.getPayload()).getId()); -// Message message2 = channel.receive(100); -// assertNull(message2); // should be null, since - } - - -// @SuppressWarnings("unchecked") -// private OAuthConfiguration getTestConfigurationForDirectMessages() throws Exception{ -// OAuthConfiguration configuration = mock(OAuthConfiguration.class); -// RateLimitStatus rateLimitStatus = mock(RateLimitStatus.class); -// when(twitter.getRateLimitStatus()).thenReturn(rateLimitStatus); -// when(configuration.getTwitter()).thenReturn(twitter); -// when(rateLimitStatus.getSecondsUntilReset()).thenReturn(2464); -// when(rateLimitStatus.getRemainingHits()).thenReturn(250); -// -// ResponseList responses = mock(ResponseList.class); -// List testMessages = new ArrayList(); -// testMessages.add(firstMessage); -// testMessages.add(secondMessage); -// -// when(responses.iterator()).thenReturn(testMessages.iterator()); -// when(twitter.getDirectMessages()).thenReturn(responses); -// when(twitter.getDirectMessages(Mockito.any(Paging.class))).thenReturn(responses); -// return configuration; -// } - -} From d9eafee19bac8a8709394b7655c895babc7d8bd8 Mon Sep 17 00:00:00 2001 From: Mark Fisher Date: Fri, 5 Nov 2010 18:01:45 -0400 Subject: [PATCH 69/82] removed unused code, and got rid of warnings --- .../integration/http/ContentTypeResolver.java | 45 ------ .../http/DataBindingInboundRequestMapper.java | 146 ------------------ .../HttpRequestHandlingEndpointSupport.java | 6 +- .../HttpRequestHandlingMessagingGateway.java | 17 +- ...ultipartAwareFormHttpMessageConverter.java | 3 +- .../http/MultipartHttpInputMessage.java | 2 +- .../http/SerializingHttpMessageConverter.java | 2 +- .../DataBindingInboundRequestMapperTests.java | 102 ------------ ...pRequestHandlingMessagingGatewayTests.java | 82 +++++++++- 9 files changed, 93 insertions(+), 312 deletions(-) delete mode 100644 spring-integration-http/src/main/java/org/springframework/integration/http/ContentTypeResolver.java delete mode 100644 spring-integration-http/src/main/java/org/springframework/integration/http/DataBindingInboundRequestMapper.java delete mode 100644 spring-integration-http/src/test/java/org/springframework/integration/http/DataBindingInboundRequestMapperTests.java diff --git a/spring-integration-http/src/main/java/org/springframework/integration/http/ContentTypeResolver.java b/spring-integration-http/src/main/java/org/springframework/integration/http/ContentTypeResolver.java deleted file mode 100644 index 62040fdcce..0000000000 --- a/spring-integration-http/src/main/java/org/springframework/integration/http/ContentTypeResolver.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright 2002-2010 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.integration.http; - -import org.springframework.http.MediaType; - -/** - * Strategy for resolving the content type of a given object. The content type - * will be represented as an instance of the {@link MediaType} enum. - * - * @author Mark Fisher - * @since 2.0 - */ -public interface ContentTypeResolver { - - /** - * Resolves the content type of a given object. - * - * @param content the object whose content type should be resolved - */ - MediaType resolveContentType(Object content); - - /** - * Resolves the content type of a given String instance and charset name. - * - * @param content the String whose content type should be resolved - * @param charset charset name - */ - MediaType resolveContentType(String content, String charset); - -} diff --git a/spring-integration-http/src/main/java/org/springframework/integration/http/DataBindingInboundRequestMapper.java b/spring-integration-http/src/main/java/org/springframework/integration/http/DataBindingInboundRequestMapper.java deleted file mode 100644 index 2d80509227..0000000000 --- a/spring-integration-http/src/main/java/org/springframework/integration/http/DataBindingInboundRequestMapper.java +++ /dev/null @@ -1,146 +0,0 @@ -/* - * Copyright 2002-2009 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.integration.http; - -import java.util.Map; - -import javax.servlet.http.HttpServletRequest; - -import org.springframework.beans.BeansException; -import org.springframework.beans.factory.BeanFactory; -import org.springframework.beans.factory.BeanFactoryAware; -import org.springframework.beans.factory.InitializingBean; -import org.springframework.integration.Message; -import org.springframework.integration.support.MessageBuilder; -import org.springframework.util.Assert; -import org.springframework.web.bind.ServletRequestDataBinder; -import org.springframework.web.bind.support.WebBindingInitializer; -import org.springframework.web.servlet.handler.DispatcherServletWebRequest; - -/** - * InboundRequestMapper implementation that binds the request parameter map to - * a target instance. The target instance may be a non-singleton bean as - * specified by the {@link #setTargetBeanName(String) 'targetBeanName'} - * property. Otherwise, this mapper's target type must provide a default, - * no-arg constructor. - * - * @author Mark Fisher - * @since 1.0.2 - */ -public class DataBindingInboundRequestMapper implements InboundRequestMapper, BeanFactoryAware, InitializingBean { - - private volatile Class targetType = Object.class; - - private volatile String targetBeanName; - - private volatile WebBindingInitializer webBindingInitializer; - - private volatile BeanFactory beanFactory; - - private volatile boolean validated; - - - public DataBindingInboundRequestMapper() { - this.targetType = Object.class; - } - - public DataBindingInboundRequestMapper(Class targetType) { - Assert.notNull(targetType, "targetType must not be null"); - this.targetType = targetType; - } - - - public void setTargetType(Class targetType) { - this.targetType = targetType; - } - - /** - * Specify the name of a bean definition to use when creating the target - * instance. The bean must not be a singleton, and it must be - * compatible with the {@link #targetType}. - *

If no 'targetBeanName' value is provided, the target type must - * provide a default, no-arg constructor. - */ - public void setTargetBeanName(String targetBeanName) { - this.targetBeanName = targetBeanName; - } - - /** - * Specify an optional {@link WebBindingInitializer} to be invoked prior - * to the request binding process. - */ - public void setWebBindingInitializer(WebBindingInitializer webBindingInitializer) { - this.webBindingInitializer = webBindingInitializer; - } - - /** - * Provides the {@link BeanFactory} necessary to look up a - * {@link #setTargetBeanName(String) 'targetBeanName'} if specified. - * This method is typically invoked automatically by the container. - */ - public void setBeanFactory(BeanFactory beanFactory) throws BeansException { - this.beanFactory = beanFactory; - } - - public final void afterPropertiesSet() { - if (this.targetBeanName == null && Object.class.equals(this.targetType)) { - throw new IllegalArgumentException( - "When no 'targetBeanName' is provided, the 'targetType' must be more specific than Object."); - } - this.validateTargetBeanIfNecessary(); - } - - private void validateTargetBeanIfNecessary() { - if (this.targetBeanName != null && !this.validated) { - Assert.notNull(this.beanFactory, "beanFactory is required for binding to a bean"); - if (this.beanFactory.isSingleton(this.targetBeanName)) { - throw new IllegalArgumentException("binding target bean must not be a singleton"); - } - Class beanType = this.beanFactory.getType(this.targetBeanName); - if (beanType != null) { - Assert.isAssignable(this.targetType, beanType); - } - this.validated = true; - } - } - - @SuppressWarnings("unchecked") - public Message toMessage(HttpServletRequest request) throws Exception { - ServletRequestDataBinder binder = new ServletRequestDataBinder(getTarget()); - this.initBinder(binder, request); - binder.bind(request); - // this will immediately throw any bind Exceptions - Map map = binder.close(); - Object payload = map.get(ServletRequestDataBinder.DEFAULT_OBJECT_NAME); - return MessageBuilder.withPayload(payload).build(); - } - - private void initBinder(ServletRequestDataBinder binder, HttpServletRequest request) { - if (this.webBindingInitializer != null) { - this.webBindingInitializer.initBinder(binder, new DispatcherServletWebRequest(request)); - } - } - - private Object getTarget() throws InstantiationException, IllegalAccessException { - if (this.targetBeanName != null) { - this.validateTargetBeanIfNecessary(); - return this.beanFactory.getBean(this.targetBeanName, this.targetType); - } - return this.targetType.newInstance(); - } - -} diff --git a/spring-integration-http/src/main/java/org/springframework/integration/http/HttpRequestHandlingEndpointSupport.java b/spring-integration-http/src/main/java/org/springframework/integration/http/HttpRequestHandlingEndpointSupport.java index 298f8bfea7..d9ba35685d 100644 --- a/spring-integration-http/src/main/java/org/springframework/integration/http/HttpRequestHandlingEndpointSupport.java +++ b/spring-integration-http/src/main/java/org/springframework/integration/http/HttpRequestHandlingEndpointSupport.java @@ -106,7 +106,7 @@ abstract class HttpRequestHandlingEndpointSupport extends MessagingGatewaySuppor this(true); } - @SuppressWarnings("unchecked") + @SuppressWarnings("rawtypes") public HttpRequestHandlingEndpointSupport(boolean expectReply) { this.expectReply = expectReply; this.messageConverters.add(new MultipartAwareFormHttpMessageConverter()); @@ -324,7 +324,7 @@ abstract class HttpRequestHandlingEndpointSupport extends MessagingGatewaySuppor /** * Converts a servlet request's parameterMap to a {@link MultiValueMap}. */ - @SuppressWarnings("unchecked") + @SuppressWarnings("rawtypes") private LinkedMultiValueMap convertParameterMap(Map parameterMap) { LinkedMultiValueMap convertedMap = new LinkedMultiValueMap(); for (Object key : parameterMap.keySet()) { @@ -336,7 +336,7 @@ abstract class HttpRequestHandlingEndpointSupport extends MessagingGatewaySuppor return convertedMap; } - @SuppressWarnings("unchecked") + @SuppressWarnings({"unchecked", "rawtypes"}) private Object generatePayloadFromRequestBody(ServletServerHttpRequest request) throws IOException { MediaType contentType = request.getHeaders().getContentType(); Class expectedType = this.requestPayloadType; diff --git a/spring-integration-http/src/main/java/org/springframework/integration/http/HttpRequestHandlingMessagingGateway.java b/spring-integration-http/src/main/java/org/springframework/integration/http/HttpRequestHandlingMessagingGateway.java index efcdbc2f57..cd77aecb16 100644 --- a/spring-integration-http/src/main/java/org/springframework/integration/http/HttpRequestHandlingMessagingGateway.java +++ b/spring-integration-http/src/main/java/org/springframework/integration/http/HttpRequestHandlingMessagingGateway.java @@ -53,11 +53,11 @@ import org.springframework.web.HttpRequestHandler; * @author Mark Fisher * @since 2.0 */ -public class HttpRequestHandlingMessagingGateway extends HttpRequestHandlingEndpointSupport implements - HttpRequestHandler { +public class HttpRequestHandlingMessagingGateway extends HttpRequestHandlingEndpointSupport implements HttpRequestHandler { private volatile boolean convertExceptions; + public HttpRequestHandlingMessagingGateway() { this(true); } @@ -66,6 +66,7 @@ public class HttpRequestHandlingMessagingGateway extends HttpRequestHandlingEndp super(expectReply); } + /** * Flag to determine if conversion and writing out of message handling exceptions should be attempted (default * false, in which case they will simply be re-thrown). If the flag is true and no message converter can convert the @@ -99,22 +100,24 @@ public class HttpRequestHandlingMessagingGateway extends HttpRequestHandlingEndp } private Object handleExceptionInternal(Exception e) throws IOException { - if (convertExceptions && isExpectReply()) { + if (this.convertExceptions && isExpectReply()) { return e; } else { if (e instanceof IOException) { throw (IOException) e; } - else { + else if (e instanceof RuntimeException) { throw (RuntimeException) e; } + else { + throw new MessagingException("error occurred handling HTTP request", e); + } } } - @SuppressWarnings("unchecked") - private void writeResponse(Object content, ServletServerHttpResponse response, List acceptTypes) - throws IOException { + @SuppressWarnings({"unchecked", "rawtypes"}) + private void writeResponse(Object content, ServletServerHttpResponse response, List acceptTypes) throws IOException { for (HttpMessageConverter converter : this.getMessageConverters()) { for (MediaType acceptType : acceptTypes) { if (converter.canWrite(content.getClass(), acceptType)) { diff --git a/spring-integration-http/src/main/java/org/springframework/integration/http/MultipartAwareFormHttpMessageConverter.java b/spring-integration-http/src/main/java/org/springframework/integration/http/MultipartAwareFormHttpMessageConverter.java index 44b333b9ba..bcbb2e519e 100644 --- a/spring-integration-http/src/main/java/org/springframework/integration/http/MultipartAwareFormHttpMessageConverter.java +++ b/spring-integration-http/src/main/java/org/springframework/integration/http/MultipartAwareFormHttpMessageConverter.java @@ -98,10 +98,9 @@ public class MultipartAwareFormHttpMessageConverter implements HttpMessageConver return this.readMultipart(multipartInputMessage); } - @SuppressWarnings("unchecked") private MultiValueMap readMultipart(MultipartHttpInputMessage multipartRequest) throws IOException { MultiValueMap resultMap = new LinkedMultiValueMap(); - Map parameterMap = multipartRequest.getParameterMap(); + Map parameterMap = multipartRequest.getParameterMap(); for (Object key : parameterMap.keySet()) { resultMap.add((String) key, parameterMap.get(key)); } diff --git a/spring-integration-http/src/main/java/org/springframework/integration/http/MultipartHttpInputMessage.java b/spring-integration-http/src/main/java/org/springframework/integration/http/MultipartHttpInputMessage.java index 9f57bfe551..b83cff4bfd 100644 --- a/spring-integration-http/src/main/java/org/springframework/integration/http/MultipartHttpInputMessage.java +++ b/spring-integration-http/src/main/java/org/springframework/integration/http/MultipartHttpInputMessage.java @@ -62,7 +62,7 @@ public class MultipartHttpInputMessage extends ServletServerHttpRequest implemen } // TODO: return MultiValueMap? - @SuppressWarnings("unchecked") + @SuppressWarnings("rawtypes") public Map getParameterMap() { return this.multipartServletRequest.getParameterMap(); } diff --git a/spring-integration-http/src/main/java/org/springframework/integration/http/SerializingHttpMessageConverter.java b/spring-integration-http/src/main/java/org/springframework/integration/http/SerializingHttpMessageConverter.java index 78130d59d5..984e1cbade 100644 --- a/spring-integration-http/src/main/java/org/springframework/integration/http/SerializingHttpMessageConverter.java +++ b/spring-integration-http/src/main/java/org/springframework/integration/http/SerializingHttpMessageConverter.java @@ -62,7 +62,7 @@ public class SerializingHttpMessageConverter extends AbstractHttpMessageConverte } @Override - @SuppressWarnings("unchecked") + @SuppressWarnings("rawtypes") public Serializable readInternal(Class clazz, HttpInputMessage inputMessage) throws IOException { try { return (Serializable) new ObjectInputStream(inputMessage.getBody()).readObject(); diff --git a/spring-integration-http/src/test/java/org/springframework/integration/http/DataBindingInboundRequestMapperTests.java b/spring-integration-http/src/test/java/org/springframework/integration/http/DataBindingInboundRequestMapperTests.java deleted file mode 100644 index dcb20e57ba..0000000000 --- a/spring-integration-http/src/test/java/org/springframework/integration/http/DataBindingInboundRequestMapperTests.java +++ /dev/null @@ -1,102 +0,0 @@ -/* - * Copyright 2002-2009 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.integration.http; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; - -import org.junit.Test; - -import org.springframework.beans.MutablePropertyValues; -import org.springframework.context.support.StaticApplicationContext; -import org.springframework.integration.Message; -import org.springframework.integration.http.DataBindingInboundRequestMapper; -import org.springframework.mock.web.MockHttpServletRequest; -import org.springframework.web.bind.support.ConfigurableWebBindingInitializer; - -/** - * @author Mark Fisher - */ -public class DataBindingInboundRequestMapperTests { - - @Test - public void bindToType() throws Exception { - DataBindingInboundRequestMapper mapper = new DataBindingInboundRequestMapper(TestBean.class); - MockHttpServletRequest request = new MockHttpServletRequest(); - request.setParameter("name", "testBean"); - request.setParameter("age", "42"); - Message result = mapper.toMessage(request); - assertNotNull(result); - assertEquals(TestBean.class, result.getPayload().getClass()); - TestBean payload = (TestBean) result.getPayload(); - assertEquals("testBean", payload.name); - assertEquals(84, payload.age); - } - - @Test - public void bindToTypeWithBindingInitializer() throws Exception { - DataBindingInboundRequestMapper mapper = new DataBindingInboundRequestMapper(TestBean.class); - ConfigurableWebBindingInitializer initializer = new ConfigurableWebBindingInitializer(); - initializer.setDirectFieldAccess(true); - mapper.setWebBindingInitializer(initializer); - MockHttpServletRequest request = new MockHttpServletRequest(); - request.setParameter("name", "testBean"); - request.setParameter("age", "42"); - Message result = mapper.toMessage(request); - assertNotNull(result); - assertEquals(TestBean.class, result.getPayload().getClass()); - TestBean payload = (TestBean) result.getPayload(); - assertEquals("testBean", payload.name); - assertEquals(42, payload.age); - } - - @Test - public void bindToPrototypeBean() throws Exception { - StaticApplicationContext context = new StaticApplicationContext(); - MutablePropertyValues properties = new MutablePropertyValues(); - properties.addPropertyValue("name", "prototype"); - context.registerPrototype("prototypeTarget", TestBean.class, properties); - DataBindingInboundRequestMapper mapper = new DataBindingInboundRequestMapper(TestBean.class); - mapper.setTargetBeanName("prototypeTarget"); - mapper.setBeanFactory(context); - MockHttpServletRequest request = new MockHttpServletRequest(); - request.setParameter("age", "42"); - Message result = mapper.toMessage(request); - assertNotNull(result); - assertEquals(TestBean.class, result.getPayload().getClass()); - TestBean payload = (TestBean) result.getPayload(); - assertEquals("prototype", payload.name); - assertEquals(84, payload.age); - } - - - public static class TestBean { - - String name; - - int age; - - public void setName(String name) { - this.name = name; - } - - public void setAge(int age) { - this.age = age * 2; - } - } - -} diff --git a/spring-integration-http/src/test/java/org/springframework/integration/http/HttpRequestHandlingMessagingGatewayTests.java b/spring-integration-http/src/test/java/org/springframework/integration/http/HttpRequestHandlingMessagingGatewayTests.java index 660f79df27..792f41d7ba 100644 --- a/spring-integration-http/src/test/java/org/springframework/integration/http/HttpRequestHandlingMessagingGatewayTests.java +++ b/spring-integration-http/src/test/java/org/springframework/integration/http/HttpRequestHandlingMessagingGatewayTests.java @@ -21,9 +21,12 @@ import static org.junit.Assert.assertNotNull; import java.io.IOException; import java.io.PrintWriter; +import java.io.Serializable; import java.util.Arrays; +import java.util.List; import org.junit.Test; + import org.springframework.http.HttpInputMessage; import org.springframework.http.HttpOutputMessage; import org.springframework.http.MediaType; @@ -37,6 +40,7 @@ import org.springframework.integration.channel.QueueChannel; import org.springframework.integration.handler.AbstractReplyProducingMessageHandler; import org.springframework.mock.web.MockHttpServletResponse; import org.springframework.util.LinkedMultiValueMap; +import org.springframework.util.SerializationUtils; /** * @author Mark Fisher @@ -113,7 +117,7 @@ public class HttpRequestHandlingMessagingGatewayTests { HttpRequestHandlingMessagingGateway gateway = new HttpRequestHandlingMessagingGateway(true); gateway.setRequestChannel(requestChannel); gateway.setConvertExceptions(true); - gateway.setMessageConverters(Arrays.>asList(new DumbHttpMessageConverter())); + gateway.setMessageConverters(Arrays.>asList(new TestHttpMessageConverter())); MockHttpServletRequest request = new MockHttpServletRequest(); request.addHeader("Accept", "application/x-java-serialized-object"); request.setMethod("GET"); @@ -123,9 +127,61 @@ public class HttpRequestHandlingMessagingGatewayTests { assertEquals("Planned", content); } - private static class DumbHttpMessageConverter extends AbstractHttpMessageConverter { + @Test + public void multiValueParameterMap() throws Exception { + QueueChannel channel = new QueueChannel(); + HttpRequestHandlingMessagingGateway gateway = new HttpRequestHandlingMessagingGateway(false); + gateway.setRequestChannel(channel); + MockHttpServletRequest request = new MockHttpServletRequest("GET", "/test"); + request.setParameter("foo", "123"); + request.addParameter("bar", "456"); + request.addParameter("bar", "789"); + MockHttpServletResponse response = new MockHttpServletResponse(); + gateway.handleRequest(request, response); + Message message = channel.receive(0); + assertNotNull(message); + assertNotNull(message.getPayload()); + assertEquals(LinkedMultiValueMap.class, message.getPayload().getClass()); + @SuppressWarnings("unchecked") + LinkedMultiValueMap map = (LinkedMultiValueMap) message.getPayload(); + List fooValues = map.get("foo"); + List barValues = map.get("bar"); + assertEquals(1, fooValues.size()); + assertEquals("123", fooValues.get(0)); + assertEquals(2, barValues.size()); + assertEquals("456", barValues.get(0)); + assertEquals("789", barValues.get(1)); + } + + @Test + public void serializableRequestBody() throws Exception { + QueueChannel channel = new QueueChannel(); + HttpRequestHandlingMessagingGateway gateway = new HttpRequestHandlingMessagingGateway(false); + gateway.setRequestPayloadType(TestBean.class); + gateway.setRequestChannel(channel); + MockHttpServletRequest request = new MockHttpServletRequest("POST", "/test"); + request.setContentType("application/x-java-serialized-object"); + TestBean testBean = new TestBean(); + testBean.setName("T. Bean"); + testBean.setAge(42); + request.setContent(SerializationUtils.serialize(testBean)); + MockHttpServletResponse response = new MockHttpServletResponse(); + gateway.handleRequest(request, response); + byte[] bytes = response.getContentAsByteArray(); + assertNotNull(bytes); + Message message = channel.receive(0); + assertNotNull(message); + assertNotNull(message.getPayload()); + assertEquals(TestBean.class, message.getPayload().getClass()); + TestBean result = (TestBean) message.getPayload(); + assertEquals("T. Bean", result.name); + assertEquals(84, result.age); + } + + + private static class TestHttpMessageConverter extends AbstractHttpMessageConverter { - public DumbHttpMessageConverter() { + public TestHttpMessageConverter() { setSupportedMediaTypes(Arrays.asList(MediaType.ALL)); } @@ -141,11 +197,27 @@ public class HttpRequestHandlingMessagingGatewayTests { } @Override - protected void writeInternal(Exception t, HttpOutputMessage outputMessage) throws IOException, - HttpMessageNotWritableException { + protected void writeInternal(Exception t, HttpOutputMessage outputMessage) throws IOException, HttpMessageNotWritableException { new PrintWriter(outputMessage.getBody()).append(t.getCause().getMessage()).flush(); } + } + + + @SuppressWarnings("serial") + public static class TestBean implements Serializable { + + String name; + + int age; + + public void setName(String name) { + this.name = name; + } + + public void setAge(int age) { + this.age = age * 2; + } } } From 0c8906768770c37023f025b7fb8c44ffe527e43f Mon Sep 17 00:00:00 2001 From: Mark Fisher Date: Fri, 5 Nov 2010 18:21:30 -0400 Subject: [PATCH 70/82] refactored package structure, added: inbound, outbound, converter, multipart, and support --- .../http/InboundRequestMapper.java | 32 --------------- .../http/ResponseStatusCodeException.java | 41 ------------------- .../config/HttpInboundEndpointParser.java | 4 +- .../HttpOutboundChannelAdapterParser.java | 6 +-- .../config/HttpOutboundGatewayParser.java | 7 +--- ...ultipartAwareFormHttpMessageConverter.java | 5 ++- .../SerializingHttpMessageConverter.java | 2 +- .../HttpRequestHandlingController.java | 2 +- .../HttpRequestHandlingEndpointSupport.java | 6 ++- .../HttpRequestHandlingMessagingGateway.java | 3 +- .../DefaultMultipartFileReader.java | 2 +- .../FileCopyingMultipartFileReader.java | 2 +- .../{ => multipart}/MultipartFileReader.java | 2 +- .../MultipartHttpInputMessage.java | 2 +- .../SimpleMultipartFileReader.java | 2 +- .../UploadedMultipartFile.java | 2 +- .../HttpRequestExecutingMessageHandler.java | 4 +- .../DefaultHttpHeaderMapper.java | 2 +- ...tpRequestExecutingMessageHandlerTests.java | 1 + .../HttpRequestHandlingControllerTests.java | 1 + ...pRequestHandlingMessagingGatewayTests.java | 1 + .../http/UriVariableExpressionTests.java | 1 + .../HttpInboundChannelAdapterParserTests.java | 4 +- .../config/HttpInboundGatewayParserTests.java | 4 +- ...HttpOutboundChannelAdapterParserTests.java | 2 +- .../HttpOutboundGatewayParserTests.java | 2 +- 26 files changed, 39 insertions(+), 103 deletions(-) delete mode 100644 spring-integration-http/src/main/java/org/springframework/integration/http/InboundRequestMapper.java delete mode 100644 spring-integration-http/src/main/java/org/springframework/integration/http/ResponseStatusCodeException.java rename spring-integration-http/src/main/java/org/springframework/integration/http/{ => converter}/MultipartAwareFormHttpMessageConverter.java (94%) rename spring-integration-http/src/main/java/org/springframework/integration/http/{ => converter}/SerializingHttpMessageConverter.java (98%) rename spring-integration-http/src/main/java/org/springframework/integration/http/{ => inbound}/HttpRequestHandlingController.java (98%) rename spring-integration-http/src/main/java/org/springframework/integration/http/{ => inbound}/HttpRequestHandlingEndpointSupport.java (97%) rename spring-integration-http/src/main/java/org/springframework/integration/http/{ => inbound}/HttpRequestHandlingMessagingGateway.java (97%) rename spring-integration-http/src/main/java/org/springframework/integration/http/{ => multipart}/DefaultMultipartFileReader.java (95%) rename spring-integration-http/src/main/java/org/springframework/integration/http/{ => multipart}/FileCopyingMultipartFileReader.java (97%) rename spring-integration-http/src/main/java/org/springframework/integration/http/{ => multipart}/MultipartFileReader.java (94%) rename spring-integration-http/src/main/java/org/springframework/integration/http/{ => multipart}/MultipartHttpInputMessage.java (97%) rename spring-integration-http/src/main/java/org/springframework/integration/http/{ => multipart}/SimpleMultipartFileReader.java (97%) rename spring-integration-http/src/main/java/org/springframework/integration/http/{ => multipart}/UploadedMultipartFile.java (98%) rename spring-integration-http/src/main/java/org/springframework/integration/http/{ => outbound}/HttpRequestExecutingMessageHandler.java (98%) rename spring-integration-http/src/main/java/org/springframework/integration/http/{ => support}/DefaultHttpHeaderMapper.java (98%) diff --git a/spring-integration-http/src/main/java/org/springframework/integration/http/InboundRequestMapper.java b/spring-integration-http/src/main/java/org/springframework/integration/http/InboundRequestMapper.java deleted file mode 100644 index bdf3cc4f7f..0000000000 --- a/spring-integration-http/src/main/java/org/springframework/integration/http/InboundRequestMapper.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright 2002-2009 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.integration.http; - -import javax.servlet.http.HttpServletRequest; - -import org.springframework.integration.mapping.InboundMessageMapper; - -/** - * Strategy interface for mapping from an inbound {@link HttpServletRequest} - * to a Message. - * - * @author Mark Fisher - * @since 1.0.2 - */ -public interface InboundRequestMapper extends InboundMessageMapper { - -} diff --git a/spring-integration-http/src/main/java/org/springframework/integration/http/ResponseStatusCodeException.java b/spring-integration-http/src/main/java/org/springframework/integration/http/ResponseStatusCodeException.java deleted file mode 100644 index edf991ba56..0000000000 --- a/spring-integration-http/src/main/java/org/springframework/integration/http/ResponseStatusCodeException.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright 2002-2009 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.integration.http; - -/** - * Exception that provides a response status code. This can be used by - * {@link InboundRequestMapper} implementations to indicate an error. - * - * @author Mark Fisher - * @since 1.0.2 - */ -@SuppressWarnings("serial") -public class ResponseStatusCodeException extends Exception { - - private final int statusCode; - - - public ResponseStatusCodeException(int statusCode) { - this.statusCode = statusCode; - } - - - public int getStatusCode() { - return this.statusCode; - } - -} diff --git a/spring-integration-http/src/main/java/org/springframework/integration/http/config/HttpInboundEndpointParser.java b/spring-integration-http/src/main/java/org/springframework/integration/http/config/HttpInboundEndpointParser.java index 954ba30691..25c54faffc 100644 --- a/spring-integration-http/src/main/java/org/springframework/integration/http/config/HttpInboundEndpointParser.java +++ b/spring-integration-http/src/main/java/org/springframework/integration/http/config/HttpInboundEndpointParser.java @@ -47,8 +47,8 @@ public class HttpInboundEndpointParser extends AbstractSingleBeanDefinitionParse @Override protected String getBeanClassName(Element element) { return element.hasAttribute("view-name") - ? "org.springframework.integration.http.HttpRequestHandlingController" - : "org.springframework.integration.http.HttpRequestHandlingMessagingGateway"; + ? "org.springframework.integration.http.inbound.HttpRequestHandlingController" + : "org.springframework.integration.http.inbound.HttpRequestHandlingMessagingGateway"; } @Override diff --git a/spring-integration-http/src/main/java/org/springframework/integration/http/config/HttpOutboundChannelAdapterParser.java b/spring-integration-http/src/main/java/org/springframework/integration/http/config/HttpOutboundChannelAdapterParser.java index e04ea2509c..407e7fb92f 100644 --- a/spring-integration-http/src/main/java/org/springframework/integration/http/config/HttpOutboundChannelAdapterParser.java +++ b/spring-integration-http/src/main/java/org/springframework/integration/http/config/HttpOutboundChannelAdapterParser.java @@ -39,12 +39,10 @@ import org.springframework.util.xml.DomUtils; */ public class HttpOutboundChannelAdapterParser extends AbstractOutboundChannelAdapterParser { - private static final String PACKAGE_PATH = "org.springframework.integration.http"; - @Override protected AbstractBeanDefinition parseConsumer(Element element, ParserContext parserContext) { BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition( - PACKAGE_PATH + ".HttpRequestExecutingMessageHandler"); + "org.springframework.integration.http.outbound.HttpRequestExecutingMessageHandler"); builder.addPropertyValue("expectReply", false); builder.addConstructorArgValue(element.getAttribute("url")); IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, "http-method"); @@ -61,7 +59,7 @@ public class HttpOutboundChannelAdapterParser extends AbstractOutboundChannelAda } else if (StringUtils.hasText(mappedRequestHeaders)) { BeanDefinitionBuilder headerMapperBuilder = BeanDefinitionBuilder.genericBeanDefinition( - "org.springframework.integration.http.DefaultHttpHeaderMapper"); + "org.springframework.integration.http.support.DefaultHttpHeaderMapper"); IntegrationNamespaceUtils.setValueIfAttributeDefined(headerMapperBuilder, element, "mapped-request-headers", "outboundHeaderNames"); builder.addPropertyValue("headerMapper", headerMapperBuilder.getBeanDefinition()); } diff --git a/spring-integration-http/src/main/java/org/springframework/integration/http/config/HttpOutboundGatewayParser.java b/spring-integration-http/src/main/java/org/springframework/integration/http/config/HttpOutboundGatewayParser.java index febb3347b6..d5b795630c 100644 --- a/spring-integration-http/src/main/java/org/springframework/integration/http/config/HttpOutboundGatewayParser.java +++ b/spring-integration-http/src/main/java/org/springframework/integration/http/config/HttpOutboundGatewayParser.java @@ -37,9 +37,6 @@ import org.springframework.util.xml.DomUtils; */ public class HttpOutboundGatewayParser extends AbstractConsumerEndpointParser { - private static final String PACKAGE_PATH = "org.springframework.integration.http"; - - @Override protected String getInputChannelAttributeName() { return "request-channel"; @@ -48,7 +45,7 @@ public class HttpOutboundGatewayParser extends AbstractConsumerEndpointParser { @Override protected BeanDefinitionBuilder parseHandler(Element element, ParserContext parserContext) { BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition( - PACKAGE_PATH + ".HttpRequestExecutingMessageHandler"); + "org.springframework.integration.http.outbound.HttpRequestExecutingMessageHandler"); builder.addConstructorArgValue(element.getAttribute("url")); IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, "http-method"); IntegrationNamespaceUtils.setReferenceIfAttributeDefined(builder, element, "message-converters"); @@ -65,7 +62,7 @@ public class HttpOutboundGatewayParser extends AbstractConsumerEndpointParser { } else if (StringUtils.hasText(mappedRequestHeaders) || StringUtils.hasText(mappedResponseHeaders)) { BeanDefinitionBuilder headerMapperBuilder = BeanDefinitionBuilder.genericBeanDefinition( - "org.springframework.integration.http.DefaultHttpHeaderMapper"); + "org.springframework.integration.http.support.DefaultHttpHeaderMapper"); IntegrationNamespaceUtils.setValueIfAttributeDefined(headerMapperBuilder, element, "mapped-request-headers", "outboundHeaderNames"); IntegrationNamespaceUtils.setValueIfAttributeDefined(headerMapperBuilder, element, "mapped-response-headers", "inboundHeaderNames"); builder.addPropertyValue("headerMapper", headerMapperBuilder.getBeanDefinition()); diff --git a/spring-integration-http/src/main/java/org/springframework/integration/http/MultipartAwareFormHttpMessageConverter.java b/spring-integration-http/src/main/java/org/springframework/integration/http/converter/MultipartAwareFormHttpMessageConverter.java similarity index 94% rename from spring-integration-http/src/main/java/org/springframework/integration/http/MultipartAwareFormHttpMessageConverter.java rename to spring-integration-http/src/main/java/org/springframework/integration/http/converter/MultipartAwareFormHttpMessageConverter.java index bcbb2e519e..c891cd9b75 100644 --- a/spring-integration-http/src/main/java/org/springframework/integration/http/MultipartAwareFormHttpMessageConverter.java +++ b/spring-integration-http/src/main/java/org/springframework/integration/http/converter/MultipartAwareFormHttpMessageConverter.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.springframework.integration.http; +package org.springframework.integration.http.converter; import java.io.IOException; import java.nio.charset.Charset; @@ -28,6 +28,9 @@ import org.springframework.http.converter.HttpMessageConverter; import org.springframework.http.converter.HttpMessageNotReadableException; import org.springframework.http.converter.HttpMessageNotWritableException; import org.springframework.http.converter.xml.XmlAwareFormHttpMessageConverter; +import org.springframework.integration.http.multipart.DefaultMultipartFileReader; +import org.springframework.integration.http.multipart.MultipartFileReader; +import org.springframework.integration.http.multipart.MultipartHttpInputMessage; import org.springframework.util.Assert; import org.springframework.util.LinkedMultiValueMap; import org.springframework.util.MultiValueMap; diff --git a/spring-integration-http/src/main/java/org/springframework/integration/http/SerializingHttpMessageConverter.java b/spring-integration-http/src/main/java/org/springframework/integration/http/converter/SerializingHttpMessageConverter.java similarity index 98% rename from spring-integration-http/src/main/java/org/springframework/integration/http/SerializingHttpMessageConverter.java rename to spring-integration-http/src/main/java/org/springframework/integration/http/converter/SerializingHttpMessageConverter.java index 984e1cbade..f613b8e5c6 100644 --- a/spring-integration-http/src/main/java/org/springframework/integration/http/SerializingHttpMessageConverter.java +++ b/spring-integration-http/src/main/java/org/springframework/integration/http/converter/SerializingHttpMessageConverter.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.springframework.integration.http; +package org.springframework.integration.http.converter; import java.io.ByteArrayOutputStream; import java.io.IOException; diff --git a/spring-integration-http/src/main/java/org/springframework/integration/http/HttpRequestHandlingController.java b/spring-integration-http/src/main/java/org/springframework/integration/http/inbound/HttpRequestHandlingController.java similarity index 98% rename from spring-integration-http/src/main/java/org/springframework/integration/http/HttpRequestHandlingController.java rename to spring-integration-http/src/main/java/org/springframework/integration/http/inbound/HttpRequestHandlingController.java index 77129a0367..00fba2cbb5 100644 --- a/spring-integration-http/src/main/java/org/springframework/integration/http/HttpRequestHandlingController.java +++ b/spring-integration-http/src/main/java/org/springframework/integration/http/inbound/HttpRequestHandlingController.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.springframework.integration.http; +package org.springframework.integration.http.inbound; import java.io.PrintWriter; import java.io.StringWriter; diff --git a/spring-integration-http/src/main/java/org/springframework/integration/http/HttpRequestHandlingEndpointSupport.java b/spring-integration-http/src/main/java/org/springframework/integration/http/inbound/HttpRequestHandlingEndpointSupport.java similarity index 97% rename from spring-integration-http/src/main/java/org/springframework/integration/http/HttpRequestHandlingEndpointSupport.java rename to spring-integration-http/src/main/java/org/springframework/integration/http/inbound/HttpRequestHandlingEndpointSupport.java index d9ba35685d..e30142fd5f 100644 --- a/spring-integration-http/src/main/java/org/springframework/integration/http/HttpRequestHandlingEndpointSupport.java +++ b/spring-integration-http/src/main/java/org/springframework/integration/http/inbound/HttpRequestHandlingEndpointSupport.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.springframework.integration.http; +package org.springframework.integration.http.inbound; import java.io.IOException; import java.util.ArrayList; @@ -42,6 +42,10 @@ import org.springframework.http.server.ServletServerHttpResponse; import org.springframework.integration.Message; import org.springframework.integration.MessagingException; import org.springframework.integration.gateway.MessagingGatewaySupport; +import org.springframework.integration.http.converter.MultipartAwareFormHttpMessageConverter; +import org.springframework.integration.http.converter.SerializingHttpMessageConverter; +import org.springframework.integration.http.multipart.MultipartHttpInputMessage; +import org.springframework.integration.http.support.DefaultHttpHeaderMapper; import org.springframework.integration.mapping.HeaderMapper; import org.springframework.integration.support.MessageBuilder; import org.springframework.util.Assert; diff --git a/spring-integration-http/src/main/java/org/springframework/integration/http/HttpRequestHandlingMessagingGateway.java b/spring-integration-http/src/main/java/org/springframework/integration/http/inbound/HttpRequestHandlingMessagingGateway.java similarity index 97% rename from spring-integration-http/src/main/java/org/springframework/integration/http/HttpRequestHandlingMessagingGateway.java rename to spring-integration-http/src/main/java/org/springframework/integration/http/inbound/HttpRequestHandlingMessagingGateway.java index cd77aecb16..574c3d3b3b 100644 --- a/spring-integration-http/src/main/java/org/springframework/integration/http/HttpRequestHandlingMessagingGateway.java +++ b/spring-integration-http/src/main/java/org/springframework/integration/http/inbound/HttpRequestHandlingMessagingGateway.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.springframework.integration.http; +package org.springframework.integration.http.inbound; import java.io.IOException; import java.util.List; @@ -28,6 +28,7 @@ import org.springframework.http.converter.HttpMessageConverter; import org.springframework.http.server.ServletServerHttpRequest; import org.springframework.http.server.ServletServerHttpResponse; import org.springframework.integration.MessagingException; +import org.springframework.integration.http.converter.MultipartAwareFormHttpMessageConverter; import org.springframework.util.MultiValueMap; import org.springframework.web.HttpRequestHandler; diff --git a/spring-integration-http/src/main/java/org/springframework/integration/http/DefaultMultipartFileReader.java b/spring-integration-http/src/main/java/org/springframework/integration/http/multipart/DefaultMultipartFileReader.java similarity index 95% rename from spring-integration-http/src/main/java/org/springframework/integration/http/DefaultMultipartFileReader.java rename to spring-integration-http/src/main/java/org/springframework/integration/http/multipart/DefaultMultipartFileReader.java index 3b5c5bf4d7..a7929ecf59 100644 --- a/spring-integration-http/src/main/java/org/springframework/integration/http/DefaultMultipartFileReader.java +++ b/spring-integration-http/src/main/java/org/springframework/integration/http/multipart/DefaultMultipartFileReader.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.springframework.integration.http; +package org.springframework.integration.http.multipart; import java.io.IOException; diff --git a/spring-integration-http/src/main/java/org/springframework/integration/http/FileCopyingMultipartFileReader.java b/spring-integration-http/src/main/java/org/springframework/integration/http/multipart/FileCopyingMultipartFileReader.java similarity index 97% rename from spring-integration-http/src/main/java/org/springframework/integration/http/FileCopyingMultipartFileReader.java rename to spring-integration-http/src/main/java/org/springframework/integration/http/multipart/FileCopyingMultipartFileReader.java index ba9d4f421e..c6ed57bdd1 100644 --- a/spring-integration-http/src/main/java/org/springframework/integration/http/FileCopyingMultipartFileReader.java +++ b/spring-integration-http/src/main/java/org/springframework/integration/http/multipart/FileCopyingMultipartFileReader.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.springframework.integration.http; +package org.springframework.integration.http.multipart; import java.io.File; import java.io.IOException; diff --git a/spring-integration-http/src/main/java/org/springframework/integration/http/MultipartFileReader.java b/spring-integration-http/src/main/java/org/springframework/integration/http/multipart/MultipartFileReader.java similarity index 94% rename from spring-integration-http/src/main/java/org/springframework/integration/http/MultipartFileReader.java rename to spring-integration-http/src/main/java/org/springframework/integration/http/multipart/MultipartFileReader.java index 9941fac735..ba6d9b9ac8 100644 --- a/spring-integration-http/src/main/java/org/springframework/integration/http/MultipartFileReader.java +++ b/spring-integration-http/src/main/java/org/springframework/integration/http/multipart/MultipartFileReader.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.springframework.integration.http; +package org.springframework.integration.http.multipart; import java.io.IOException; diff --git a/spring-integration-http/src/main/java/org/springframework/integration/http/MultipartHttpInputMessage.java b/spring-integration-http/src/main/java/org/springframework/integration/http/multipart/MultipartHttpInputMessage.java similarity index 97% rename from spring-integration-http/src/main/java/org/springframework/integration/http/MultipartHttpInputMessage.java rename to spring-integration-http/src/main/java/org/springframework/integration/http/multipart/MultipartHttpInputMessage.java index b83cff4bfd..14110cfa1b 100644 --- a/spring-integration-http/src/main/java/org/springframework/integration/http/MultipartHttpInputMessage.java +++ b/spring-integration-http/src/main/java/org/springframework/integration/http/multipart/MultipartHttpInputMessage.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.springframework.integration.http; +package org.springframework.integration.http.multipart; import java.util.Iterator; import java.util.List; diff --git a/spring-integration-http/src/main/java/org/springframework/integration/http/SimpleMultipartFileReader.java b/spring-integration-http/src/main/java/org/springframework/integration/http/multipart/SimpleMultipartFileReader.java similarity index 97% rename from spring-integration-http/src/main/java/org/springframework/integration/http/SimpleMultipartFileReader.java rename to spring-integration-http/src/main/java/org/springframework/integration/http/multipart/SimpleMultipartFileReader.java index a8c39dc789..344bb79c0e 100644 --- a/spring-integration-http/src/main/java/org/springframework/integration/http/SimpleMultipartFileReader.java +++ b/spring-integration-http/src/main/java/org/springframework/integration/http/multipart/SimpleMultipartFileReader.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.springframework.integration.http; +package org.springframework.integration.http.multipart; import java.io.IOException; import java.nio.charset.Charset; diff --git a/spring-integration-http/src/main/java/org/springframework/integration/http/UploadedMultipartFile.java b/spring-integration-http/src/main/java/org/springframework/integration/http/multipart/UploadedMultipartFile.java similarity index 98% rename from spring-integration-http/src/main/java/org/springframework/integration/http/UploadedMultipartFile.java rename to spring-integration-http/src/main/java/org/springframework/integration/http/multipart/UploadedMultipartFile.java index 44dbfb805a..97d14b35cb 100644 --- a/spring-integration-http/src/main/java/org/springframework/integration/http/UploadedMultipartFile.java +++ b/spring-integration-http/src/main/java/org/springframework/integration/http/multipart/UploadedMultipartFile.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.springframework.integration.http; +package org.springframework.integration.http.multipart; import java.io.ByteArrayInputStream; import java.io.File; diff --git a/spring-integration-http/src/main/java/org/springframework/integration/http/HttpRequestExecutingMessageHandler.java b/spring-integration-http/src/main/java/org/springframework/integration/http/outbound/HttpRequestExecutingMessageHandler.java similarity index 98% rename from spring-integration-http/src/main/java/org/springframework/integration/http/HttpRequestExecutingMessageHandler.java rename to spring-integration-http/src/main/java/org/springframework/integration/http/outbound/HttpRequestExecutingMessageHandler.java index e86228fa36..4ca9f3cbf4 100755 --- a/spring-integration-http/src/main/java/org/springframework/integration/http/HttpRequestExecutingMessageHandler.java +++ b/spring-integration-http/src/main/java/org/springframework/integration/http/outbound/HttpRequestExecutingMessageHandler.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.springframework.integration.http; +package org.springframework.integration.http.outbound; import java.net.URI; import java.nio.charset.Charset; @@ -46,6 +46,8 @@ import org.springframework.integration.MessageHandlingException; import org.springframework.integration.MessagingException; import org.springframework.integration.core.MessageHandler; import org.springframework.integration.handler.AbstractReplyProducingMessageHandler; +import org.springframework.integration.http.converter.SerializingHttpMessageConverter; +import org.springframework.integration.http.support.DefaultHttpHeaderMapper; import org.springframework.integration.mapping.HeaderMapper; import org.springframework.integration.support.MessageBuilder; import org.springframework.util.Assert; diff --git a/spring-integration-http/src/main/java/org/springframework/integration/http/DefaultHttpHeaderMapper.java b/spring-integration-http/src/main/java/org/springframework/integration/http/support/DefaultHttpHeaderMapper.java similarity index 98% rename from spring-integration-http/src/main/java/org/springframework/integration/http/DefaultHttpHeaderMapper.java rename to spring-integration-http/src/main/java/org/springframework/integration/http/support/DefaultHttpHeaderMapper.java index 064124747f..7240572271 100644 --- a/spring-integration-http/src/main/java/org/springframework/integration/http/DefaultHttpHeaderMapper.java +++ b/spring-integration-http/src/main/java/org/springframework/integration/http/support/DefaultHttpHeaderMapper.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.springframework.integration.http; +package org.springframework.integration.http.support; import java.util.HashMap; import java.util.List; diff --git a/spring-integration-http/src/test/java/org/springframework/integration/http/HttpRequestExecutingMessageHandlerTests.java b/spring-integration-http/src/test/java/org/springframework/integration/http/HttpRequestExecutingMessageHandlerTests.java index c32bfe43e8..4559fdb578 100644 --- a/spring-integration-http/src/test/java/org/springframework/integration/http/HttpRequestExecutingMessageHandlerTests.java +++ b/spring-integration-http/src/test/java/org/springframework/integration/http/HttpRequestExecutingMessageHandlerTests.java @@ -37,6 +37,7 @@ import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; import org.springframework.integration.Message; import org.springframework.integration.channel.QueueChannel; +import org.springframework.integration.http.outbound.HttpRequestExecutingMessageHandler; import org.springframework.integration.support.MessageBuilder; import org.springframework.util.MultiValueMap; import org.springframework.web.client.RestClientException; diff --git a/spring-integration-http/src/test/java/org/springframework/integration/http/HttpRequestHandlingControllerTests.java b/spring-integration-http/src/test/java/org/springframework/integration/http/HttpRequestHandlingControllerTests.java index ddd27e0ec0..5978586ea2 100644 --- a/spring-integration-http/src/test/java/org/springframework/integration/http/HttpRequestHandlingControllerTests.java +++ b/spring-integration-http/src/test/java/org/springframework/integration/http/HttpRequestHandlingControllerTests.java @@ -26,6 +26,7 @@ import org.springframework.integration.Message; import org.springframework.integration.channel.DirectChannel; import org.springframework.integration.channel.QueueChannel; import org.springframework.integration.handler.AbstractReplyProducingMessageHandler; +import org.springframework.integration.http.inbound.HttpRequestHandlingController; import org.springframework.mock.web.MockHttpServletResponse; import org.springframework.validation.Errors; import org.springframework.validation.ObjectError; diff --git a/spring-integration-http/src/test/java/org/springframework/integration/http/HttpRequestHandlingMessagingGatewayTests.java b/spring-integration-http/src/test/java/org/springframework/integration/http/HttpRequestHandlingMessagingGatewayTests.java index 792f41d7ba..9ad05c478e 100644 --- a/spring-integration-http/src/test/java/org/springframework/integration/http/HttpRequestHandlingMessagingGatewayTests.java +++ b/spring-integration-http/src/test/java/org/springframework/integration/http/HttpRequestHandlingMessagingGatewayTests.java @@ -38,6 +38,7 @@ import org.springframework.integration.Message; import org.springframework.integration.channel.DirectChannel; import org.springframework.integration.channel.QueueChannel; import org.springframework.integration.handler.AbstractReplyProducingMessageHandler; +import org.springframework.integration.http.inbound.HttpRequestHandlingMessagingGateway; import org.springframework.mock.web.MockHttpServletResponse; import org.springframework.util.LinkedMultiValueMap; import org.springframework.util.SerializationUtils; diff --git a/spring-integration-http/src/test/java/org/springframework/integration/http/UriVariableExpressionTests.java b/spring-integration-http/src/test/java/org/springframework/integration/http/UriVariableExpressionTests.java index 4523c6a2ca..cd487127dd 100644 --- a/spring-integration-http/src/test/java/org/springframework/integration/http/UriVariableExpressionTests.java +++ b/spring-integration-http/src/test/java/org/springframework/integration/http/UriVariableExpressionTests.java @@ -29,6 +29,7 @@ import org.springframework.http.HttpMethod; import org.springframework.http.client.ClientHttpRequest; import org.springframework.http.client.SimpleClientHttpRequestFactory; import org.springframework.integration.Message; +import org.springframework.integration.http.outbound.HttpRequestExecutingMessageHandler; import org.springframework.integration.message.GenericMessage; /** diff --git a/spring-integration-http/src/test/java/org/springframework/integration/http/config/HttpInboundChannelAdapterParserTests.java b/spring-integration-http/src/test/java/org/springframework/integration/http/config/HttpInboundChannelAdapterParserTests.java index b72a14e304..0148cccf16 100644 --- a/spring-integration-http/src/test/java/org/springframework/integration/http/config/HttpInboundChannelAdapterParserTests.java +++ b/spring-integration-http/src/test/java/org/springframework/integration/http/config/HttpInboundChannelAdapterParserTests.java @@ -38,9 +38,9 @@ import org.springframework.http.HttpMethod; import org.springframework.integration.Message; import org.springframework.integration.core.PollableChannel; import org.springframework.integration.history.MessageHistory; -import org.springframework.integration.http.HttpRequestHandlingController; -import org.springframework.integration.http.HttpRequestHandlingMessagingGateway; import org.springframework.integration.http.MockHttpServletRequest; +import org.springframework.integration.http.inbound.HttpRequestHandlingController; +import org.springframework.integration.http.inbound.HttpRequestHandlingMessagingGateway; import org.springframework.integration.test.util.TestUtils; import org.springframework.mock.web.MockHttpServletResponse; import org.springframework.test.context.ContextConfiguration; diff --git a/spring-integration-http/src/test/java/org/springframework/integration/http/config/HttpInboundGatewayParserTests.java b/spring-integration-http/src/test/java/org/springframework/integration/http/config/HttpInboundGatewayParserTests.java index 2381618c0b..d926b35531 100644 --- a/spring-integration-http/src/test/java/org/springframework/integration/http/config/HttpInboundGatewayParserTests.java +++ b/spring-integration-http/src/test/java/org/springframework/integration/http/config/HttpInboundGatewayParserTests.java @@ -34,10 +34,10 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.integration.Message; import org.springframework.integration.core.PollableChannel; import org.springframework.integration.core.SubscribableChannel; -import org.springframework.integration.http.HttpRequestHandlingController; -import org.springframework.integration.http.HttpRequestHandlingMessagingGateway; import org.springframework.integration.http.MockHttpServletRequest; import org.springframework.integration.http.MockHttpServletResponse; +import org.springframework.integration.http.inbound.HttpRequestHandlingController; +import org.springframework.integration.http.inbound.HttpRequestHandlingMessagingGateway; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; diff --git a/spring-integration-http/src/test/java/org/springframework/integration/http/config/HttpOutboundChannelAdapterParserTests.java b/spring-integration-http/src/test/java/org/springframework/integration/http/config/HttpOutboundChannelAdapterParserTests.java index 0b690a9444..594eb13d3f 100644 --- a/spring-integration-http/src/test/java/org/springframework/integration/http/config/HttpOutboundChannelAdapterParserTests.java +++ b/spring-integration-http/src/test/java/org/springframework/integration/http/config/HttpOutboundChannelAdapterParserTests.java @@ -36,7 +36,7 @@ import org.springframework.http.client.ClientHttpRequestFactory; import org.springframework.http.client.ClientHttpResponse; import org.springframework.http.client.SimpleClientHttpRequestFactory; import org.springframework.integration.endpoint.AbstractEndpoint; -import org.springframework.integration.http.HttpRequestExecutingMessageHandler; +import org.springframework.integration.http.outbound.HttpRequestExecutingMessageHandler; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import org.springframework.util.ObjectUtils; diff --git a/spring-integration-http/src/test/java/org/springframework/integration/http/config/HttpOutboundGatewayParserTests.java b/spring-integration-http/src/test/java/org/springframework/integration/http/config/HttpOutboundGatewayParserTests.java index 80ba14e3b1..22c6f3a648 100644 --- a/spring-integration-http/src/test/java/org/springframework/integration/http/config/HttpOutboundGatewayParserTests.java +++ b/spring-integration-http/src/test/java/org/springframework/integration/http/config/HttpOutboundGatewayParserTests.java @@ -38,7 +38,7 @@ import org.springframework.http.client.ClientHttpResponse; import org.springframework.http.client.SimpleClientHttpRequestFactory; import org.springframework.integration.MessageChannel; import org.springframework.integration.endpoint.AbstractEndpoint; -import org.springframework.integration.http.HttpRequestExecutingMessageHandler; +import org.springframework.integration.http.outbound.HttpRequestExecutingMessageHandler; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import org.springframework.util.ObjectUtils; From 1df19858b3d8ba863e46a21bce4c6233f22bb6d0 Mon Sep 17 00:00:00 2001 From: Mark Fisher Date: Fri, 5 Nov 2010 18:23:56 -0400 Subject: [PATCH 71/82] moved test code to correspond to refactored package structure --- .../http/{ => inbound}/HttpRequestHandlingControllerTests.java | 3 ++- .../HttpRequestHandlingMessagingGatewayTests.java | 3 ++- .../HttpRequestExecutingMessageHandlerTests.java | 2 +- .../http/{ => outbound}/UriVariableExpressionTests.java | 2 +- 4 files changed, 6 insertions(+), 4 deletions(-) rename spring-integration-http/src/test/java/org/springframework/integration/http/{ => inbound}/HttpRequestHandlingControllerTests.java (98%) rename spring-integration-http/src/test/java/org/springframework/integration/http/{ => inbound}/HttpRequestHandlingMessagingGatewayTests.java (98%) rename spring-integration-http/src/test/java/org/springframework/integration/http/{ => outbound}/HttpRequestExecutingMessageHandlerTests.java (99%) rename spring-integration-http/src/test/java/org/springframework/integration/http/{ => outbound}/UriVariableExpressionTests.java (97%) diff --git a/spring-integration-http/src/test/java/org/springframework/integration/http/HttpRequestHandlingControllerTests.java b/spring-integration-http/src/test/java/org/springframework/integration/http/inbound/HttpRequestHandlingControllerTests.java similarity index 98% rename from spring-integration-http/src/test/java/org/springframework/integration/http/HttpRequestHandlingControllerTests.java rename to spring-integration-http/src/test/java/org/springframework/integration/http/inbound/HttpRequestHandlingControllerTests.java index 5978586ea2..bed51dede9 100644 --- a/spring-integration-http/src/test/java/org/springframework/integration/http/HttpRequestHandlingControllerTests.java +++ b/spring-integration-http/src/test/java/org/springframework/integration/http/inbound/HttpRequestHandlingControllerTests.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.springframework.integration.http; +package org.springframework.integration.http.inbound; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; @@ -26,6 +26,7 @@ import org.springframework.integration.Message; import org.springframework.integration.channel.DirectChannel; import org.springframework.integration.channel.QueueChannel; import org.springframework.integration.handler.AbstractReplyProducingMessageHandler; +import org.springframework.integration.http.MockHttpServletRequest; import org.springframework.integration.http.inbound.HttpRequestHandlingController; import org.springframework.mock.web.MockHttpServletResponse; import org.springframework.validation.Errors; diff --git a/spring-integration-http/src/test/java/org/springframework/integration/http/HttpRequestHandlingMessagingGatewayTests.java b/spring-integration-http/src/test/java/org/springframework/integration/http/inbound/HttpRequestHandlingMessagingGatewayTests.java similarity index 98% rename from spring-integration-http/src/test/java/org/springframework/integration/http/HttpRequestHandlingMessagingGatewayTests.java rename to spring-integration-http/src/test/java/org/springframework/integration/http/inbound/HttpRequestHandlingMessagingGatewayTests.java index 9ad05c478e..d039d0b7f6 100644 --- a/spring-integration-http/src/test/java/org/springframework/integration/http/HttpRequestHandlingMessagingGatewayTests.java +++ b/spring-integration-http/src/test/java/org/springframework/integration/http/inbound/HttpRequestHandlingMessagingGatewayTests.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.springframework.integration.http; +package org.springframework.integration.http.inbound; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; @@ -38,6 +38,7 @@ import org.springframework.integration.Message; import org.springframework.integration.channel.DirectChannel; import org.springframework.integration.channel.QueueChannel; import org.springframework.integration.handler.AbstractReplyProducingMessageHandler; +import org.springframework.integration.http.MockHttpServletRequest; import org.springframework.integration.http.inbound.HttpRequestHandlingMessagingGateway; import org.springframework.mock.web.MockHttpServletResponse; import org.springframework.util.LinkedMultiValueMap; diff --git a/spring-integration-http/src/test/java/org/springframework/integration/http/HttpRequestExecutingMessageHandlerTests.java b/spring-integration-http/src/test/java/org/springframework/integration/http/outbound/HttpRequestExecutingMessageHandlerTests.java similarity index 99% rename from spring-integration-http/src/test/java/org/springframework/integration/http/HttpRequestExecutingMessageHandlerTests.java rename to spring-integration-http/src/test/java/org/springframework/integration/http/outbound/HttpRequestExecutingMessageHandlerTests.java index 4559fdb578..c671b216da 100644 --- a/spring-integration-http/src/test/java/org/springframework/integration/http/HttpRequestExecutingMessageHandlerTests.java +++ b/spring-integration-http/src/test/java/org/springframework/integration/http/outbound/HttpRequestExecutingMessageHandlerTests.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.springframework.integration.http; +package org.springframework.integration.http.outbound; import static junit.framework.Assert.assertEquals; import static junit.framework.Assert.assertNull; diff --git a/spring-integration-http/src/test/java/org/springframework/integration/http/UriVariableExpressionTests.java b/spring-integration-http/src/test/java/org/springframework/integration/http/outbound/UriVariableExpressionTests.java similarity index 97% rename from spring-integration-http/src/test/java/org/springframework/integration/http/UriVariableExpressionTests.java rename to spring-integration-http/src/test/java/org/springframework/integration/http/outbound/UriVariableExpressionTests.java index cd487127dd..3a22094838 100644 --- a/spring-integration-http/src/test/java/org/springframework/integration/http/UriVariableExpressionTests.java +++ b/spring-integration-http/src/test/java/org/springframework/integration/http/outbound/UriVariableExpressionTests.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.springframework.integration.http; +package org.springframework.integration.http.outbound; import static org.junit.Assert.assertEquals; From a3d50d61462b1b8ce6fd3470e3249fd67248317f Mon Sep 17 00:00:00 2001 From: Mark Fisher Date: Fri, 5 Nov 2010 18:27:35 -0400 Subject: [PATCH 72/82] updated HTTP section in reference manual with pacakge info (inbound and outbound) on plain bean examples --- docs/src/reference/docbook/http.xml | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/docs/src/reference/docbook/http.xml b/docs/src/reference/docbook/http.xml index e25a5671e3..621b1f6224 100644 --- a/docs/src/reference/docbook/http.xml +++ b/docs/src/reference/docbook/http.xml @@ -18,7 +18,7 @@ support the HTTP inbound adapters need to be deployed within a servlet container. The easiest way to do this is to provide a servlet definition in web.xml, see for further details. Below is an example bean definition for a simple HTTP inbound endpoint. - + ]]> @@ -51,7 +51,7 @@ configured to serve as a Spring MVC Controller with a view name. Because of the constructor arg value of TRUE, it wait for a reply. This also shows how to customize the HTTP methods accepted by the gateway, which are POST and GET by default. - + @@ -75,14 +75,14 @@ To configure the HttpRequestExecutingMessageHandler write a bean definition like this: - + ]]> This bean definition will execute HTTP requests by delegating to a RestTemplate. That template in turn delegates to a list of HttpMessageConverters to generate the HTTP request body from the Message payload. You can configure those converters as well as the ClientHttpRequestFactory instance to use: - + @@ -176,7 +176,7 @@ On the server side we have the following configuration: - + The 'httpInboundAdapter' will receive the request, convert it to a Message with a payload as LinkedMultiValueMap which we are parsing in the 'multipartReceiver' service-activator; - multipartRequest){ - System.out.println("### Successfully recieved multipart request ###"); + multipartRequest){ + System.out.println("### Successfully received multipart request ###"); for (String elementName : multipartRequest.keySet()) { if (elementName.equals("company")){ System.out.println("\t" + elementName + " - " + @@ -201,7 +201,7 @@ we are parsing in the 'multipartReceiver' service-activator; ]]> You should see the following output: - From 308231f669a697a591bc7dca2bc3bfe5d80a0b10 Mon Sep 17 00:00:00 2001 From: Mark Fisher Date: Fri, 5 Nov 2010 18:33:53 -0400 Subject: [PATCH 73/82] avoiding warnings --- .../ip/tcp/TcpSendingMessageHandlerTests.java | 36 +++++++++++-------- 1 file changed, 22 insertions(+), 14 deletions(-) diff --git a/spring-integration-ip/src/test/java/org/springframework/integration/ip/tcp/TcpSendingMessageHandlerTests.java b/spring-integration-ip/src/test/java/org/springframework/integration/ip/tcp/TcpSendingMessageHandlerTests.java index a3dff9e1d0..7d8bf30b16 100644 --- a/spring-integration-ip/src/test/java/org/springframework/integration/ip/tcp/TcpSendingMessageHandlerTests.java +++ b/spring-integration-ip/src/test/java/org/springframework/integration/ip/tcp/TcpSendingMessageHandlerTests.java @@ -38,6 +38,8 @@ import java.util.concurrent.atomic.AtomicBoolean; import javax.net.ServerSocketFactory; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; import org.junit.Test; import org.springframework.core.serializer.DefaultDeserializer; @@ -62,6 +64,9 @@ import org.springframework.integration.support.MessageBuilder; */ public class TcpSendingMessageHandlerTests { + private static final Log logger = LogFactory.getLog(TcpSendingMessageHandlerTests.class); + + private void readFully(InputStream is, byte[] buff) throws IOException { for (int i = 0; i < buff.length; i++) { buff[i] = (byte) is.read(); @@ -86,7 +91,8 @@ public class TcpSendingMessageHandlerTests { b = ("Reply" + (++i) + "\r\n").getBytes(); socket.getOutputStream().write(b); } - } catch (Exception e) { + } + catch (Exception e) { if (!done.get()) { e.printStackTrace(); } @@ -745,16 +751,16 @@ public class TcpSendingMessageHandlerTests { int i = 0; while (true) { ObjectInputStream ois = new ObjectInputStream(socket.getInputStream()); - Object in; + Object in = null; ObjectOutputStream oos = new ObjectOutputStream(socket.getOutputStream()); if (i == 0) { in = ois.readObject(); -// System.out.println(in); + logger.debug("read object: " + in); oos.writeObject("world!"); ois = new ObjectInputStream(socket.getInputStream()); oos = new ObjectOutputStream(socket.getOutputStream()); in = ois.readObject(); -// System.out.println(in); + logger.debug("read object: " + in); oos.writeObject("world!"); ois = new ObjectInputStream(socket.getInputStream()); oos = new ObjectOutputStream(socket.getOutputStream()); @@ -762,7 +768,8 @@ public class TcpSendingMessageHandlerTests { in = ois.readObject(); oos.writeObject("Reply" + (++i)); } - } catch (Exception e) { + } + catch (Exception e) { if (!done.get()) { e.printStackTrace(); } @@ -815,7 +822,7 @@ public class TcpSendingMessageHandlerTests { ObjectOutputStream oos = new ObjectOutputStream(socket.getOutputStream()); if (i == 100) { in = ois.readObject(); -// System.out.println(in); + logger.debug("read object: " + in); oos.writeObject("world!"); ois = new ObjectInputStream(socket.getInputStream()); oos = new ObjectOutputStream(socket.getOutputStream()); @@ -855,7 +862,7 @@ public class TcpSendingMessageHandlerTests { assertNotNull(mOut); results.add((String) mOut.getPayload()); } -// System.out.println(results); + logger.debug("results: " + results); for (int i = 100; i < 1100; i++) { assertTrue("Missing Reply" + i, results.remove("Reply" + i)); } @@ -876,16 +883,16 @@ public class TcpSendingMessageHandlerTests { int i = 0; while (true) { ObjectInputStream ois = new ObjectInputStream(socket.getInputStream()); - Object in; + Object in = null; ObjectOutputStream oos = new ObjectOutputStream(socket.getOutputStream()); if (i == 0) { in = ois.readObject(); -// System.out.println(in); + logger.debug("read object: " + in); oos.writeObject("world!"); ois = new ObjectInputStream(socket.getInputStream()); oos = new ObjectOutputStream(socket.getOutputStream()); in = ois.readObject(); -// System.out.println(in); + logger.debug("read object: " + in); oos.writeObject("world!"); ois = new ObjectInputStream(socket.getInputStream()); oos = new ObjectOutputStream(socket.getOutputStream()); @@ -893,7 +900,8 @@ public class TcpSendingMessageHandlerTests { in = ois.readObject(); oos.writeObject("Reply" + (++i)); } - } catch (Exception e) { + } + catch (Exception e) { if (!done.get()) { e.printStackTrace(); } @@ -932,16 +940,16 @@ public class TcpSendingMessageHandlerTests { int i = 0; while (true) { ObjectInputStream ois = new ObjectInputStream(socket.getInputStream()); - Object in; + Object in = null; ObjectOutputStream oos = new ObjectOutputStream(socket.getOutputStream()); if (i == 0) { in = ois.readObject(); -// System.out.println(in); + logger.debug("read object: " + in); oos.writeObject("world!"); ois = new ObjectInputStream(socket.getInputStream()); oos = new ObjectOutputStream(socket.getOutputStream()); in = ois.readObject(); -// System.out.println(in); + logger.debug("read object: " + in); oos.writeObject("world!"); ois = new ObjectInputStream(socket.getInputStream()); oos = new ObjectOutputStream(socket.getOutputStream()); From cfb378ab4feb3462db339a6069e0f412ca9b457f Mon Sep 17 00:00:00 2001 From: Mark Fisher Date: Fri, 5 Nov 2010 18:34:58 -0400 Subject: [PATCH 74/82] removed unused imports in tests --- .../jms/config/JmsInboundChannelAdapterParserTests.java | 1 - .../jms/config/JmsMessageDrivenChannelAdapterParserTests.java | 1 - 2 files changed, 2 deletions(-) diff --git a/spring-integration-jms/src/test/java/org/springframework/integration/jms/config/JmsInboundChannelAdapterParserTests.java b/spring-integration-jms/src/test/java/org/springframework/integration/jms/config/JmsInboundChannelAdapterParserTests.java index fddddc4e89..e18630f1bf 100644 --- a/spring-integration-jms/src/test/java/org/springframework/integration/jms/config/JmsInboundChannelAdapterParserTests.java +++ b/spring-integration-jms/src/test/java/org/springframework/integration/jms/config/JmsInboundChannelAdapterParserTests.java @@ -16,7 +16,6 @@ package org.springframework.integration.jms.config; -import static junit.framework.Assert.assertTrue; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; diff --git a/spring-integration-jms/src/test/java/org/springframework/integration/jms/config/JmsMessageDrivenChannelAdapterParserTests.java b/spring-integration-jms/src/test/java/org/springframework/integration/jms/config/JmsMessageDrivenChannelAdapterParserTests.java index d71a8730a7..d8438bd53b 100644 --- a/spring-integration-jms/src/test/java/org/springframework/integration/jms/config/JmsMessageDrivenChannelAdapterParserTests.java +++ b/spring-integration-jms/src/test/java/org/springframework/integration/jms/config/JmsMessageDrivenChannelAdapterParserTests.java @@ -16,7 +16,6 @@ package org.springframework.integration.jms.config; -import static junit.framework.Assert.assertTrue; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; From 53b132b7b51b8b52519435c740a6885c77fa7e86 Mon Sep 17 00:00:00 2001 From: Mark Fisher Date: Fri, 5 Nov 2010 18:48:58 -0400 Subject: [PATCH 75/82] removed unused imports --- .../org/springframework/integration/mail/Pop3MailReceiver.java | 1 - .../springframework/integration/mail/Pop3MailReceiverTests.java | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/spring-integration-mail/src/main/java/org/springframework/integration/mail/Pop3MailReceiver.java b/spring-integration-mail/src/main/java/org/springframework/integration/mail/Pop3MailReceiver.java index 4a2fb337c4..bf98d8555b 100755 --- a/spring-integration-mail/src/main/java/org/springframework/integration/mail/Pop3MailReceiver.java +++ b/spring-integration-mail/src/main/java/org/springframework/integration/mail/Pop3MailReceiver.java @@ -16,7 +16,6 @@ package org.springframework.integration.mail; -import javax.mail.Folder; import javax.mail.Message; import javax.mail.MessagingException; import javax.mail.URLName; diff --git a/spring-integration-mail/src/test/java/org/springframework/integration/mail/Pop3MailReceiverTests.java b/spring-integration-mail/src/test/java/org/springframework/integration/mail/Pop3MailReceiverTests.java index fed5f2b9ec..acc3a47b36 100644 --- a/spring-integration-mail/src/test/java/org/springframework/integration/mail/Pop3MailReceiverTests.java +++ b/spring-integration-mail/src/test/java/org/springframework/integration/mail/Pop3MailReceiverTests.java @@ -13,6 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.springframework.integration.mail; import static org.mockito.Mockito.doAnswer; @@ -26,7 +27,6 @@ import javax.mail.Folder; import javax.mail.Message; import javax.mail.internet.MimeMessage; -import org.junit.Ignore; import org.junit.Test; import org.mockito.invocation.InvocationOnMock; import org.mockito.stubbing.Answer; From 172d97ddeb12589b6338422df4906720f88c27e4 Mon Sep 17 00:00:00 2001 From: Chris Beams Date: Fri, 5 Nov 2010 22:41:32 -0700 Subject: [PATCH 76/82] Update symlinks during :docs:uploadArchives Previous to this change, symlinks at http://static.springsource.org/spring-integration/docs had to be maintained by hand. The build now automatically updates: * 'Wildcard' symlinks (e.g.: 2.0.x -> 2.0.0.RC1) if the release type is anything other than SNAPSHOT. * 'Latest GA' symlink (e.g.: latest-ga -> 1.0.3.RELEASE) if the release type is RELEASE. Also, deletion of the docs zip archive is now consolidated into the same 'sshexec' command as the unzipping itself. Unzipping is now done with -q (quiet) to cut down on output noise. --- docs/build.gradle | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/docs/build.gradle b/docs/build.gradle index 9c3ea47505..c2152ec1b2 100644 --- a/docs/build.gradle +++ b/docs/build.gradle @@ -225,13 +225,20 @@ uploadArchives { classpath: configurations.scpAntTask.asPath) // copy the archive, unpack it, then delete it - def unpackCommand = "cd ${remoteDocsDir} && unzip -K -o ${archive.archiveName}" - def deleteCommand = "rm ${remoteDocsDir}/${archive.archiveName}" + def unpackCommand = "cd ${remoteDocsDir} && rm -rf ${version} && unzip -qKo ${archive.archiveName} && rm ${archive.archiveName}" + def wildcardSymlinkCommand = "cd ${remoteDocsDir} && rm -f ${version.wildcardValue} && ln -s ${version} ${version.wildcardValue}" + def latestGASymlinkCommand = "cd ${remoteDocsDir} && rm -f latest-ga && ln -s ${version} latest-ga" - println "sshexec ${unpackCommand}" + println "Unpacking docs archive: (${unpackCommand})" sshexec(host: sshHost, username: sshUsername, keyfile: sshPrivateKey, command: unpackCommand) - println "sshexec ${deleteCommand}" - sshexec(host: sshHost, username: sshUsername, keyfile: sshPrivateKey, command: deleteCommand) + if (version.releaseType != 'SNAPSHOT') { + println "Creating wildcard symlink: (${wildcardSymlinkCommand})" + sshexec(host: sshHost, username: sshUsername, keyfile: sshPrivateKey, command: wildcardSymlinkCommand) + } + if (version.releaseType == 'RELEASE') { + println "Creating latest-ga symlink: (${latestGASymlinkCommand})" + sshexec(host: sshHost, username: sshUsername, keyfile: sshPrivateKey, command: latestGASymlinkCommand) + } println "UPLOAD SUCCESSFUL - validate by visiting ${docUrl}" } } From 16458de1f5427217d4b164b363bb1d57dae9541b Mon Sep 17 00:00:00 2001 From: Oleg Zhurakousky Date: Sat, 6 Nov 2010 08:11:11 -0400 Subject: [PATCH 77/82] INT-1553, more polishing on Twitter --- .../twitter/config/ConnectionParser.java | 16 +--------------- .../TwitterSendingMessageHandlerParser.java | 4 +--- .../inbound/AbstractTwitterMessageSource.java | 6 ++---- 3 files changed, 4 insertions(+), 22 deletions(-) diff --git a/spring-integration-twitter/src/main/java/org/springframework/integration/twitter/config/ConnectionParser.java b/spring-integration-twitter/src/main/java/org/springframework/integration/twitter/config/ConnectionParser.java index 17f5f3da90..5bc2a38d4b 100644 --- a/spring-integration-twitter/src/main/java/org/springframework/integration/twitter/config/ConnectionParser.java +++ b/spring-integration-twitter/src/main/java/org/springframework/integration/twitter/config/ConnectionParser.java @@ -37,23 +37,9 @@ public class ConnectionParser extends AbstractSingleBeanDefinitionParser { return BASE_PACKAGE + ".oauth.OAuthTwitterFactoryBean"; } - @Override - protected boolean shouldGenerateIdAsFallback() { - return true; - } - @Override protected void doParse(Element element, ParserContext parserContext, BeanDefinitionBuilder builder) { -// String ref = element.getAttribute("twitter-connection"); -// if (StringUtils.hasText(ref)) { -// builder.addPropertyReference("twitterConnection", ref); -// } -// else { -// for (String attribute : new String[] { "consumer-key", "consumer-secret", "access-token", "access-token-secret" }) { -// IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, attribute); -// } -// } - + BeanDefinitionBuilder accessTokenBuilder = BeanDefinitionBuilder.genericBeanDefinition("twitter4j.http.AccessToken"); accessTokenBuilder.addConstructorArgValue(element.getAttribute("access-token")); accessTokenBuilder.addConstructorArgValue(element.getAttribute("access-token-secret")); diff --git a/spring-integration-twitter/src/main/java/org/springframework/integration/twitter/config/TwitterSendingMessageHandlerParser.java b/spring-integration-twitter/src/main/java/org/springframework/integration/twitter/config/TwitterSendingMessageHandlerParser.java index 2803f13b42..fee83a1af7 100644 --- a/spring-integration-twitter/src/main/java/org/springframework/integration/twitter/config/TwitterSendingMessageHandlerParser.java +++ b/spring-integration-twitter/src/main/java/org/springframework/integration/twitter/config/TwitterSendingMessageHandlerParser.java @@ -18,13 +18,11 @@ package org.springframework.integration.twitter.config; import static org.springframework.integration.twitter.config.TwitterNamespaceHandler.BASE_PACKAGE; -import org.w3c.dom.Element; - import org.springframework.beans.factory.support.AbstractBeanDefinition; import org.springframework.beans.factory.support.BeanDefinitionBuilder; import org.springframework.beans.factory.xml.ParserContext; import org.springframework.integration.config.xml.AbstractOutboundChannelAdapterParser; -import org.springframework.integration.config.xml.IntegrationNamespaceUtils; +import org.w3c.dom.Element; /** * Parser for all outbound Twitter adapters diff --git a/spring-integration-twitter/src/main/java/org/springframework/integration/twitter/inbound/AbstractTwitterMessageSource.java b/spring-integration-twitter/src/main/java/org/springframework/integration/twitter/inbound/AbstractTwitterMessageSource.java index 73ddc759df..4f8904fa65 100644 --- a/spring-integration-twitter/src/main/java/org/springframework/integration/twitter/inbound/AbstractTwitterMessageSource.java +++ b/spring-integration-twitter/src/main/java/org/springframework/integration/twitter/inbound/AbstractTwitterMessageSource.java @@ -33,8 +33,6 @@ import org.springframework.integration.history.TrackableComponent; import org.springframework.integration.store.MetadataStore; import org.springframework.integration.store.SimpleMetadataStore; import org.springframework.integration.support.MessageBuilder; -import org.springframework.scheduling.TaskScheduler; -import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler; import org.springframework.util.Assert; import org.springframework.util.StringUtils; @@ -47,7 +45,7 @@ import twitter4j.Twitter; * messages when using the Twitter API. This class also handles keeping track of * the latest inbound message it has received and avoiding, where possible, * redelivery of common messages. This functionality is enabled using the - * {@link org.springframework.integration.store.MetadataStore} + * {@link org.springframework.integration.store.MetadataStore} * strategy. * * @author Josh Long @@ -129,7 +127,6 @@ public abstract class AbstractTwitterMessageSource extends AbstractEndpoint @SuppressWarnings("unchecked") protected void forwardAll(List tResponses) { - Object o = tResponses.iterator(); Collections.sort(tResponses, this.getComparator()); for (T twitterResponse : tResponses) { forward(twitterResponse); @@ -195,6 +192,7 @@ public abstract class AbstractTwitterMessageSource extends AbstractEndpoint } protected void markLastStatusId(long statusId) { + this.markerId = statusId; this.metadataStore.put(this.metadataKey, String.valueOf(statusId)); } } From 56143b63aa481934def83a253899b6eaff6391b6 Mon Sep 17 00:00:00 2001 From: Oleg Zhurakousky Date: Mon, 8 Nov 2010 09:03:44 -0500 Subject: [PATCH 78/82] INT-1553 initial refactoring to introduce Twitter4jTemplate in place of the twitter-connection --- .../twitter/core/Twitter4jTemplate.java | 151 ++++++++++++++++++ .../core/TwitterOperationException.java | 55 +++++++ .../twitter/core/TwitterOperations.java | 42 +++++ .../inbound/AbstractTwitterMessageSource.java | 9 +- .../DirectMessageReceivingMessageSource.java | 3 +- .../MentionReceivingMessageSource.java | 3 +- .../inbound/RateLimitStatusTrigger.java | 16 +- .../TimelineUpdateReceivingMessageSource.java | 3 +- .../oauth/OAuthTwitterFactoryBean.java | 68 -------- ...bstractOutboundTwitterEndpointSupport.java | 17 +- .../DirectMessageSendingMessageHandler.java | 17 +- .../TimelineUpdateSendingMessageHandler.java | 3 +- ...stReceivingMessageSourceParser-context.xml | 6 +- ...TestReceivingMessageSourceParserTests.java | 26 +++ ...estSendingMessageHandlerParser-context.xml | 6 +- .../TwitterConnectionParserTests-context.xml | 22 --- .../config/TwitterConnectionParserTests.java | 50 ------ .../twitter/core/Twitter4jTemplateTests.java | 30 ++++ ...ectMessageReceivingMessageSourceTests.java | 12 +- .../inbound/RateLimitStatusTriggerTests.java | 4 +- ...boundDirectMessageMessageHandlerTests.java | 4 +- 21 files changed, 345 insertions(+), 202 deletions(-) create mode 100644 spring-integration-twitter/src/main/java/org/springframework/integration/twitter/core/Twitter4jTemplate.java create mode 100644 spring-integration-twitter/src/main/java/org/springframework/integration/twitter/core/TwitterOperationException.java create mode 100644 spring-integration-twitter/src/main/java/org/springframework/integration/twitter/core/TwitterOperations.java delete mode 100644 spring-integration-twitter/src/main/java/org/springframework/integration/twitter/oauth/OAuthTwitterFactoryBean.java delete mode 100644 spring-integration-twitter/src/test/java/org/springframework/integration/twitter/config/TwitterConnectionParserTests-context.xml delete mode 100644 spring-integration-twitter/src/test/java/org/springframework/integration/twitter/config/TwitterConnectionParserTests.java create mode 100644 spring-integration-twitter/src/test/java/org/springframework/integration/twitter/core/Twitter4jTemplateTests.java diff --git a/spring-integration-twitter/src/main/java/org/springframework/integration/twitter/core/Twitter4jTemplate.java b/spring-integration-twitter/src/main/java/org/springframework/integration/twitter/core/Twitter4jTemplate.java new file mode 100644 index 0000000000..e2ab5c1481 --- /dev/null +++ b/spring-integration-twitter/src/main/java/org/springframework/integration/twitter/core/Twitter4jTemplate.java @@ -0,0 +1,151 @@ +/** + * + */ +package org.springframework.integration.twitter.core; + +import java.util.List; + +import org.springframework.util.Assert; + +import twitter4j.DirectMessage; +import twitter4j.Paging; +import twitter4j.RateLimitStatus; +import twitter4j.Status; +import twitter4j.StatusUpdate; +import twitter4j.Twitter; +import twitter4j.TwitterFactory; +import twitter4j.http.AccessToken; + +/** + * @author Oleg Zhurakousky + * @since 2.0 + * + */ +public class Twitter4jTemplate implements TwitterOperations{ + private final Twitter twitter; + + /** + * Used to construct this template to perform Twitter API calls that do not require authorization. + * (e.g., search) + */ + public Twitter4jTemplate(){ + this.twitter = new TwitterFactory().getInstance(); + } + /** + * Used to construct this template with OAuth authentication/authorization to perform Twitter API calls + * that do require authorization (e.g., send/receive DirectMessage) + * + * @param consumerKey + * @param consumerSecret + * @param accessToken + * @param accessTokenSecret + */ + public Twitter4jTemplate(String consumerKey, String consumerSecret, String accessToken, String accessTokenSecret){ + Assert.hasText(consumerKey, "'consumerKey' must be provided"); + Assert.hasText(consumerSecret, "'consumerSecret' must be provided"); + Assert.hasText(accessToken, "'accessToken' must be provided"); + Assert.hasText(accessTokenSecret, "'accessTokenSecret' must be provided"); + AccessToken at = new AccessToken(accessToken, accessTokenSecret); + this.twitter = new TwitterFactory().getOAuthAuthorizedInstance(consumerKey, consumerSecret, at); + } + + @Override + public String getProfileId() { + try { + return twitter.getScreenName(); + } + catch (Exception e) { + throw new TwitterOperationException("Failed to obtain profile id ", e); + } + } + @Override + public RateLimitStatus getRateLimitStatus() { + try { + return twitter.getRateLimitStatus(); + } + catch (Exception e) { + throw new TwitterOperationException("Failed to obtain Rate Limit status ", e); + } + } + @Override + public List getDirectMessages() { + try { + return twitter.getDirectMessages(); + } + catch (Exception e) { + throw new TwitterOperationException("Failed to receive Direct Messages ", e); + } + } + @Override + public List getDirectMessages(Paging paging) { + try { + return twitter.getDirectMessages(paging); + } + catch (Exception e) { + throw new TwitterOperationException("Failed to receive Direct Messages ", e); + } + } + @Override + public List getMentions() { + try { + return twitter.getMentions(); + } + catch (Exception e) { + throw new TwitterOperationException("Failed to receive Mention statuses ", e); + } + } + @Override + public List getMentions(Paging paging) { + try { + return twitter.getMentions(paging); + } + catch (Exception e) { + throw new TwitterOperationException("Failed to receive Mention statuses ", e); + } + } + @Override + public List getFriendsTimeline() { + try { + return twitter.getFriendsTimeline(); + } + catch (Exception e) { + throw new TwitterOperationException("Failed to receive Timeline statuses ", e); + } + } + @Override + public List getFriendsTimeline(Paging paging) { + try { + return twitter.getFriendsTimeline(paging); + } + catch (Exception e) { + throw new TwitterOperationException("Failed to receive Timeline statuses ", e); + } + } + @Override + public void sendDirectMessage(String userName, String text) { + try { + twitter.sendDirectMessage(userName, text); + } + catch (Exception e) { + throw new TwitterOperationException("Failed to send Direct Message ", e); + } + } + @Override + public void sendDirectMessage(int userId, String text) { + try { + twitter.sendDirectMessage(userId, text); + } + catch (Exception e) { + throw new TwitterOperationException("Failed to send Direct Message ", e); + } + } + @Override + public void updateStatus(StatusUpdate status) { + try { + twitter.updateStatus(status); + } + catch (Exception e) { + throw new TwitterOperationException("Failed to send Status update ", e); + } + } +} diff --git a/spring-integration-twitter/src/main/java/org/springframework/integration/twitter/core/TwitterOperationException.java b/spring-integration-twitter/src/main/java/org/springframework/integration/twitter/core/TwitterOperationException.java new file mode 100644 index 0000000000..8f52273598 --- /dev/null +++ b/spring-integration-twitter/src/main/java/org/springframework/integration/twitter/core/TwitterOperationException.java @@ -0,0 +1,55 @@ +/* + * Copyright 2002-2010 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.integration.twitter.core; + +/** + * @author Oleg Zhurakousky + * @since 2.0 + * + */ +@SuppressWarnings("serial") +public class TwitterOperationException extends RuntimeException { + + /** + * + */ + public TwitterOperationException() { + super(); + } + + /** + * @param description + */ + public TwitterOperationException(String description) { + super(description); + } + + /** + * @param throwable + */ + public TwitterOperationException(Throwable throwable) { + super(throwable); + } + + /** + * @param description + * @param throwable + */ + public TwitterOperationException(String description, Throwable throwable) { + super(description, throwable); + } + +} diff --git a/spring-integration-twitter/src/main/java/org/springframework/integration/twitter/core/TwitterOperations.java b/spring-integration-twitter/src/main/java/org/springframework/integration/twitter/core/TwitterOperations.java new file mode 100644 index 0000000000..867564ef13 --- /dev/null +++ b/spring-integration-twitter/src/main/java/org/springframework/integration/twitter/core/TwitterOperations.java @@ -0,0 +1,42 @@ +/** + * + */ +package org.springframework.integration.twitter.core; + +import java.util.List; + +import twitter4j.DirectMessage; +import twitter4j.Paging; +import twitter4j.RateLimitStatus; +import twitter4j.Status; +import twitter4j.StatusUpdate; + +/** + * @author Oleg Zhurakousky + * @since 2.0 + * + */ +public interface TwitterOperations { + + String getProfileId(); + + RateLimitStatus getRateLimitStatus(); + + List getDirectMessages(); + + List getDirectMessages(Paging paging); + + List getMentions(); + + List getMentions(Paging paging); + + List getFriendsTimeline(); + + List getFriendsTimeline(Paging paging); + + void sendDirectMessage(String userName, String text); + + void sendDirectMessage(int userId, String text); + + void updateStatus(StatusUpdate status); +} diff --git a/spring-integration-twitter/src/main/java/org/springframework/integration/twitter/inbound/AbstractTwitterMessageSource.java b/spring-integration-twitter/src/main/java/org/springframework/integration/twitter/inbound/AbstractTwitterMessageSource.java index 4f8904fa65..4ca42f08a6 100644 --- a/spring-integration-twitter/src/main/java/org/springframework/integration/twitter/inbound/AbstractTwitterMessageSource.java +++ b/spring-integration-twitter/src/main/java/org/springframework/integration/twitter/inbound/AbstractTwitterMessageSource.java @@ -33,6 +33,7 @@ import org.springframework.integration.history.TrackableComponent; import org.springframework.integration.store.MetadataStore; import org.springframework.integration.store.SimpleMetadataStore; import org.springframework.integration.support.MessageBuilder; +import org.springframework.integration.twitter.core.TwitterOperations; import org.springframework.util.Assert; import org.springframework.util.StringUtils; @@ -67,7 +68,7 @@ public abstract class AbstractTwitterMessageSource extends AbstractEndpoint protected volatile long markerId = -1; - protected final Twitter twitter; + protected final TwitterOperations twitter; private final Object markerGuard = new Object(); @@ -75,7 +76,7 @@ public abstract class AbstractTwitterMessageSource extends AbstractEndpoint private final HistoryWritingMessagePostProcessor historyWritingPostProcessor = new HistoryWritingMessagePostProcessor(); - public AbstractTwitterMessageSource(Twitter twitter){ + public AbstractTwitterMessageSource(TwitterOperations twitter){ this.twitter = twitter; } @@ -120,8 +121,8 @@ public abstract class AbstractTwitterMessageSource extends AbstractEndpoint else if (logger.isWarnEnabled()) { logger.warn(this.getClass().getSimpleName() + " has no name. MetadataStore key might not be unique."); } - String accessToken = twitter.getOAuthAccessToken().getToken(); - metadataKeyBuilder.append(accessToken); + String profileId = twitter.getProfileId(); + metadataKeyBuilder.append(profileId); this.metadataKey = metadataKeyBuilder.toString(); } diff --git a/spring-integration-twitter/src/main/java/org/springframework/integration/twitter/inbound/DirectMessageReceivingMessageSource.java b/spring-integration-twitter/src/main/java/org/springframework/integration/twitter/inbound/DirectMessageReceivingMessageSource.java index a245540ec6..fedcaa4b96 100644 --- a/spring-integration-twitter/src/main/java/org/springframework/integration/twitter/inbound/DirectMessageReceivingMessageSource.java +++ b/spring-integration-twitter/src/main/java/org/springframework/integration/twitter/inbound/DirectMessageReceivingMessageSource.java @@ -19,6 +19,7 @@ import java.util.Comparator; import java.util.List; import org.springframework.integration.MessagingException; +import org.springframework.integration.twitter.core.TwitterOperations; import org.springframework.util.CollectionUtils; import twitter4j.DirectMessage; @@ -34,7 +35,7 @@ import twitter4j.Twitter; */ public class DirectMessageReceivingMessageSource extends AbstractTwitterMessageSource { - public DirectMessageReceivingMessageSource(Twitter twitter){ + public DirectMessageReceivingMessageSource(TwitterOperations twitter){ super(twitter); } diff --git a/spring-integration-twitter/src/main/java/org/springframework/integration/twitter/inbound/MentionReceivingMessageSource.java b/spring-integration-twitter/src/main/java/org/springframework/integration/twitter/inbound/MentionReceivingMessageSource.java index 44ae57bf5c..56c721eff5 100644 --- a/spring-integration-twitter/src/main/java/org/springframework/integration/twitter/inbound/MentionReceivingMessageSource.java +++ b/spring-integration-twitter/src/main/java/org/springframework/integration/twitter/inbound/MentionReceivingMessageSource.java @@ -18,6 +18,7 @@ package org.springframework.integration.twitter.inbound; import java.util.List; import org.springframework.integration.MessagingException; +import org.springframework.integration.twitter.core.TwitterOperations; import twitter4j.Paging; import twitter4j.Status; @@ -31,7 +32,7 @@ import twitter4j.Twitter; */ public class MentionReceivingMessageSource extends AbstractTwitterMessageSource { - public MentionReceivingMessageSource(Twitter twitter){ + public MentionReceivingMessageSource(TwitterOperations twitter){ super(twitter); } @Override diff --git a/spring-integration-twitter/src/main/java/org/springframework/integration/twitter/inbound/RateLimitStatusTrigger.java b/spring-integration-twitter/src/main/java/org/springframework/integration/twitter/inbound/RateLimitStatusTrigger.java index 5abbebdcbd..33bf3d5032 100644 --- a/spring-integration-twitter/src/main/java/org/springframework/integration/twitter/inbound/RateLimitStatusTrigger.java +++ b/spring-integration-twitter/src/main/java/org/springframework/integration/twitter/inbound/RateLimitStatusTrigger.java @@ -19,14 +19,12 @@ import java.util.Date; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; -import org.springframework.scheduling.SchedulingException; +import org.springframework.integration.twitter.core.TwitterOperations; import org.springframework.scheduling.Trigger; import org.springframework.scheduling.TriggerContext; import org.springframework.util.Assert; import twitter4j.RateLimitStatus; -import twitter4j.Twitter; -import twitter4j.TwitterException; /** * @author Oleg Zhurakousky @@ -34,9 +32,9 @@ import twitter4j.TwitterException; */ class RateLimitStatusTrigger implements Trigger { protected final Log logger = LogFactory.getLog(getClass()); - private Twitter twitter; + private TwitterOperations twitter; - public RateLimitStatusTrigger(Twitter twitter){ + public RateLimitStatusTrigger(TwitterOperations twitter){ Assert.notNull(twitter, "'twitter' must not be null"); this.twitter = twitter; } @@ -48,7 +46,7 @@ class RateLimitStatusTrigger implements Trigger { if (triggerContext.lastCompletionTime() == null){ return new Date(System.currentTimeMillis()); } - try { +// try { RateLimitStatus rateLimitStatus = twitter.getRateLimitStatus(); int secondsUntilReset = rateLimitStatus.getSecondsUntilReset(); int remainingHits = rateLimitStatus.getRemainingHits(); @@ -69,8 +67,8 @@ class RateLimitStatusTrigger implements Trigger { " remaining pull this rate period. The period ends in " + secondsUntilReset); return new Date(System.currentTimeMillis() + msUntilWeCanPullAgain); - } catch (TwitterException e) { - throw new SchedulingException("Failed to schedule the next Twitter update", e); - } +// } catch (TwitterException e) { +// throw new SchedulingException("Failed to schedule the next Twitter update", e); +// } } } diff --git a/spring-integration-twitter/src/main/java/org/springframework/integration/twitter/inbound/TimelineUpdateReceivingMessageSource.java b/spring-integration-twitter/src/main/java/org/springframework/integration/twitter/inbound/TimelineUpdateReceivingMessageSource.java index ef63cae268..e9e865ab21 100644 --- a/spring-integration-twitter/src/main/java/org/springframework/integration/twitter/inbound/TimelineUpdateReceivingMessageSource.java +++ b/spring-integration-twitter/src/main/java/org/springframework/integration/twitter/inbound/TimelineUpdateReceivingMessageSource.java @@ -16,6 +16,7 @@ package org.springframework.integration.twitter.inbound; import org.springframework.integration.MessagingException; +import org.springframework.integration.twitter.core.TwitterOperations; import twitter4j.Paging; import twitter4j.Status; @@ -32,7 +33,7 @@ import twitter4j.Twitter; */ public class TimelineUpdateReceivingMessageSource extends AbstractTwitterMessageSource { - public TimelineUpdateReceivingMessageSource(Twitter twitter){ + public TimelineUpdateReceivingMessageSource(TwitterOperations twitter){ super(twitter); } @Override diff --git a/spring-integration-twitter/src/main/java/org/springframework/integration/twitter/oauth/OAuthTwitterFactoryBean.java b/spring-integration-twitter/src/main/java/org/springframework/integration/twitter/oauth/OAuthTwitterFactoryBean.java deleted file mode 100644 index 4cf1c5e748..0000000000 --- a/spring-integration-twitter/src/main/java/org/springframework/integration/twitter/oauth/OAuthTwitterFactoryBean.java +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Copyright 2002-2010 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.integration.twitter.oauth; - -import org.springframework.beans.factory.FactoryBean; -import org.springframework.beans.factory.InitializingBean; -import org.springframework.util.Assert; - -import twitter4j.Twitter; -import twitter4j.TwitterFactory; -import twitter4j.http.AccessToken; - -/** - * Will create an OAuth-Authorized instance of Twitter object. - * - * @author Oleg Zhurakousky - * @since 2.0 - */ -public class OAuthTwitterFactoryBean implements FactoryBean, InitializingBean { - private final String consumerKey; - private final String consumerSecret; - private final AccessToken accessToken; - - private volatile Twitter twitter; - - public OAuthTwitterFactoryBean(String consumerKey, String consumerSecret, AccessToken accessToken){ - Assert.hasText(consumerKey, "'consumerKey' must be provided"); - Assert.hasText(consumerSecret, "'consumerSecret' must be provided"); - Assert.notNull(accessToken, "'accessToken' must be provided"); - this.consumerKey = consumerKey; - this.consumerSecret = consumerSecret; - this.accessToken = accessToken; - } - @Override - public Twitter getObject() throws Exception { - Assert.notNull(this.twitter, "OAuthTwitterFactoryBean must be initialized. Invoke afterPropertiesSet() method"); - return twitter; - } - - @Override - public Class getObjectType() { - return Twitter.class; - } - - @Override - public boolean isSingleton() { - return true; - } - - @Override - public void afterPropertiesSet() throws Exception { - this.twitter = new TwitterFactory().getOAuthAuthorizedInstance(consumerKey, consumerSecret, accessToken); - } - -} diff --git a/spring-integration-twitter/src/main/java/org/springframework/integration/twitter/outbound/AbstractOutboundTwitterEndpointSupport.java b/spring-integration-twitter/src/main/java/org/springframework/integration/twitter/outbound/AbstractOutboundTwitterEndpointSupport.java index 2193fb0612..cbb5ae17b1 100644 --- a/spring-integration-twitter/src/main/java/org/springframework/integration/twitter/outbound/AbstractOutboundTwitterEndpointSupport.java +++ b/spring-integration-twitter/src/main/java/org/springframework/integration/twitter/outbound/AbstractOutboundTwitterEndpointSupport.java @@ -16,6 +16,7 @@ package org.springframework.integration.twitter.outbound; import org.springframework.integration.handler.AbstractMessageHandler; +import org.springframework.integration.twitter.core.TwitterOperations; import org.springframework.util.Assert; import twitter4j.Twitter; @@ -28,23 +29,11 @@ import twitter4j.Twitter; * @since 2.0 */ public abstract class AbstractOutboundTwitterEndpointSupport extends AbstractMessageHandler { - //protected volatile OAuthConfiguration configuration; - protected final Twitter twitter; + protected final TwitterOperations twitter; protected final OutboundStatusUpdateMessageMapper supportStatusUpdate = new OutboundStatusUpdateMessageMapper(); - public AbstractOutboundTwitterEndpointSupport(Twitter twitter){ + public AbstractOutboundTwitterEndpointSupport(TwitterOperations twitter){ Assert.notNull(twitter, "'twitter' must not be null"); this.twitter = twitter; } -// public void setConfiguration(OAuthConfiguration configuration) { -// this.configuration = configuration; -// } - -// @Override -// protected void onInit() throws Exception { -// Assert.notNull(this.configuration, "'configuration' can't be null"); -// this.twitter = this.configuration.getTwitter(); -// Assert.notNull(this.twitter, "'twitter' can't be null"); -// } - } diff --git a/spring-integration-twitter/src/main/java/org/springframework/integration/twitter/outbound/DirectMessageSendingMessageHandler.java b/spring-integration-twitter/src/main/java/org/springframework/integration/twitter/outbound/DirectMessageSendingMessageHandler.java index 3832523ff7..17364965ec 100644 --- a/spring-integration-twitter/src/main/java/org/springframework/integration/twitter/outbound/DirectMessageSendingMessageHandler.java +++ b/spring-integration-twitter/src/main/java/org/springframework/integration/twitter/outbound/DirectMessageSendingMessageHandler.java @@ -17,13 +17,10 @@ package org.springframework.integration.twitter.outbound; import org.springframework.integration.Message; -import org.springframework.integration.MessageHandlingException; import org.springframework.integration.twitter.core.TwitterHeaders; +import org.springframework.integration.twitter.core.TwitterOperations; import org.springframework.util.Assert; -import twitter4j.Twitter; -import twitter4j.TwitterException; - /** * Simple adapter to support sending outbound direct messages ("DM"s) using twitter * @@ -33,7 +30,7 @@ import twitter4j.TwitterException; */ public class DirectMessageSendingMessageHandler extends AbstractOutboundTwitterEndpointSupport { - public DirectMessageSendingMessageHandler(Twitter twitter){ + public DirectMessageSendingMessageHandler(TwitterOperations twitter){ super(twitter); } @@ -42,7 +39,7 @@ public class DirectMessageSendingMessageHandler extends AbstractOutboundTwitterE if (this.twitter == null) { this.afterPropertiesSet(); } - try { +// try { Assert.isInstanceOf(String.class, message.getPayload(), "Only payload of type String is supported. If your payload " + "is not of type String consider adding a transformer to the message flow in front of this adapter."); Assert.isTrue(message.getHeaders().containsKey(TwitterHeaders.DM_TARGET_USER_ID), @@ -58,10 +55,10 @@ public class DirectMessageSendingMessageHandler extends AbstractOutboundTwitterE else if (toUser instanceof String) { this.twitter.sendDirectMessage((String) toUser, payload); } - } - catch (TwitterException e) { - throw new MessageHandlingException(message, e); - } +// } +// catch (TwitterException e) { +// throw new MessageHandlingException(message, e); +// } } } diff --git a/spring-integration-twitter/src/main/java/org/springframework/integration/twitter/outbound/TimelineUpdateSendingMessageHandler.java b/spring-integration-twitter/src/main/java/org/springframework/integration/twitter/outbound/TimelineUpdateSendingMessageHandler.java index a8813f035c..9a1f25c3b3 100644 --- a/spring-integration-twitter/src/main/java/org/springframework/integration/twitter/outbound/TimelineUpdateSendingMessageHandler.java +++ b/spring-integration-twitter/src/main/java/org/springframework/integration/twitter/outbound/TimelineUpdateSendingMessageHandler.java @@ -16,6 +16,7 @@ package org.springframework.integration.twitter.outbound; import org.springframework.integration.Message; +import org.springframework.integration.twitter.core.TwitterOperations; import org.springframework.util.Assert; import twitter4j.StatusUpdate; @@ -30,7 +31,7 @@ import twitter4j.Twitter; */ public class TimelineUpdateSendingMessageHandler extends AbstractOutboundTwitterEndpointSupport { - public TimelineUpdateSendingMessageHandler(Twitter twitter){ + public TimelineUpdateSendingMessageHandler(TwitterOperations twitter){ super(twitter); } diff --git a/spring-integration-twitter/src/test/java/org/springframework/integration/twitter/config/TestReceivingMessageSourceParser-context.xml b/spring-integration-twitter/src/test/java/org/springframework/integration/twitter/config/TestReceivingMessageSourceParser-context.xml index 57bdc3ade0..4392700bc9 100644 --- a/spring-integration-twitter/src/test/java/org/springframework/integration/twitter/config/TestReceivingMessageSourceParser-context.xml +++ b/spring-integration-twitter/src/test/java/org/springframework/integration/twitter/config/TestReceivingMessageSourceParser-context.xml @@ -17,11 +17,7 @@ http://www.springframework.org/schema/lang http://www.springframework.org/schema/lang/spring-lang-3.0.xsd http://www.springframework.org/schema/integration/twitter http://www.springframework.org/schema/integration/twitter/spring-integration-twitter.xsd"> - + diff --git a/spring-integration-twitter/src/test/java/org/springframework/integration/twitter/config/TestReceivingMessageSourceParserTests.java b/spring-integration-twitter/src/test/java/org/springframework/integration/twitter/config/TestReceivingMessageSourceParserTests.java index 69d34522df..687c11d210 100644 --- a/spring-integration-twitter/src/test/java/org/springframework/integration/twitter/config/TestReceivingMessageSourceParserTests.java +++ b/spring-integration-twitter/src/test/java/org/springframework/integration/twitter/config/TestReceivingMessageSourceParserTests.java @@ -16,12 +16,17 @@ package org.springframework.integration.twitter.config; import static junit.framework.Assert.assertFalse; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; import org.junit.Test; +import org.springframework.beans.factory.FactoryBean; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import org.springframework.integration.endpoint.SourcePollingChannelAdapter; import org.springframework.integration.test.util.TestUtils; +import org.springframework.integration.twitter.core.Twitter4jTemplate; +import org.springframework.integration.twitter.core.TwitterOperations; import org.springframework.integration.twitter.inbound.AbstractTwitterMessageSource; /** @@ -45,4 +50,25 @@ public class TestReceivingMessageSourceParserTests { ms = (AbstractTwitterMessageSource) TestUtils.getPropertyValue(spca, "source"); assertFalse(ms.isAutoStartup()); } + + public static class TwitterTemplateFactoryBean implements FactoryBean{ + + @Override + public TwitterOperations getObject() throws Exception { + TwitterOperations oper = mock(TwitterOperations.class); + when(oper.getProfileId()).thenReturn("kermit"); + return oper; + } + + @Override + public Class getObjectType() { + return TwitterOperations.class; + } + + @Override + public boolean isSingleton() { + return true; + } + + } } diff --git a/spring-integration-twitter/src/test/java/org/springframework/integration/twitter/config/TestSendingMessageHandlerParser-context.xml b/spring-integration-twitter/src/test/java/org/springframework/integration/twitter/config/TestSendingMessageHandlerParser-context.xml index 044982aea1..54ba5ac776 100644 --- a/spring-integration-twitter/src/test/java/org/springframework/integration/twitter/config/TestSendingMessageHandlerParser-context.xml +++ b/spring-integration-twitter/src/test/java/org/springframework/integration/twitter/config/TestSendingMessageHandlerParser-context.xml @@ -18,11 +18,7 @@ http://www.springframework.org/schema/integration/twitter http://www.springframework.org/schema/integration/twitter/spring-integration-twitter-2.0.xsd"> - + diff --git a/spring-integration-twitter/src/test/java/org/springframework/integration/twitter/config/TwitterConnectionParserTests-context.xml b/spring-integration-twitter/src/test/java/org/springframework/integration/twitter/config/TwitterConnectionParserTests-context.xml deleted file mode 100644 index 20ef2561b1..0000000000 --- a/spring-integration-twitter/src/test/java/org/springframework/integration/twitter/config/TwitterConnectionParserTests-context.xml +++ /dev/null @@ -1,22 +0,0 @@ - - - - - - - - - diff --git a/spring-integration-twitter/src/test/java/org/springframework/integration/twitter/config/TwitterConnectionParserTests.java b/spring-integration-twitter/src/test/java/org/springframework/integration/twitter/config/TwitterConnectionParserTests.java deleted file mode 100644 index 0cbf5b1900..0000000000 --- a/spring-integration-twitter/src/test/java/org/springframework/integration/twitter/config/TwitterConnectionParserTests.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright 2002-2010 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.integration.twitter.config; - -import static junit.framework.Assert.assertEquals; -import static junit.framework.Assert.assertNotNull; -import static junit.framework.Assert.assertTrue; - -import org.junit.Test; -import org.springframework.context.ApplicationContext; -import org.springframework.context.support.ClassPathXmlApplicationContext; -import org.springframework.integration.test.util.TestUtils; -import org.springframework.integration.twitter.oauth.OAuthTwitterFactoryBean; - -import twitter4j.Twitter; -import twitter4j.http.AccessToken; - -/** - * @author Oleg Zhurakousky - * @since 2.0 - * - */ -public class TwitterConnectionParserTests { - - @Test - public void testOAuthTwitterFactoryBean(){ - ApplicationContext ac = new ClassPathXmlApplicationContext("TwitterConnectionParserTests-context.xml", this.getClass()); - OAuthTwitterFactoryBean twitterFb = ac.getBean("&twitter", OAuthTwitterFactoryBean.class); - assertEquals("consumerKey", TestUtils.getPropertyValue(twitterFb, "consumerKey")); - assertEquals("consumerSecret", TestUtils.getPropertyValue(twitterFb, "consumerSecret")); - AccessToken accessToken = (AccessToken) TestUtils.getPropertyValue(twitterFb, "accessToken"); - assertEquals("accessToken", accessToken.getToken()); - assertEquals("accessTokenSecret", accessToken.getTokenSecret()); - Twitter twitter = ac.getBean("twitter", Twitter.class); - assertTrue(twitter.isOAuthEnabled()); - } -} diff --git a/spring-integration-twitter/src/test/java/org/springframework/integration/twitter/core/Twitter4jTemplateTests.java b/spring-integration-twitter/src/test/java/org/springframework/integration/twitter/core/Twitter4jTemplateTests.java new file mode 100644 index 0000000000..961d552dc2 --- /dev/null +++ b/spring-integration-twitter/src/test/java/org/springframework/integration/twitter/core/Twitter4jTemplateTests.java @@ -0,0 +1,30 @@ +/* + * Copyright 2002-2010 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.integration.twitter.core; + +import org.junit.Test; + +/** + * @author Oleg Zhurakousky + * + */ +public class Twitter4jTemplateTests { + + @Test + public void testProfileId(){ + + } +} diff --git a/spring-integration-twitter/src/test/java/org/springframework/integration/twitter/inbound/DirectMessageReceivingMessageSourceTests.java b/spring-integration-twitter/src/test/java/org/springframework/integration/twitter/inbound/DirectMessageReceivingMessageSourceTests.java index 12c0acd924..c6a2043cc0 100644 --- a/spring-integration-twitter/src/test/java/org/springframework/integration/twitter/inbound/DirectMessageReceivingMessageSourceTests.java +++ b/spring-integration-twitter/src/test/java/org/springframework/integration/twitter/inbound/DirectMessageReceivingMessageSourceTests.java @@ -23,13 +23,13 @@ import static org.mockito.Mockito.when; import java.util.ArrayList; import java.util.Date; -import java.util.List; import java.util.Queue; import org.junit.Before; import org.junit.Test; import org.mockito.Mockito; import org.springframework.integration.test.util.TestUtils; +import org.springframework.integration.twitter.core.TwitterOperations; import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler; import org.springframework.util.CollectionUtils; @@ -37,8 +37,6 @@ import twitter4j.DirectMessage; import twitter4j.Paging; import twitter4j.RateLimitStatus; import twitter4j.ResponseList; -import twitter4j.Twitter; -import twitter4j.http.AccessToken; /** * @author Oleg Zhurakousky @@ -49,12 +47,12 @@ public class DirectMessageReceivingMessageSourceTests { private DirectMessage secondMessage; - private Twitter twitter = mock(Twitter.class); + private TwitterOperations twitter; @Before public void prepare() throws Exception{ - twitter = mock(Twitter.class); + twitter = mock(TwitterOperations.class); firstMessage = mock(DirectMessage.class); when(firstMessage.getCreatedAt()).thenReturn(new Date(5555555555L)); when(firstMessage.getId()).thenReturn(200); @@ -63,7 +61,7 @@ public class DirectMessageReceivingMessageSourceTests { when(secondMessage.getId()).thenReturn(2000); - when(twitter.getOAuthAccessToken()).thenReturn(new AccessToken("token123", "tokenSecret123")); + when(twitter.getProfileId()).thenReturn("kermit"); } @@ -76,7 +74,7 @@ public class DirectMessageReceivingMessageSourceTests { source.setBeanName("twitterEndpoint"); source.afterPropertiesSet(); source.start(); - assertEquals("twitter:inbound-dm-channel-adapter.twitterEndpoint.token123", TestUtils.getPropertyValue(source, "metadataKey")); + assertEquals("twitter:inbound-dm-channel-adapter.twitterEndpoint.kermit", TestUtils.getPropertyValue(source, "metadataKey")); assertTrue(source.isRunning()); } diff --git a/spring-integration-twitter/src/test/java/org/springframework/integration/twitter/inbound/RateLimitStatusTriggerTests.java b/spring-integration-twitter/src/test/java/org/springframework/integration/twitter/inbound/RateLimitStatusTriggerTests.java index 6b9506c9e9..4eeeace434 100644 --- a/spring-integration-twitter/src/test/java/org/springframework/integration/twitter/inbound/RateLimitStatusTriggerTests.java +++ b/spring-integration-twitter/src/test/java/org/springframework/integration/twitter/inbound/RateLimitStatusTriggerTests.java @@ -22,10 +22,10 @@ import static org.mockito.Mockito.when; import java.util.Date; import org.junit.Test; +import org.springframework.integration.twitter.core.TwitterOperations; import org.springframework.scheduling.TriggerContext; import twitter4j.RateLimitStatus; -import twitter4j.Twitter; /** * @author Oleg Zhurakousky @@ -35,7 +35,7 @@ public class RateLimitStatusTriggerTests { @Test public void testTriggerImediateAndSubsequentExecutionTime() throws Exception{ - Twitter twitter = mock(Twitter.class); + TwitterOperations twitter = mock(TwitterOperations.class); RateLimitStatusTrigger trigger = new RateLimitStatusTrigger(twitter); TriggerContext context = mock(TriggerContext.class); Date currentDate = new Date(System.currentTimeMillis()); diff --git a/spring-integration-twitter/src/test/java/org/springframework/integration/twitter/outbound/OutboundDirectMessageMessageHandlerTests.java b/spring-integration-twitter/src/test/java/org/springframework/integration/twitter/outbound/OutboundDirectMessageMessageHandlerTests.java index 34353bb45d..459a96e6f3 100644 --- a/spring-integration-twitter/src/test/java/org/springframework/integration/twitter/outbound/OutboundDirectMessageMessageHandlerTests.java +++ b/spring-integration-twitter/src/test/java/org/springframework/integration/twitter/outbound/OutboundDirectMessageMessageHandlerTests.java @@ -23,16 +23,16 @@ import static org.mockito.Mockito.verify; import org.junit.Test; import org.springframework.integration.support.MessageBuilder; import org.springframework.integration.twitter.core.TwitterHeaders; +import org.springframework.integration.twitter.core.TwitterOperations; import twitter4j.GeoLocation; -import twitter4j.Twitter; /** * @author Oleg Zhurakousky */ public class OutboundDirectMessageMessageHandlerTests { - private Twitter twitter = mock(Twitter.class); + private TwitterOperations twitter = mock(TwitterOperations.class); @Test public void validateSendDirectMessage() throws Exception{ From 79b7342ad90bdaa5f725a1772caf7fb410fddbfc Mon Sep 17 00:00:00 2001 From: Oleg Zhurakousky Date: Mon, 8 Nov 2010 09:08:23 -0500 Subject: [PATCH 79/82] INT-1553 removed twitter-connection from the namespace --- .../twitter/config/TwitterNamespaceHandler.java | 3 --- .../config/spring-integration-twitter-2.0.xsd | 15 --------------- 2 files changed, 18 deletions(-) diff --git a/spring-integration-twitter/src/main/java/org/springframework/integration/twitter/config/TwitterNamespaceHandler.java b/spring-integration-twitter/src/main/java/org/springframework/integration/twitter/config/TwitterNamespaceHandler.java index 6fc7c21f5e..0dc22df983 100644 --- a/spring-integration-twitter/src/main/java/org/springframework/integration/twitter/config/TwitterNamespaceHandler.java +++ b/spring-integration-twitter/src/main/java/org/springframework/integration/twitter/config/TwitterNamespaceHandler.java @@ -31,9 +31,6 @@ public class TwitterNamespaceHandler extends AbstractIntegrationNamespaceHandler public void init() { - // twitter connection - registerBeanDefinitionParser("twitter-connection", new ConnectionParser()); - // inbound registerBeanDefinitionParser("inbound-update-channel-adapter", new TwitterReceivingMessageSourceParser()); registerBeanDefinitionParser("inbound-dm-channel-adapter", new TwitterReceivingMessageSourceParser()); diff --git a/spring-integration-twitter/src/main/resources/org/springframework/integration/twitter/config/spring-integration-twitter-2.0.xsd b/spring-integration-twitter/src/main/resources/org/springframework/integration/twitter/config/spring-integration-twitter-2.0.xsd index 8c124c2bcf..703273deb8 100644 --- a/spring-integration-twitter/src/main/resources/org/springframework/integration/twitter/config/spring-integration-twitter-2.0.xsd +++ b/spring-integration-twitter/src/main/resources/org/springframework/integration/twitter/config/spring-integration-twitter-2.0.xsd @@ -13,21 +13,6 @@ - - - - Sets up an instance of OAuthConfiguration which all adapters need to function properly - - - - - - - - - - - From 4aaac0f04bb7206a9a71b5ed8a09360339db6699 Mon Sep 17 00:00:00 2001 From: Chris Beams Date: Mon, 8 Nov 2010 06:54:47 -0800 Subject: [PATCH 80/82] Only attempt to access sshPrivateKey property if present --- docs/build.gradle | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/docs/build.gradle b/docs/build.gradle index c2152ec1b2..eee1512cb1 100644 --- a/docs/build.gradle +++ b/docs/build.gradle @@ -206,7 +206,9 @@ uploadArchives { name = 'sshHost: ' + sshHost // used for debugging host = sshHost user = sshUsername - keyFile = sshPrivateKey as File + if (project.hasProperty('sshPrivateKey')) { + keyFile = sshPrivateKey ? sshPrivateKey as File : null + } addArtifactPattern "${remoteDocsDir}/${archive.archiveName}" } } From c5b072b2a83e4847b1cbea158f7f95449ae42e81 Mon Sep 17 00:00:00 2001 From: Oleg Zhurakousky Date: Mon, 8 Nov 2010 12:02:51 -0500 Subject: [PATCH 81/82] INT-1553 removed ConnectionParser, added tests for Twitter4JTemplate --- .../twitter/config/ConnectionParser.java | 51 ----------- .../DirectMessageReceivingMessageSource.java | 1 - .../twitter/core/Twitter4jTemplateTests.java | 91 ++++++++++++++++++- 3 files changed, 89 insertions(+), 54 deletions(-) delete mode 100644 spring-integration-twitter/src/main/java/org/springframework/integration/twitter/config/ConnectionParser.java diff --git a/spring-integration-twitter/src/main/java/org/springframework/integration/twitter/config/ConnectionParser.java b/spring-integration-twitter/src/main/java/org/springframework/integration/twitter/config/ConnectionParser.java deleted file mode 100644 index 5bc2a38d4b..0000000000 --- a/spring-integration-twitter/src/main/java/org/springframework/integration/twitter/config/ConnectionParser.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright 2002-2010 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.integration.twitter.config; - -import static org.springframework.integration.twitter.config.TwitterNamespaceHandler.BASE_PACKAGE; - -import org.springframework.beans.factory.support.BeanDefinitionBuilder; -import org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser; -import org.springframework.beans.factory.xml.ParserContext; -import org.w3c.dom.Element; - -/** - * Parser for the 'twitter-connection' element. - * - * @author Josh Long - * @author Mark Fisher - * @since 2.0 - */ -public class ConnectionParser extends AbstractSingleBeanDefinitionParser { - - @Override - protected String getBeanClassName(Element element) { - return BASE_PACKAGE + ".oauth.OAuthTwitterFactoryBean"; - } - - @Override - protected void doParse(Element element, ParserContext parserContext, BeanDefinitionBuilder builder) { - - BeanDefinitionBuilder accessTokenBuilder = BeanDefinitionBuilder.genericBeanDefinition("twitter4j.http.AccessToken"); - accessTokenBuilder.addConstructorArgValue(element.getAttribute("access-token")); - accessTokenBuilder.addConstructorArgValue(element.getAttribute("access-token-secret")); - builder.addConstructorArgValue(element.getAttribute("consumer-key")); - builder.addConstructorArgValue(element.getAttribute("consumer-secret")); - builder.addConstructorArgValue(accessTokenBuilder.getBeanDefinition()); - } - -} diff --git a/spring-integration-twitter/src/main/java/org/springframework/integration/twitter/inbound/DirectMessageReceivingMessageSource.java b/spring-integration-twitter/src/main/java/org/springframework/integration/twitter/inbound/DirectMessageReceivingMessageSource.java index fedcaa4b96..6f80adf37d 100644 --- a/spring-integration-twitter/src/main/java/org/springframework/integration/twitter/inbound/DirectMessageReceivingMessageSource.java +++ b/spring-integration-twitter/src/main/java/org/springframework/integration/twitter/inbound/DirectMessageReceivingMessageSource.java @@ -24,7 +24,6 @@ import org.springframework.util.CollectionUtils; import twitter4j.DirectMessage; import twitter4j.Paging; -import twitter4j.Twitter; /** * This class handles support for receiving DMs (direct messages) using Twitter. diff --git a/spring-integration-twitter/src/test/java/org/springframework/integration/twitter/core/Twitter4jTemplateTests.java b/spring-integration-twitter/src/test/java/org/springframework/integration/twitter/core/Twitter4jTemplateTests.java index 961d552dc2..d35269d510 100644 --- a/spring-integration-twitter/src/test/java/org/springframework/integration/twitter/core/Twitter4jTemplateTests.java +++ b/spring-integration-twitter/src/test/java/org/springframework/integration/twitter/core/Twitter4jTemplateTests.java @@ -15,16 +15,103 @@ */ package org.springframework.integration.twitter.core; +import static junit.framework.Assert.assertEquals; +import static junit.framework.Assert.assertTrue; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import java.lang.reflect.Field; + +import org.junit.Before; import org.junit.Test; +import org.mockito.Mockito; +import org.springframework.integration.test.util.TestUtils; + +import twitter4j.Paging; +import twitter4j.StatusUpdate; +import twitter4j.Twitter; +import twitter4j.http.AccessToken; +import twitter4j.http.Authorization; +import twitter4j.http.OAuthAuthorization; /** + * Validates that all calls are delegated properly top Twitter + * * @author Oleg Zhurakousky * */ public class Twitter4jTemplateTests { + Twitter4jTemplate template; + Twitter twitter; + + @Before + public void prepare() throws Exception{ + template = new Twitter4jTemplate(); + Field twitterField = Twitter4jTemplate.class.getDeclaredField("twitter"); + twitterField.setAccessible(true); + twitter = mock(Twitter.class); + twitterField.set(template, twitter); + } + @Test + public void testOauthConstructor() throws Exception{ + template = new Twitter4jTemplate("a", "b", "c", "d"); + Twitter twitter = (Twitter) TestUtils.getPropertyValue(template, "twitter"); + Authorization auth = twitter.getAuthorization(); + assertTrue(twitter.getAuthorization() instanceof OAuthAuthorization); + AccessToken accessToken = ((OAuthAuthorization)auth).getOAuthAccessToken(); + assertEquals("c", accessToken.getToken()); + assertEquals("d", accessToken.getTokenSecret()); + } @Test - public void testProfileId(){ - + public void testProfileId() throws Exception{ + when(twitter.getScreenName()).thenReturn("kermit"); + assertEquals("kermit", template.getProfileId()); + } + @Test + public void testRateLimitStatus() throws Exception{ + template.getRateLimitStatus(); + verify(twitter, times(1)).getRateLimitStatus(); + } + + @Test + public void testGetDirectMessages() throws Exception{ + template.getDirectMessages(); + template.getDirectMessages(new Paging()); + verify(twitter, times(1)).getDirectMessages(); + verify(twitter, times(1)).getDirectMessages(Mockito.any(Paging.class)); + } + + @Test + public void testGetMentions() throws Exception{ + template.getMentions(); + template.getMentions(new Paging()); + verify(twitter, times(1)).getMentions(); + verify(twitter, times(1)).getMentions(Mockito.any(Paging.class)); + } + + @Test + public void testGetFriendsTimeline() throws Exception{ + template.getFriendsTimeline(); + template.getFriendsTimeline(new Paging()); + verify(twitter, times(1)).getFriendsTimeline(); + verify(twitter, times(1)).getFriendsTimeline(Mockito.any(Paging.class)); + } + + @Test + public void testSendDirectMessage() throws Exception{ + template.sendDirectMessage("kermit", "hello"); + template.sendDirectMessage(1, "hello"); + verify(twitter, times(1)).sendDirectMessage("kermit", "hello"); + verify(twitter, times(1)).sendDirectMessage(1, "hello"); + } + + @Test + public void testUpdateStatus() throws Exception{ + StatusUpdate statusUpdate = new StatusUpdate("writing twitter test"); + template.updateStatus(statusUpdate); + verify(twitter, times(1)).updateStatus(statusUpdate); } } From 8d280e4a9940b54553a8e894d6fb12e0abb81750 Mon Sep 17 00:00:00 2001 From: Oleg Zhurakousky Date: Mon, 8 Nov 2010 12:31:39 -0500 Subject: [PATCH 82/82] INT-1553 polishing, added more tests for status update, code coverage is at 76% --- .../twitter/core/Twitter4jTemplate.java | 1 - ...bstractOutboundTwitterEndpointSupport.java | 2 - .../DirectMessageSendingMessageHandler.java | 35 ++++----- .../OutboundStatusUpdateMessageMapper.java | 1 - .../TimelineUpdateSendingMessageHandler.java | 3 +- .../twitter/core/Twitter4jTemplateTests.java | 6 +- ...ectMessageReceivingMessageSourceTests.java | 2 + ...elineUpdateSendingMessageHandlerTests.java | 78 +++++++++++++++++++ 8 files changed, 99 insertions(+), 29 deletions(-) create mode 100644 spring-integration-twitter/src/test/java/org/springframework/integration/twitter/outbound/TimelineUpdateSendingMessageHandlerTests.java diff --git a/spring-integration-twitter/src/main/java/org/springframework/integration/twitter/core/Twitter4jTemplate.java b/spring-integration-twitter/src/main/java/org/springframework/integration/twitter/core/Twitter4jTemplate.java index e2ab5c1481..3c84baec19 100644 --- a/spring-integration-twitter/src/main/java/org/springframework/integration/twitter/core/Twitter4jTemplate.java +++ b/spring-integration-twitter/src/main/java/org/springframework/integration/twitter/core/Twitter4jTemplate.java @@ -23,7 +23,6 @@ import twitter4j.http.AccessToken; */ public class Twitter4jTemplate implements TwitterOperations{ private final Twitter twitter; - /** * Used to construct this template to perform Twitter API calls that do not require authorization. * (e.g., search) diff --git a/spring-integration-twitter/src/main/java/org/springframework/integration/twitter/outbound/AbstractOutboundTwitterEndpointSupport.java b/spring-integration-twitter/src/main/java/org/springframework/integration/twitter/outbound/AbstractOutboundTwitterEndpointSupport.java index cbb5ae17b1..7c8ad8241e 100644 --- a/spring-integration-twitter/src/main/java/org/springframework/integration/twitter/outbound/AbstractOutboundTwitterEndpointSupport.java +++ b/spring-integration-twitter/src/main/java/org/springframework/integration/twitter/outbound/AbstractOutboundTwitterEndpointSupport.java @@ -19,8 +19,6 @@ import org.springframework.integration.handler.AbstractMessageHandler; import org.springframework.integration.twitter.core.TwitterOperations; import org.springframework.util.Assert; -import twitter4j.Twitter; - /** * Base adapter class for all outbound Twitter adapters diff --git a/spring-integration-twitter/src/main/java/org/springframework/integration/twitter/outbound/DirectMessageSendingMessageHandler.java b/spring-integration-twitter/src/main/java/org/springframework/integration/twitter/outbound/DirectMessageSendingMessageHandler.java index 17364965ec..a0140cf825 100644 --- a/spring-integration-twitter/src/main/java/org/springframework/integration/twitter/outbound/DirectMessageSendingMessageHandler.java +++ b/spring-integration-twitter/src/main/java/org/springframework/integration/twitter/outbound/DirectMessageSendingMessageHandler.java @@ -39,26 +39,21 @@ public class DirectMessageSendingMessageHandler extends AbstractOutboundTwitterE if (this.twitter == null) { this.afterPropertiesSet(); } -// try { - Assert.isInstanceOf(String.class, message.getPayload(), "Only payload of type String is supported. If your payload " + - "is not of type String consider adding a transformer to the message flow in front of this adapter."); - Assert.isTrue(message.getHeaders().containsKey(TwitterHeaders.DM_TARGET_USER_ID), - "the '" + TwitterHeaders.DM_TARGET_USER_ID + "' header is required"); - Object toUser = message.getHeaders().get(TwitterHeaders.DM_TARGET_USER_ID); - Assert.isTrue(toUser instanceof String || toUser instanceof Integer, - "the header '" + TwitterHeaders.DM_TARGET_USER_ID + - "' must be either a String (a screenname) or an int (a user ID)"); - String payload = (String) message.getPayload(); - if (toUser instanceof Integer) { - this.twitter.sendDirectMessage((Integer) toUser, payload); - } - else if (toUser instanceof String) { - this.twitter.sendDirectMessage((String) toUser, payload); - } -// } -// catch (TwitterException e) { -// throw new MessageHandlingException(message, e); -// } + Assert.isInstanceOf(String.class, message.getPayload(), "Only payload of type String is supported. If your payload " + + "is not of type String consider adding a transformer to the message flow in front of this adapter."); + Assert.isTrue(message.getHeaders().containsKey(TwitterHeaders.DM_TARGET_USER_ID), + "the '" + TwitterHeaders.DM_TARGET_USER_ID + "' header is required"); + Object toUser = message.getHeaders().get(TwitterHeaders.DM_TARGET_USER_ID); + Assert.isTrue(toUser instanceof String || toUser instanceof Integer, + "the header '" + TwitterHeaders.DM_TARGET_USER_ID + + "' must be either a String (a screenname) or an int (a user ID)"); + String payload = (String) message.getPayload(); + if (toUser instanceof Integer) { + this.twitter.sendDirectMessage((Integer) toUser, payload); + } + else if (toUser instanceof String) { + this.twitter.sendDirectMessage((String) toUser, payload); + } } } diff --git a/spring-integration-twitter/src/main/java/org/springframework/integration/twitter/outbound/OutboundStatusUpdateMessageMapper.java b/spring-integration-twitter/src/main/java/org/springframework/integration/twitter/outbound/OutboundStatusUpdateMessageMapper.java index f6a97f29b1..ef8e810c78 100644 --- a/spring-integration-twitter/src/main/java/org/springframework/integration/twitter/outbound/OutboundStatusUpdateMessageMapper.java +++ b/spring-integration-twitter/src/main/java/org/springframework/integration/twitter/outbound/OutboundStatusUpdateMessageMapper.java @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package org.springframework.integration.twitter.outbound; import org.springframework.integration.Message; diff --git a/spring-integration-twitter/src/main/java/org/springframework/integration/twitter/outbound/TimelineUpdateSendingMessageHandler.java b/spring-integration-twitter/src/main/java/org/springframework/integration/twitter/outbound/TimelineUpdateSendingMessageHandler.java index 9a1f25c3b3..e44967926a 100644 --- a/spring-integration-twitter/src/main/java/org/springframework/integration/twitter/outbound/TimelineUpdateSendingMessageHandler.java +++ b/spring-integration-twitter/src/main/java/org/springframework/integration/twitter/outbound/TimelineUpdateSendingMessageHandler.java @@ -1,5 +1,5 @@ /* - * Copyright 2010 the original author or authors + * Copyright 2002-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. @@ -20,7 +20,6 @@ import org.springframework.integration.twitter.core.TwitterOperations; import org.springframework.util.Assert; import twitter4j.StatusUpdate; -import twitter4j.Twitter; /** diff --git a/spring-integration-twitter/src/test/java/org/springframework/integration/twitter/core/Twitter4jTemplateTests.java b/spring-integration-twitter/src/test/java/org/springframework/integration/twitter/core/Twitter4jTemplateTests.java index d35269d510..078bff118e 100644 --- a/spring-integration-twitter/src/test/java/org/springframework/integration/twitter/core/Twitter4jTemplateTests.java +++ b/spring-integration-twitter/src/test/java/org/springframework/integration/twitter/core/Twitter4jTemplateTests.java @@ -110,8 +110,8 @@ public class Twitter4jTemplateTests { @Test public void testUpdateStatus() throws Exception{ - StatusUpdate statusUpdate = new StatusUpdate("writing twitter test"); - template.updateStatus(statusUpdate); - verify(twitter, times(1)).updateStatus(statusUpdate); + StatusUpdate status = new StatusUpdate("writing twitter test"); + template.updateStatus(status); + verify(twitter, times(1)).updateStatus(Mockito.any(StatusUpdate.class)); } } diff --git a/spring-integration-twitter/src/test/java/org/springframework/integration/twitter/inbound/DirectMessageReceivingMessageSourceTests.java b/spring-integration-twitter/src/test/java/org/springframework/integration/twitter/inbound/DirectMessageReceivingMessageSourceTests.java index c6a2043cc0..99d4732112 100644 --- a/spring-integration-twitter/src/test/java/org/springframework/integration/twitter/inbound/DirectMessageReceivingMessageSourceTests.java +++ b/spring-integration-twitter/src/test/java/org/springframework/integration/twitter/inbound/DirectMessageReceivingMessageSourceTests.java @@ -78,6 +78,7 @@ public class DirectMessageReceivingMessageSourceTests { assertTrue(source.isRunning()); } + @SuppressWarnings("rawtypes") @Test public void testSuccessfullInitializationWithMessages() throws Exception{ this.setUpMockScenarioForMessagePolling(); @@ -116,6 +117,7 @@ public class DirectMessageReceivingMessageSourceTests { when(twitter.getDirectMessages(Mockito.any(Paging.class))).thenReturn(testMessages); } + @SuppressWarnings({ "rawtypes", "serial" }) public static class SampleResoponceList extends ArrayList implements ResponseList { @Override diff --git a/spring-integration-twitter/src/test/java/org/springframework/integration/twitter/outbound/TimelineUpdateSendingMessageHandlerTests.java b/spring-integration-twitter/src/test/java/org/springframework/integration/twitter/outbound/TimelineUpdateSendingMessageHandlerTests.java new file mode 100644 index 0000000000..f3164faf05 --- /dev/null +++ b/spring-integration-twitter/src/test/java/org/springframework/integration/twitter/outbound/TimelineUpdateSendingMessageHandlerTests.java @@ -0,0 +1,78 @@ +/* + * Copyright 2002-2010 the original author or authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.integration.twitter.outbound; + +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; + +import java.lang.reflect.Field; + +import org.junit.Before; +import org.junit.Test; +import org.mockito.Mockito; +import org.springframework.integration.Message; +import org.springframework.integration.message.GenericMessage; +import org.springframework.integration.support.MessageBuilder; +import org.springframework.integration.twitter.core.Twitter4jTemplate; +import org.springframework.integration.twitter.core.TwitterHeaders; +import org.springframework.integration.twitter.core.TwitterOperations; + +import twitter4j.GeoLocation; +import twitter4j.StatusUpdate; +import twitter4j.Twitter; + +/** + * @author Oleg Zhurakousky + * + */ +public class TimelineUpdateSendingMessageHandlerTests { + + TwitterOperations twitterOperations; + Twitter twitter; + + @Before + public void prepare() throws Exception{ + twitterOperations = spy(new Twitter4jTemplate()); + Field twitterField = Twitter4jTemplate.class.getDeclaredField("twitter"); + twitterField.setAccessible(true); + twitter = mock(Twitter.class); + twitterField.set(twitterOperations, twitter); + } + + @SuppressWarnings({ "unchecked", "rawtypes" }) + @Test + public void testSendingStatusUpdate() throws Exception{ + TimelineUpdateSendingMessageHandler handler = new TimelineUpdateSendingMessageHandler(twitterOperations); + handler.handleMessage(new GenericMessage("writing twitter tests")); + verify(twitterOperations, times(1)).updateStatus(Mockito.any(StatusUpdate.class)); + verify(twitter, times(1)).updateStatus(Mockito.any(StatusUpdate.class)); + } + @Test + public void testSendingStatusUpdateWithHeaders() throws Exception{ + TimelineUpdateSendingMessageHandler handler = new TimelineUpdateSendingMessageHandler(twitterOperations); + Message message = MessageBuilder.withPayload("writing twitter tests") + .setHeader(TwitterHeaders.IN_REPLY_TO_STATUS_ID, new Long(123)) + .setHeader(TwitterHeaders.PLACE_ID, "123") + .setHeader(TwitterHeaders.GEOLOCATION, mock(GeoLocation.class)) + .setHeader(TwitterHeaders.DISPLAY_COORDINATES, true) + .build(); + handler.handleMessage(message); + verify(twitterOperations, times(1)).updateStatus(Mockito.any(StatusUpdate.class)); + verify(twitter, times(1)).updateStatus(Mockito.any(StatusUpdate.class)); + } +}