diff --git a/spring-integration-adapters/src/main/java/META-INF/spring-integration.parsers b/spring-integration-adapters/src/main/java/META-INF/spring-integration.parsers index ff2ac60cea..28c5e1493a 100644 --- a/spring-integration-adapters/src/main/java/META-INF/spring-integration.parsers +++ b/spring-integration-adapters/src/main/java/META-INF/spring-integration.parsers @@ -1,3 +1,5 @@ +console-source=org.springframework.integration.adapter.stream.config.ConsoleSourceParser +console-target=org.springframework.integration.adapter.stream.config.ConsoleTargetParser file-source=org.springframework.integration.adapter.file.config.FileSourceParser file-target=org.springframework.integration.adapter.file.config.FileTargetAdapterParser ftp-source=org.springframework.integration.adapter.ftp.config.FtpSourceParser diff --git a/spring-integration-adapters/src/main/java/org/springframework/integration/adapter/config/spring-integration-adapters-1.0.xsd b/spring-integration-adapters/src/main/java/org/springframework/integration/adapter/config/spring-integration-adapters-1.0.xsd index ea771e85a6..43f0d73dc8 100644 --- a/spring-integration-adapters/src/main/java/org/springframework/integration/adapter/config/spring-integration-adapters-1.0.xsd +++ b/spring-integration-adapters/src/main/java/org/springframework/integration/adapter/config/spring-integration-adapters-1.0.xsd @@ -178,6 +178,32 @@ + + + + + Configures a source that reads from stdin (System.in). + + + + + + + + + + + + Configures a target that writes to stdout (System.out) or to stderr (System.err) + if the "error" attribute is set to true. + + + + + + + + diff --git a/spring-integration-adapters/src/main/java/org/springframework/integration/adapter/stream/CharacterStreamSource.java b/spring-integration-adapters/src/main/java/org/springframework/integration/adapter/stream/CharacterStreamSource.java index 9d1c0698c3..a87dd1c6cf 100644 --- a/spring-integration-adapters/src/main/java/org/springframework/integration/adapter/stream/CharacterStreamSource.java +++ b/spring-integration-adapters/src/main/java/org/springframework/integration/adapter/stream/CharacterStreamSource.java @@ -20,8 +20,9 @@ import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.io.Reader; +import java.io.UnsupportedEncodingException; -import org.springframework.integration.channel.MessageChannel; +import org.springframework.integration.ConfigurationException; import org.springframework.integration.message.MessagingException; import org.springframework.integration.message.PollableSource; import org.springframework.integration.message.StringMessage; @@ -78,4 +79,13 @@ public class CharacterStreamSource implements PollableSource { return new CharacterStreamSource(new InputStreamReader(System.in)); } + public static final CharacterStreamSource stdin(String charsetName) { + try { + return new CharacterStreamSource(new InputStreamReader(System.in, charsetName)); + } + catch (UnsupportedEncodingException e) { + throw new ConfigurationException("unsupported encoding: " + charsetName, e); + } + } + } diff --git a/spring-integration-adapters/src/main/java/org/springframework/integration/adapter/stream/config/ConsoleSourceParser.java b/spring-integration-adapters/src/main/java/org/springframework/integration/adapter/stream/config/ConsoleSourceParser.java new file mode 100644 index 0000000000..d238076b76 --- /dev/null +++ b/spring-integration-adapters/src/main/java/org/springframework/integration/adapter/stream/config/ConsoleSourceParser.java @@ -0,0 +1,57 @@ +/* + * Copyright 2002-2008 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.adapter.stream.config; + +import org.w3c.dom.Element; + +import org.springframework.beans.factory.support.BeanDefinitionBuilder; +import org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser; +import org.springframework.integration.adapter.stream.CharacterStreamSource; +import org.springframework.util.StringUtils; + +/** + * Parser for the <console-source> element. + * + * @author Mark Fisher + */ +public class ConsoleSourceParser extends AbstractSingleBeanDefinitionParser { + + @Override + protected Class getBeanClass(Element element) { + return CharacterStreamSource.class; + } + + @Override + protected boolean shouldGenerateId() { + return false; + } + + @Override + protected boolean shouldGenerateIdAsFallback() { + return true; + } + + @Override + protected void doParse(Element element, BeanDefinitionBuilder builder) { + builder.setFactoryMethod("stdin"); + String charsetName = element.getAttribute("charset"); + if (StringUtils.hasText(charsetName)) { + builder.addConstructorArgValue(charsetName); + } + } + +} diff --git a/spring-integration-adapters/src/main/java/org/springframework/integration/adapter/stream/config/ConsoleTargetParser.java b/spring-integration-adapters/src/main/java/org/springframework/integration/adapter/stream/config/ConsoleTargetParser.java new file mode 100644 index 0000000000..f5689167df --- /dev/null +++ b/spring-integration-adapters/src/main/java/org/springframework/integration/adapter/stream/config/ConsoleTargetParser.java @@ -0,0 +1,62 @@ +/* + * Copyright 2002-2008 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.adapter.stream.config; + +import org.w3c.dom.Element; + +import org.springframework.beans.factory.support.BeanDefinitionBuilder; +import org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser; +import org.springframework.integration.adapter.stream.CharacterStreamTargetAdapter; +import org.springframework.util.StringUtils; + +/** + * Parser for the <console-target> element. + * + * @author Mark Fisher + */ +public class ConsoleTargetParser extends AbstractSingleBeanDefinitionParser { + + @Override + protected Class getBeanClass(Element element) { + return CharacterStreamTargetAdapter.class; + } + + @Override + protected boolean shouldGenerateId() { + return false; + } + + @Override + protected boolean shouldGenerateIdAsFallback() { + return true; + } + + @Override + protected void doParse(Element element, BeanDefinitionBuilder builder) { + if ("true".equals(element.getAttribute("error"))) { + builder.setFactoryMethod("stderrAdapter"); + } + else { + builder.setFactoryMethod("stdoutAdapter"); + } + String charsetName = element.getAttribute("charset"); + if (StringUtils.hasText(charsetName)) { + builder.addConstructorArgValue(charsetName); + } + } + +} diff --git a/spring-integration-adapters/src/test/java/org/springframework/integration/adapter/stream/config/ConsoleSourceParserTests.java b/spring-integration-adapters/src/test/java/org/springframework/integration/adapter/stream/config/ConsoleSourceParserTests.java new file mode 100644 index 0000000000..1cd860198c --- /dev/null +++ b/spring-integration-adapters/src/test/java/org/springframework/integration/adapter/stream/config/ConsoleSourceParserTests.java @@ -0,0 +1,104 @@ +/* + * Copyright 2002-2008 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.adapter.stream.config; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; + +import java.io.BufferedReader; +import java.io.ByteArrayInputStream; +import java.io.InputStreamReader; +import java.io.Reader; +import java.io.UnsupportedEncodingException; +import java.nio.charset.Charset; + +import org.junit.Before; +import org.junit.Test; + +import org.springframework.beans.DirectFieldAccessor; +import org.springframework.beans.factory.BeanCreationException; +import org.springframework.context.support.ClassPathXmlApplicationContext; +import org.springframework.integration.ConfigurationException; +import org.springframework.integration.adapter.stream.CharacterStreamSource; +import org.springframework.integration.message.Message; + +/** + * @author Mark Fisher + */ +public class ConsoleSourceParserTests { + + @Before + public void writeTestInput() { + ByteArrayInputStream stream = new ByteArrayInputStream("foo".getBytes()); + System.setIn(stream); + } + + @Test + public void testConsoleSourceWithDefaultCharset() { + ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext( + "consoleSourceParserTests.xml", ConsoleSourceParserTests.class); + CharacterStreamSource source = + (CharacterStreamSource) context.getBean("sourceWithDefaultCharset"); + DirectFieldAccessor sourceAccessor = new DirectFieldAccessor(source); + Reader bufferedReader = (Reader) sourceAccessor.getPropertyValue("reader"); + assertEquals(BufferedReader.class, bufferedReader.getClass()); + DirectFieldAccessor bufferedReaderAccessor = new DirectFieldAccessor(bufferedReader); + Reader reader = (Reader) bufferedReaderAccessor.getPropertyValue("in"); + assertEquals(InputStreamReader.class, reader.getClass()); + Charset readerCharset = Charset.forName(((InputStreamReader) reader).getEncoding()); + assertEquals(Charset.defaultCharset(), readerCharset); + Message message = source.receive(); + assertNotNull(message); + assertEquals("foo", message.getPayload()); + } + + @Test + public void testConsoleSourceWithProvidedCharset() { + ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext( + "consoleSourceParserTests.xml", ConsoleSourceParserTests.class); + CharacterStreamSource source = + (CharacterStreamSource) context.getBean("sourceWithProvidedCharset"); + DirectFieldAccessor sourceAccessor = new DirectFieldAccessor(source); + Reader bufferedReader = (Reader) sourceAccessor.getPropertyValue("reader"); + assertEquals(BufferedReader.class, bufferedReader.getClass()); + DirectFieldAccessor bufferedReaderAccessor = new DirectFieldAccessor(bufferedReader); + Reader reader = (Reader) bufferedReaderAccessor.getPropertyValue("in"); + assertEquals(InputStreamReader.class, reader.getClass()); + Charset readerCharset = Charset.forName(((InputStreamReader) reader).getEncoding()); + assertEquals(Charset.forName("UTF-8"), readerCharset); + Message message = source.receive(); + assertNotNull(message); + assertEquals("foo", message.getPayload()); + } + + @Test + public void testConsoleSourceWithInvalidCharset() { + BeanCreationException beanCreationException = null; + try { + new ClassPathXmlApplicationContext( + "invalidConsoleSourceParserTests.xml", ConsoleSourceParserTests.class); + } + catch (BeanCreationException e) { + beanCreationException = e; + } + Throwable parentCause = beanCreationException.getCause().getCause(); + assertEquals(ConfigurationException.class, parentCause.getClass()); + Throwable configurationExceptionCause = ((ConfigurationException) parentCause).getCause(); + assertEquals(UnsupportedEncodingException.class, configurationExceptionCause.getClass()); + } + +} diff --git a/spring-integration-adapters/src/test/java/org/springframework/integration/adapter/stream/config/ConsoleTargetParserTests.java b/spring-integration-adapters/src/test/java/org/springframework/integration/adapter/stream/config/ConsoleTargetParserTests.java new file mode 100644 index 0000000000..d14e108d1c --- /dev/null +++ b/spring-integration-adapters/src/test/java/org/springframework/integration/adapter/stream/config/ConsoleTargetParserTests.java @@ -0,0 +1,136 @@ +/* + * Copyright 2002-2008 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.adapter.stream.config; + +import static org.junit.Assert.assertEquals; + +import java.io.BufferedWriter; +import java.io.ByteArrayOutputStream; +import java.io.OutputStreamWriter; +import java.io.PrintStream; +import java.io.UnsupportedEncodingException; +import java.io.Writer; +import java.nio.charset.Charset; + +import org.junit.Before; +import org.junit.Test; + +import org.springframework.beans.DirectFieldAccessor; +import org.springframework.beans.factory.BeanCreationException; +import org.springframework.context.support.ClassPathXmlApplicationContext; +import org.springframework.integration.ConfigurationException; +import org.springframework.integration.adapter.stream.CharacterStreamTargetAdapter; +import org.springframework.integration.message.StringMessage; + +/** + * @author Mark Fisher + */ +public class ConsoleTargetParserTests { + + private final ByteArrayOutputStream err = new ByteArrayOutputStream(); + + private final ByteArrayOutputStream out = new ByteArrayOutputStream(); + + + @Before + public void setupStreams() { + System.setErr(new PrintStream(this.err)); + System.setOut(new PrintStream(this.out)); + } + + private void resetStreams() { + this.err.reset(); + this.out.reset(); + } + + @Test + public void testConsoleTargetWithDefaultCharset() { + ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext( + "consoleTargetParserTests.xml", ConsoleTargetParserTests.class); + CharacterStreamTargetAdapter target = + (CharacterStreamTargetAdapter) context.getBean("targetWithDefaultCharset"); + DirectFieldAccessor targetAccessor = new DirectFieldAccessor(target); + Writer bufferedWriter = (Writer) targetAccessor.getPropertyValue("writer"); + assertEquals(BufferedWriter.class, bufferedWriter.getClass()); + DirectFieldAccessor bufferedWriterAccessor = new DirectFieldAccessor(bufferedWriter); + Writer writer = (Writer) bufferedWriterAccessor.getPropertyValue("out"); + assertEquals(OutputStreamWriter.class, writer.getClass()); + Charset writerCharset = Charset.forName(((OutputStreamWriter) writer).getEncoding()); + assertEquals(Charset.defaultCharset(), writerCharset); + this.resetStreams(); + target.send(new StringMessage("foo")); + assertEquals("foo", out.toString()); + assertEquals("", err.toString()); + } + + @Test + public void testConsoleTargetWithProvidedCharset() { + ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext( + "consoleTargetParserTests.xml", ConsoleTargetParserTests.class); + CharacterStreamTargetAdapter target = + (CharacterStreamTargetAdapter) context.getBean("targetWithProvidedCharset"); + DirectFieldAccessor targetAccessor = new DirectFieldAccessor(target); + Writer bufferedWriter = (Writer) targetAccessor.getPropertyValue("writer"); + assertEquals(BufferedWriter.class, bufferedWriter.getClass()); + DirectFieldAccessor bufferedWriterAccessor = new DirectFieldAccessor(bufferedWriter); + Writer writer = (Writer) bufferedWriterAccessor.getPropertyValue("out"); + assertEquals(OutputStreamWriter.class, writer.getClass()); + Charset writerCharset = Charset.forName(((OutputStreamWriter) writer).getEncoding()); + assertEquals(Charset.forName("UTF-8"), writerCharset); + this.resetStreams(); + target.send(new StringMessage("bar")); + assertEquals("bar", out.toString()); + assertEquals("", err.toString()); + } + + @Test + public void testConsoleTargetWithInvalidCharset() { + BeanCreationException beanCreationException = null; + try { + new ClassPathXmlApplicationContext( + "invalidConsoleTargetParserTests.xml", ConsoleTargetParserTests.class); + } + catch (BeanCreationException e) { + beanCreationException = e; + } + Throwable parentCause = beanCreationException.getCause().getCause(); + assertEquals(ConfigurationException.class, parentCause.getClass()); + Throwable configurationExceptionCause = ((ConfigurationException) parentCause).getCause(); + assertEquals(UnsupportedEncodingException.class, configurationExceptionCause.getClass()); + } + + @Test + public void testErrorTarget() { + ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext( + "consoleTargetParserTests.xml", ConsoleTargetParserTests.class); + CharacterStreamTargetAdapter target = + (CharacterStreamTargetAdapter) context.getBean("stderrTarget"); + DirectFieldAccessor targetAccessor = new DirectFieldAccessor(target); + Writer bufferedWriter = (Writer) targetAccessor.getPropertyValue("writer"); + assertEquals(BufferedWriter.class, bufferedWriter.getClass()); + DirectFieldAccessor bufferedWriterAccessor = new DirectFieldAccessor(bufferedWriter); + Writer writer = (Writer) bufferedWriterAccessor.getPropertyValue("out"); + assertEquals(OutputStreamWriter.class, writer.getClass()); + Charset writerCharset = Charset.forName(((OutputStreamWriter) writer).getEncoding()); + assertEquals(Charset.defaultCharset(), writerCharset); + this.resetStreams(); + target.send(new StringMessage("bad")); + assertEquals("", out.toString()); + assertEquals("bad", err.toString()); + } + +} diff --git a/spring-integration-adapters/src/test/java/org/springframework/integration/adapter/stream/config/consoleSourceParserTests.xml b/spring-integration-adapters/src/test/java/org/springframework/integration/adapter/stream/config/consoleSourceParserTests.xml new file mode 100644 index 0000000000..ed35e5b1c6 --- /dev/null +++ b/spring-integration-adapters/src/test/java/org/springframework/integration/adapter/stream/config/consoleSourceParserTests.xml @@ -0,0 +1,14 @@ + + + + + + + + \ No newline at end of file diff --git a/spring-integration-adapters/src/test/java/org/springframework/integration/adapter/stream/config/consoleTargetParserTests.xml b/spring-integration-adapters/src/test/java/org/springframework/integration/adapter/stream/config/consoleTargetParserTests.xml new file mode 100644 index 0000000000..58fa0b17a3 --- /dev/null +++ b/spring-integration-adapters/src/test/java/org/springframework/integration/adapter/stream/config/consoleTargetParserTests.xml @@ -0,0 +1,16 @@ + + + + + + + + + + \ No newline at end of file diff --git a/spring-integration-adapters/src/test/java/org/springframework/integration/adapter/stream/config/invalidConsoleSourceParserTests.xml b/spring-integration-adapters/src/test/java/org/springframework/integration/adapter/stream/config/invalidConsoleSourceParserTests.xml new file mode 100644 index 0000000000..d9fe407319 --- /dev/null +++ b/spring-integration-adapters/src/test/java/org/springframework/integration/adapter/stream/config/invalidConsoleSourceParserTests.xml @@ -0,0 +1,12 @@ + + + + + + \ No newline at end of file diff --git a/spring-integration-adapters/src/test/java/org/springframework/integration/adapter/stream/config/invalidConsoleTargetParserTests.xml b/spring-integration-adapters/src/test/java/org/springframework/integration/adapter/stream/config/invalidConsoleTargetParserTests.xml new file mode 100644 index 0000000000..204ae78793 --- /dev/null +++ b/spring-integration-adapters/src/test/java/org/springframework/integration/adapter/stream/config/invalidConsoleTargetParserTests.xml @@ -0,0 +1,12 @@ + + + + + + \ No newline at end of file