Merge pull request #780 from garyrussell/INT-2982

* garyrussell-INT-2982:
  INT-2982 Add Syslog Inbound Channel Adapter
This commit is contained in:
Gunnar Hillert
2013-04-23 23:39:07 -04:00
34 changed files with 1440 additions and 44 deletions

View File

@@ -480,6 +480,14 @@ project('spring-integration-stream') {
}
}
project('spring-integration-syslog') {
description = 'Spring Integration Syslog Support'
dependencies {
compile project(":spring-integration-ip")
testCompile project(":spring-integration-test")
}
}
project('spring-integration-test') {
description = 'Spring Integration Test Support'
dependencies {

View File

@@ -22,6 +22,7 @@ include 'spring-integration-scripting'
include 'spring-integration-security'
include 'spring-integration-sftp'
include 'spring-integration-stream'
include 'spring-integration-syslog'
include 'spring-integration-test'
include 'spring-integration-twitter'
include 'spring-integration-ws'

View File

@@ -42,7 +42,13 @@ public class SyslogToMapTransformer extends AbstractPayloadTransformer<Object, M
public static final String SEVERITY = "SEVERITY";
public static final String TIMESAMP = "TIMESTAMP";
public static final String TIMESTAMP = "TIMESTAMP";
/**
* @deprecated use {@link #TIMESTAMP}
*/
@Deprecated
public static final String TIMESAMP = TIMESTAMP;
public static final String HOST = "HOST";
@@ -100,14 +106,14 @@ public class SyslogToMapTransformer extends AbstractPayloadTransformer<Object, M
else {
calendar.set(Calendar.YEAR, year);
}
map.put(TIMESAMP, calendar.getTime());
map.put(TIMESTAMP, calendar.getTime());
}
catch (Exception e) {
/*
* If we can't parse the timestamp, return it as an
* unmodified String. (Postel's law).
*/
map.put(TIMESAMP, timestamp);
map.put(TIMESTAMP, timestamp);
}
map.put(HOST, matcher.group(3));
map.put(TAG, matcher.group(4));
@@ -132,12 +138,13 @@ public class SyslogToMapTransformer extends AbstractPayloadTransformer<Object, M
@Override
protected Map<String, ?> transformPayload(Object payload) throws Exception {
Assert.isTrue(payload instanceof byte[] || payload instanceof String,
"payload must be String or byte[]");
if (payload instanceof byte[]) {
boolean isByteArray = payload instanceof byte[];
boolean isString = payload instanceof String;
Assert.isTrue(isByteArray || isString, "payload must be String or byte[]");
if (isByteArray) {
return this.transform((byte[]) payload);
}
else if (payload instanceof String) {
else if (isString) {
return this.transform((String) payload);
}
return null;

View File

@@ -56,7 +56,7 @@ public class SyslogTransformerParserTests {
assertEquals(6, map.size());
assertEquals(19, map.get(SyslogToMapTransformer.FACILITY));
assertEquals(5, map.get(SyslogToMapTransformer.SEVERITY));
Object date = map.get(SyslogToMapTransformer.TIMESAMP);
Object date = map.get(SyslogToMapTransformer.TIMESTAMP);
assertTrue(date instanceof Date || date instanceof String);
assertEquals("WEBERN", map.get(SyslogToMapTransformer.HOST));
assertEquals("TESTING[70729]", map.get(SyslogToMapTransformer.TAG));

View File

@@ -39,7 +39,7 @@ public class SysLogTransformerTests {
assertEquals(6, transformed.size());
assertEquals(19, transformed.get(SyslogToMapTransformer.FACILITY));
assertEquals(6, transformed.get(SyslogToMapTransformer.SEVERITY));
Object date = transformed.get(SyslogToMapTransformer.TIMESAMP);
Object date = transformed.get(SyslogToMapTransformer.TIMESTAMP);
assertTrue(date instanceof Date || date instanceof String);
assertEquals("WEBERN", transformed.get(SyslogToMapTransformer.HOST));
assertEquals("TESTING[70729]", transformed.get(SyslogToMapTransformer.TAG));

View File

@@ -34,6 +34,7 @@ import org.w3c.dom.Element;
*/
public class UdpInboundChannelAdapterParser extends AbstractChannelAdapterParser {
@Override
protected AbstractBeanDefinition doParse(Element element, ParserContext parserContext, String channelName) {
BeanDefinitionBuilder builder = parseUdp(element, parserContext);
IpAdapterParserUtils.addCommonSocketOptions(builder, element);

View File

@@ -27,25 +27,14 @@
</xsd:annotation>
<xsd:complexType>
<xsd:complexContent>
<xsd:extension base="udpAdapterType">
<xsd:attribute name="pool-size" type="xsd:string" >
<xsd:extension base="udpInboundAdapterType">
<xsd:attribute name="channel" type="xsd:string">
<xsd:annotation>
<xsd:documentation>
The number of threads that will be used for socket/channel handling. Only applies
if an external task-executor is NOT being used. When using an external task executor,
its configuration specifies the number of threads.
</xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="receive-buffer-size" type="xsd:string" />
<xsd:attribute name="multicast-address" type="xsd:string" />
<xsd:attribute name="task-executor" type="xsd:string">
<xsd:annotation>
<xsd:documentation>
Specifies a specific Executor to be used for socket handling. If not supplied, an internal
pooled executor will be used (See pool-size). Needed on some platforms that require the use of specific
task executors such as a WorkManagerTaskExecutor.
</xsd:documentation>
<xsd:appinfo>
<tool:annotation kind="ref">
<tool:expected-type type="org.springframework.integration.MessageChannel"/>
</tool:annotation>
</xsd:appinfo>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="error-channel" type="xsd:string">
@@ -62,14 +51,6 @@ its configuration specifies the number of threads.
</xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="lookup-host" type="xsd:string" >
<xsd:annotation>
<xsd:documentation>
Whether or not to do a DNS reverse-lookup on the remote ip address to insert the host name into the
message headers (ip_hostName). Default "true".
</xsd:documentation>
</xsd:annotation>
</xsd:attribute>
</xsd:extension>
</xsd:complexContent>
</xsd:complexType>
@@ -87,6 +68,15 @@ message headers (ip_hostName). Default "true".
<xsd:all>
<xsd:element name="request-handler-advice-chain" type="integration:adviceChainType" minOccurs="0" maxOccurs="1" />
</xsd:all>
<xsd:attribute name="channel" type="xsd:string">
<xsd:annotation>
<xsd:appinfo>
<tool:annotation kind="ref">
<tool:expected-type type="org.springframework.integration.MessageChannel"/>
</tool:annotation>
</xsd:appinfo>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="host" type="xsd:string" />
<xsd:attribute name="acknowledge" type="xsd:string" />
<xsd:attribute name="ack-host" type="xsd:string" />
@@ -668,6 +658,41 @@ setCustomHeaders(). Default is TcpMessageMapper.
</xsd:complexType>
</xsd:element>
<xsd:complexType name="udpInboundAdapterType">
<xsd:complexContent>
<xsd:extension base="udpAdapterType">
<xsd:attribute name="pool-size" type="xsd:string" >
<xsd:annotation>
<xsd:documentation>
The number of threads that will be used for socket/channel handling. Only applies
if an external task-executor is NOT being used. When using an external task executor,
its configuration specifies the number of threads.
</xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="receive-buffer-size" type="xsd:string" />
<xsd:attribute name="multicast-address" type="xsd:string" />
<xsd:attribute name="task-executor" type="xsd:string">
<xsd:annotation>
<xsd:documentation>
Specifies a specific Executor to be used for socket handling. If not supplied, an internal
pooled executor will be used (See pool-size). Needed on some platforms that require the use of specific
task executors such as a WorkManagerTaskExecutor.
</xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="lookup-host" type="xsd:string" >
<xsd:annotation>
<xsd:documentation>
Whether or not to do a DNS reverse-lookup on the remote ip address to insert the host name into the
message headers (ip_hostName). Default "true".
</xsd:documentation>
</xsd:annotation>
</xsd:attribute>
</xsd:extension>
</xsd:complexContent>
</xsd:complexType>
<xsd:complexType name="udpAdapterType">
<xsd:annotation>
<xsd:documentation>
@@ -676,15 +701,6 @@ setCustomHeaders(). Default is TcpMessageMapper.
</xsd:annotation>
<xsd:complexContent>
<xsd:extension base="common-attributes">
<xsd:attribute name="channel" type="xsd:string">
<xsd:annotation>
<xsd:appinfo>
<tool:annotation kind="ref">
<tool:expected-type type="org.springframework.integration.MessageChannel"/>
</tool:annotation>
</xsd:appinfo>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="check-length" type="xsd:string" />
<xsd:attribute name="multicast" type="xsd:string" />
</xsd:extension>

View File

@@ -0,0 +1,60 @@
/*
* Copyright 2002-2013 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* 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.syslog;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import org.springframework.integration.Message;
import org.springframework.integration.support.MessageBuilder;
import org.springframework.integration.transformer.SyslogToMapTransformer;
/**
* Default {@link MessageConverter}; delegates to a {@link SyslogToMapTransformer}
* to convert the payload to a map of values and also provides some of the map
* contents as message headers.
* See @link {@link SyslogHeaders} for the headers that are mapped.
* @author Gary Russell
* @since 3.0
*
*/
public class DefaultMessageConverter implements MessageConverter {
private final SyslogToMapTransformer transformer = new SyslogToMapTransformer();
public static final Set<String> SYSLOG_PAYLOAD_ENTRIES = new HashSet<String>(
Arrays.asList(new String[] {SyslogToMapTransformer.MESSAGE, SyslogToMapTransformer.UNDECODED}));
@Override
public Message<?> fromSyslog(Message<?> message) throws Exception {
Map<String, ?> map = this.transformer.doTransform(message);
Map<String, Object> out = new HashMap<String, Object>();
for (Entry<String, ?> entry : map.entrySet()) {
String key = entry.getKey();
if (!SYSLOG_PAYLOAD_ENTRIES.contains(key)) {
out.put(SyslogHeaders.PREFIX + entry.getKey(), entry.getValue());
}
}
return MessageBuilder.withPayload(map)
.copyHeaders(out)
.build();
}
}

View File

@@ -0,0 +1,31 @@
/*
* Copyright 2002-2013 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* 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.syslog;
import org.springframework.integration.Message;
/**
* A converter to convert the raw message created by the underlying
* UDP/TCP endpoint to a specific form of Syslog message.
* @author Gary Russell
* @since 3.0
*
*/
public interface MessageConverter {
Message<?> fromSyslog(Message<?> syslog) throws Exception;
}

View File

@@ -0,0 +1,41 @@
/*
* Copyright 2002-2013 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* 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.syslog;
import org.springframework.integration.transformer.SyslogToMapTransformer;
/**
* Headers in a {@code Map} generated by the @link {@link SyslogToMapTransformer} that
* will be added to Spring Integration messages as headers, prefixed by {@link #PREFIX}.
* @author Gary Russell
* @since 3.0
*
*/
public class SyslogHeaders {
public static String PREFIX = "syslog_";
public static final String FACILITY = PREFIX + SyslogToMapTransformer.FACILITY;
public static final String SEVERITY = PREFIX + SyslogToMapTransformer.SEVERITY;
public static final String TIMESTAMP = PREFIX + SyslogToMapTransformer.TIMESTAMP;
public static final String HOST = PREFIX + SyslogToMapTransformer.HOST;
public static final String TAG = PREFIX + SyslogToMapTransformer.TAG;
}

View File

@@ -0,0 +1,67 @@
/*
* Copyright 2002-2013 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* 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.syslog.config;
import org.springframework.beans.factory.config.BeanDefinition;
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.IntegrationNamespaceUtils;
import org.springframework.integration.ip.config.UdpInboundChannelAdapterParser;
import org.springframework.util.StringUtils;
import org.springframework.util.xml.DomUtils;
import org.w3c.dom.Element;
/**
* Parses a {@code <int-syslog:inbound-channel-adapter/>}.
* @author Gary Russell
* @since 3.0
*
*/
public class SyslogInboundChannelAdapterParser extends UdpInboundChannelAdapterParser {
@Override
protected AbstractBeanDefinition doParse(Element element, ParserContext parserContext, String channelName) {
BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(SyslogReceivingChannelAdapterFactoryBean.class);
String protocol = element.getAttribute("protocol");
if (!StringUtils.hasText(protocol)) {
protocol = SyslogReceivingChannelAdapterFactoryBean.Protocol.udp.toString();
}
builder.addConstructorArgValue(protocol);
IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, "port");
IntegrationNamespaceUtils.setReferenceIfAttributeDefined(builder, element,
"connection-factory");
IntegrationNamespaceUtils.setReferenceIfAttributeDefined(builder, element, "converter");
Element udpAdapterElement = DomUtils.getChildElementByTagName(element, "udp-attributes");
if (udpAdapterElement != null) {
if (StringUtils.hasText(element.getAttribute("port"))) {
parserContext.getReaderContext().error(
"When child element 'udp-attributes' is present, 'port' must be defined there", element);
}
BeanDefinition udpAdapterDef = super.doParse(udpAdapterElement, parserContext, channelName);
builder.addPropertyValue("udpAdapter", udpAdapterDef);
}
builder.addPropertyReference("outputChannel", channelName);
IntegrationNamespaceUtils.setReferenceIfAttributeDefined(builder,
element, "error-channel", "errorChannel");
IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, "send-timeout");
IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, "auto-startup");
IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, "phase");
return builder.getBeanDefinition();
}
}

View File

@@ -0,0 +1,33 @@
/*
* Copyright 2002-2013 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* 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.syslog.config;
import org.springframework.integration.config.xml.AbstractIntegrationNamespaceHandler;
/**
* Namspace handler for spring-integration-syslog.
* @author Gary Russell
* @since 3.0
*
*/
public class SyslogNamespaceHandler extends AbstractIntegrationNamespaceHandler {
@Override
public void init() {
this.registerBeanDefinitionParser("inbound-channel-adapter", new SyslogInboundChannelAdapterParser());
}
}

View File

@@ -0,0 +1,209 @@
/*
* Copyright 2002-2013 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* 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.syslog.config;
import org.springframework.beans.factory.BeanNameAware;
import org.springframework.beans.factory.config.AbstractFactoryBean;
import org.springframework.context.SmartLifecycle;
import org.springframework.integration.MessageChannel;
import org.springframework.integration.ip.tcp.connection.AbstractServerConnectionFactory;
import org.springframework.integration.ip.udp.UnicastReceivingChannelAdapter;
import org.springframework.integration.syslog.MessageConverter;
import org.springframework.integration.syslog.inbound.SyslogReceivingChannelAdapterSupport;
import org.springframework.integration.syslog.inbound.TcpSyslogReceivingChannelAdapter;
import org.springframework.integration.syslog.inbound.UdpSyslogReceivingChannelAdapter;
import org.springframework.util.Assert;
/**
* Factory bean to create syslog inbound adapters (UDP or TCP).
* @author Gary Russell
* @since 3.0
*
*/
public class SyslogReceivingChannelAdapterFactoryBean extends AbstractFactoryBean<SyslogReceivingChannelAdapterSupport>
implements SmartLifecycle, BeanNameAware {
public enum Protocol { udp, tcp };
private volatile SyslogReceivingChannelAdapterSupport adapter;
private final Protocol protocol;
private volatile MessageChannel outputChannel;
private volatile boolean autoStartup = true;
private volatile MessageChannel errorChannel;
private volatile int phase;
private volatile Long sendTimeout;
private volatile AbstractServerConnectionFactory connectionFactory;
private volatile UnicastReceivingChannelAdapter udpAdapter;
private volatile Integer port;
private volatile MessageConverter converter;
private volatile String beanName;
/**
* Instantiates a factory bean that creates a {@link UdpSyslogReceivingChannelAdapter}
* if the protocol is {@link Protocol#udp} or a {@link TcpSyslogReceivingChannelAdapter} if
* the protocol is {@link Protocol#tcp}.
* @param protocol The protocol.
*/
public SyslogReceivingChannelAdapterFactoryBean(Protocol protocol) {
Assert.notNull(protocol, "'protocol' cannot be null");
this.protocol = protocol;
}
public void setOutputChannel(MessageChannel outputChannel) {
this.outputChannel = outputChannel;
}
public void setAutoStartup(boolean autoStartup) {
this.autoStartup = autoStartup;
}
public void setErrorChannel(MessageChannel errorChannel) {
this.errorChannel = errorChannel;
}
public void setPhase(int phase) {
this.phase = phase;
}
public void setSendTimeout(long sendTimeout) {
this.sendTimeout = sendTimeout;
}
public void setConnectionFactory(AbstractServerConnectionFactory connectionFactory) {
this.connectionFactory = connectionFactory;
}
public void setUdpAdapter(UnicastReceivingChannelAdapter udpAdapter) {
this.udpAdapter = udpAdapter;
}
public void setPort(int port) {
this.port = port;
}
public void setConverter(MessageConverter converter) {
this.converter = converter;
}
@Override
public void start() {
if (this.adapter != null) {
this.adapter.start();
}
}
@Override
public void stop() {
if (this.adapter != null) {
this.adapter.stop();
}
}
@Override
public boolean isRunning() {
if (this.adapter != null) {
return this.adapter.isRunning();
}
return false;
}
@Override
public int getPhase() {
return this.phase;
}
@Override
public void setBeanName(String name) {
this.beanName = name;
}
@Override
public boolean isAutoStartup() {
return this.autoStartup;
}
@Override
public void stop(Runnable callback) {
if (this.adapter != null) {
this.adapter.stop(callback);
}
}
@Override
public Class<?> getObjectType() {
return this.adapter == null ? SyslogReceivingChannelAdapterSupport.class :
this.adapter.getClass();
}
@Override
protected SyslogReceivingChannelAdapterSupport createInstance() throws Exception {
SyslogReceivingChannelAdapterSupport adapter;
if (this.protocol == Protocol.tcp) {
adapter = new TcpSyslogReceivingChannelAdapter();
if (this.connectionFactory != null) {
Assert.isNull(this.port, "Cannot specify both 'port' and 'connectionFactory'");
((TcpSyslogReceivingChannelAdapter) adapter).setConnectionFactory(this.connectionFactory);
}
Assert.isNull(this.udpAdapter, "Cannot specifiy 'udp-attributes' when the protocol is 'tcp'");
}
else if(this.protocol == Protocol.udp) {
adapter = new UdpSyslogReceivingChannelAdapter();
if (this.udpAdapter != null) {
Assert.isNull(this.port, "Cannot specify both 'port' and 'udpAdapter'");
((UdpSyslogReceivingChannelAdapter) adapter).setUdpAdapter(this.udpAdapter);
}
Assert.isNull(this.connectionFactory, "Cannot specifiy 'connection-factory' unless the protocol is 'tcp'");
}
else {
throw new IllegalStateException("Unsupported protocol: " + this.protocol.toString());
}
if (this.port != null) {
adapter.setPort(this.port);
}
if (this.outputChannel != null) {
adapter.setOutputChannel(this.outputChannel);
}
adapter.setAutoStartup(this.autoStartup);
adapter.setPhase(this.phase);
if (this.errorChannel != null) {
adapter.setErrorChannel(this.errorChannel);
}
if (this.sendTimeout != null) {
adapter.setSendTimeout(this.sendTimeout);
}
if (this.converter != null) {
adapter.setConverter(this.converter);
}
if (this.beanName != null) {
adapter.setBeanName(this.beanName);
}
adapter.afterPropertiesSet();
this.adapter = adapter;
return adapter;
}
}

View File

@@ -0,0 +1,4 @@
/**
* Provides classes for configuration - parsers, namespace handlers, factory beans.
*/
package org.springframework.integration.syslog.config;

View File

@@ -0,0 +1,80 @@
/*
* Copyright 2002-2013 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* 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.syslog.inbound;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.integration.Message;
import org.springframework.integration.MessagingException;
import org.springframework.integration.endpoint.MessageProducerSupport;
import org.springframework.integration.syslog.DefaultMessageConverter;
import org.springframework.integration.syslog.MessageConverter;
/**
* Base support class for inbound channel adapters. The default port is 514.
*
* @author Gary Russell
* @since 3.0
*
*/
public abstract class SyslogReceivingChannelAdapterSupport extends MessageProducerSupport {
protected static final int DEFAULT_PORT = 514;
private volatile int port = DEFAULT_PORT;
protected final Log logger = LogFactory.getLog(this.getClass());
private volatile MessageConverter converter = new DefaultMessageConverter();
/**
* @return The port on which this adapter listens.
*/
protected int getPort() {
return this.port;
}
/**
* Sets the port on which the adapter listens; default is 514; note that
* the RFC does not specify a well known port for TCP; 514 is the well-known
* port for UDP. Many admins also use 514 for TCP; see RFC-6587 for more
* information about TCP and RFC-3164/5424 for more information about UDP.
* @param port The port.
*/
public void setPort(int port) {
this.port = port;
}
/**
* A {@link MessageConverter} to convert the byte array payload
* of the underlying UDP/TCP message to a Spring Integration message
* with decoded payload and headers; default is {@link DefaultMessageConverter}.
* @param converter The converter.
*/
public void setConverter(MessageConverter converter) {
this.converter = converter;
}
protected void convertAndSend(Message<?> message) {
try {
this.sendMessage(this.converter.fromSyslog(message));
}
catch (Exception e) {
throw new MessagingException(message, e);
}
}
}

View File

@@ -0,0 +1,72 @@
/*
* Copyright 2002-2013 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* 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.syslog.inbound;
import org.springframework.integration.Message;
import org.springframework.integration.ip.tcp.connection.AbstractServerConnectionFactory;
import org.springframework.integration.ip.tcp.connection.TcpListener;
import org.springframework.integration.ip.tcp.connection.TcpNioServerConnectionFactory;
import org.springframework.integration.ip.tcp.serializer.ByteArrayLfSerializer;
/**
* TCP implementation of a syslog inbound channel adapter.
*
* @author Gary Russell
* @since 3.0
*
*/
public class TcpSyslogReceivingChannelAdapter extends SyslogReceivingChannelAdapterSupport
implements TcpListener {
private volatile AbstractServerConnectionFactory connectionFactory;
/**
* @param connectionFactory
*/
public void setConnectionFactory(AbstractServerConnectionFactory connectionFactory) {
this.connectionFactory = connectionFactory;
}
@Override
protected void onInit() {
super.onInit();
if (this.connectionFactory == null) {
this.connectionFactory = new TcpNioServerConnectionFactory(this.getPort());
this.connectionFactory.setDeserializer(new ByteArrayLfSerializer());
}
this.connectionFactory.registerListener(this);
}
@Override
protected void doStart() {
super.doStart();
this.connectionFactory.start();
}
@Override
protected void doStop() {
super.doStop();
this.connectionFactory.stop();
}
@Override
public boolean onMessage(Message<?> message) {
this.convertAndSend(message);
return false;
}
}

View File

@@ -0,0 +1,67 @@
/*
* Copyright 2002-2013 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* 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.syslog.inbound;
import org.springframework.integration.Message;
import org.springframework.integration.MessagingException;
import org.springframework.integration.channel.DirectChannel;
import org.springframework.integration.core.MessageHandler;
import org.springframework.integration.ip.udp.UnicastReceivingChannelAdapter;
/**
* UDP implementation of a syslog inbound channel adapter.
*
* @author Gary Russell
* @since 3.0
*
*/
public class UdpSyslogReceivingChannelAdapter extends SyslogReceivingChannelAdapterSupport {
private volatile UnicastReceivingChannelAdapter udpAdapter;
public void setUdpAdapter(UnicastReceivingChannelAdapter udpAdpter) {
this.udpAdapter = udpAdpter;
}
@Override
protected void onInit() {
if (this.udpAdapter == null) {
this.udpAdapter = new UnicastReceivingChannelAdapter(this.getPort());
}
DirectChannel outputChannel = new DirectChannel();
outputChannel.subscribe(new MessageHandler() {
@Override
public void handleMessage(Message<?> message) throws MessagingException {
convertAndSend(message);
}
});
this.udpAdapter.setOutputChannel(outputChannel);
}
@Override
protected void doStart() {
super.doStart();
this.udpAdapter.start();
}
@Override
protected void doStop() {
super.doStop();
this.udpAdapter.stop();
}
}

View File

@@ -0,0 +1,4 @@
/**
* Provides classes for inbound endpoints.
*/
package org.springframework.integration.syslog.inbound;

View File

@@ -0,0 +1,4 @@
/**
* Base package for Syslog Support.
*/
package org.springframework.integration.syslog;

View File

@@ -0,0 +1 @@
http\://www.springframework.org/schema/integration/syslog=org.springframework.integration.syslog.config.SyslogNamespaceHandler

View File

@@ -0,0 +1,2 @@
http\://www.springframework.org/schema/integration/syslog/spring-integration-syslog-3.0.xsd=org/springframework/integration/syslog/config/spring-integration-syslog-3.0.xsd
http\://www.springframework.org/schema/integration/syslog/spring-integration-syslog.xsd=org/springframework/integration/syslog/config/spring-integration-syslog-3.0.xsd

View File

@@ -0,0 +1,4 @@
# Tooling related information for the integration syslog namespace
http\://www.springframework.org/schema/integration/syslog@name=integration syslog Namespace
http\://www.springframework.org/schema/integration/syslog@prefix=int-syslog
http\://www.springframework.org/schema/integration/syslog@icon=org/springframework/integration/syslog/config/spring-integration-syslog.gif

View File

@@ -0,0 +1,114 @@
<?xml version="1.0" encoding="UTF-8"?>
<xsd:schema xmlns="http://www.springframework.org/schema/integration/ip"
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"
xmlns:int-ip="http://www.springframework.org/schema/integration/ip"
targetNamespace="http://www.springframework.org/schema/integration/syslog"
elementFormDefault="qualified"
attributeFormDefault="unqualified">
<xsd:import namespace="http://www.springframework.org/schema/beans"/>
<xsd:import namespace="http://www.springframework.org/schema/tool"/>
<xsd:import namespace="http://www.springframework.org/schema/integration"
schemaLocation="http://www.springframework.org/schema/integration/spring-integration-3.0.xsd"/>
<xsd:import namespace="http://www.springframework.org/schema/integration/ip"
schemaLocation="http://www.springframework.org/schema/integration/ip/spring-integration-ip-3.0.xsd"/>
<xsd:annotation>
<xsd:documentation><![CDATA[
Defines the configuration elements for Spring Integration's Syslog adapters.
]]></xsd:documentation>
</xsd:annotation>
<xsd:element name="inbound-channel-adapter">
<xsd:complexType>
<xsd:complexContent>
<xsd:extension base="int-ip:smartLifeCycleType">
<xsd:sequence minOccurs="0" maxOccurs="1">
<xsd:element name="udp-attributes" type="int-ip:udpInboundAdapterType"/>
</xsd:sequence>
<xsd:attribute name="id" type="xsd:string"/>
<xsd:attribute name="connection-factory" type="xsd:string">
<xsd:annotation>
<xsd:appinfo>
<tool:annotation kind="ref">
<tool:expected-type type="org.springframework.integration.ip.tcp.connection.AbstractServerConnectionFactory"/>
</tool:annotation>
</xsd:appinfo>
<xsd:documentation>
An explicit tcp connection factory; requires protocol="tcp" and incompatible with the 'port' attribute.
Use this if you want to set advanced configuration options on the factory. The default factory uses
NIO.
</xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="channel" type="xsd:string">
<xsd:annotation>
<xsd:appinfo>
<tool:annotation kind="ref">
<tool:expected-type type="org.springframework.integration.MessageChannel"/>
</tool:annotation>
</xsd:appinfo>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="error-channel" type="xsd:string">
<xsd:annotation>
<xsd:appinfo>
<tool:annotation kind="ref">
<tool:expected-type type="org.springframework.integration.MessageChannel"/>
</tool:annotation>
</xsd:appinfo>
<xsd:documentation>
If a (synchronous) downstream exception is thrown and an "error-channel" is specified,
the MessagingException will be sent to this channel. Otherwise, any such exception
will simply be logged by the channel adapter.
</xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="protocol" type="xsd:string" use="optional" default="udp">
<xsd:annotation>
<xsd:documentation>
The protocol used to listen for syslog packets, 'udp' or 'tcp'. Default
is 'udp'.
</xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="port" type="xsd:string" use="optional">
<xsd:annotation>
<xsd:documentation>
The port on which this adapter listens for syslog packets. Default is 514. This is
standard for UDP, but no standard is esablished for TCP - in many cases 514 is
used for TCP, but 514 is actually allocated to another protocol.
</xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="converter" type="xsd:string" use="optional">
<xsd:annotation>
<xsd:appinfo>
<tool:annotation kind="ref">
<tool:expected-type type="org.springframework.integration.syslog.MessageConverter"/>
</tool:annotation>
</xsd:appinfo>
<xsd:documentation>
A converter used to map the UDP/TCP message to a Spring Integration message.
Default is DefaultSyslogMessageConverter.
</xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="send-timeout" type="xsd:string" use="optional">
<xsd:annotation>
<xsd:documentation>
A timeout (milliseconds) when sending messages to 'channel' or 'error-channel'. Only
applies if the send might block - such as when sending to a bounded QueueChannel that
is currently full. Default is infinity.
</xsd:documentation>
</xsd:annotation>
</xsd:attribute>
</xsd:extension>
</xsd:complexContent>
</xsd:complexType>
</xsd:element>
</xsd:schema>

View File

@@ -0,0 +1,62 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:int="http://www.springframework.org/schema/integration"
xmlns:int-ip="http://www.springframework.org/schema/integration/ip"
xmlns:int-syslog="http://www.springframework.org/schema/integration/syslog"
xsi:schemaLocation="http://www.springframework.org/schema/integration/ip http://www.springframework.org/schema/integration/ip/spring-integration-ip.xsd
http://www.springframework.org/schema/integration/syslog http://www.springframework.org/schema/integration/syslog/spring-integration-syslog.xsd
http://www.springframework.org/schema/integration http://www.springframework.org/schema/integration/spring-integration.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="socketUtils" class="org.springframework.integration.test.util.SocketUtils" />
<int-syslog:inbound-channel-adapter id="foo" port="#{socketUtils.findAvailableUdpSocket(1514)}" />
<int-syslog:inbound-channel-adapter id="foobar" channel="foo" port="1514" auto-startup="false" />
<int:channel id="foo">
<int:queue/>
</int:channel>
<int:channel id="errors">
<int:queue/>
</int:channel>
<int-syslog:inbound-channel-adapter id="explicitUdp" protocol="udp" port="1514" auto-startup="false" />
<int:channel id="explicitUdp">
<int:queue/>
</int:channel>
<int-syslog:inbound-channel-adapter id="fullBoatUdp"
channel="foo"
auto-startup="false"
phase="123"
converter="converter"
send-timeout="456"
error-channel="errors">
<int-syslog:udp-attributes port="1514" lookup-host="false" />
</int-syslog:inbound-channel-adapter>
<bean id="converter"
class="org.springframework.integration.syslog.config.SyslogReceivingChannelAdapterParserTests$PassThruConverter" />
<int-syslog:inbound-channel-adapter id="bar" protocol="tcp" port="#{socketUtils.findAvailableServerSocket(1514)}" />
<int:channel id="bar">
<int:queue/>
</int:channel>
<int-syslog:inbound-channel-adapter id="fullBoatTcp"
protocol="tcp"
channel="bar"
connection-factory="cf"
auto-startup="false"
phase="123"
converter="converter"
send-timeout="456"
error-channel="errors" />
<int-ip:tcp-connection-factory id="cf" type="server" port="1514" />
</beans>

View File

@@ -0,0 +1,29 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:int="http://www.springframework.org/schema/integration"
xmlns:int-ip="http://www.springframework.org/schema/integration/ip"
xmlns:int-syslog="http://www.springframework.org/schema/integration/syslog"
xsi:schemaLocation="http://www.springframework.org/schema/integration/ip http://www.springframework.org/schema/integration/ip/spring-integration-ip.xsd
http://www.springframework.org/schema/integration/syslog http://www.springframework.org/schema/integration/syslog/spring-integration-syslog.xsd
http://www.springframework.org/schema/integration http://www.springframework.org/schema/integration/spring-integration.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<int:channel id="foo">
<int:queue/>
</int:channel>
<int:channel id="errors">
<int:queue/>
</int:channel>
<int-syslog:inbound-channel-adapter id="fullBoatUdp"
port="1514"
channel="foo"
auto-startup="false"
phase="123"
error-channel="errors">
<int-syslog:udp-attributes port="1514" lookup-host="false" />
</int-syslog:inbound-channel-adapter>
</beans>

View File

@@ -0,0 +1,29 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:int="http://www.springframework.org/schema/integration"
xmlns:int-ip="http://www.springframework.org/schema/integration/ip"
xmlns:int-syslog="http://www.springframework.org/schema/integration/syslog"
xsi:schemaLocation="http://www.springframework.org/schema/integration/ip http://www.springframework.org/schema/integration/ip/spring-integration-ip.xsd
http://www.springframework.org/schema/integration/syslog http://www.springframework.org/schema/integration/syslog/spring-integration-syslog.xsd
http://www.springframework.org/schema/integration http://www.springframework.org/schema/integration/spring-integration.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<int:channel id="foo">
<int:queue/>
</int:channel>
<int:channel id="errors">
<int:queue/>
</int:channel>
<int-syslog:inbound-channel-adapter id="fullBoatTcp"
protocol="tcp"
port="1514"
channel="foo"
connection-factory="cf"
error-channel="errors" />
<int-ip:tcp-connection-factory id="cf" type="server" port="1514" />
</beans>

View File

@@ -0,0 +1,29 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:int="http://www.springframework.org/schema/integration"
xmlns:int-ip="http://www.springframework.org/schema/integration/ip"
xmlns:int-syslog="http://www.springframework.org/schema/integration/syslog"
xsi:schemaLocation="http://www.springframework.org/schema/integration/ip http://www.springframework.org/schema/integration/ip/spring-integration-ip.xsd
http://www.springframework.org/schema/integration/syslog http://www.springframework.org/schema/integration/syslog/spring-integration-syslog.xsd
http://www.springframework.org/schema/integration http://www.springframework.org/schema/integration/spring-integration.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<int:channel id="foo">
<int:queue/>
</int:channel>
<int:channel id="errors">
<int:queue/>
</int:channel>
<int-syslog:inbound-channel-adapter id="fullBoatUdp"
protocol="tcp"
channel="foo"
auto-startup="false"
phase="123"
error-channel="errors">
<int-syslog:udp-attributes port="1514" lookup-host="false" />
</int-syslog:inbound-channel-adapter>
</beans>

View File

@@ -0,0 +1,28 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:int="http://www.springframework.org/schema/integration"
xmlns:int-ip="http://www.springframework.org/schema/integration/ip"
xmlns:int-syslog="http://www.springframework.org/schema/integration/syslog"
xsi:schemaLocation="http://www.springframework.org/schema/integration/ip http://www.springframework.org/schema/integration/ip/spring-integration-ip.xsd
http://www.springframework.org/schema/integration/syslog http://www.springframework.org/schema/integration/syslog/spring-integration-syslog.xsd
http://www.springframework.org/schema/integration http://www.springframework.org/schema/integration/spring-integration.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<int:channel id="foo">
<int:queue/>
</int:channel>
<int:channel id="errors">
<int:queue/>
</int:channel>
<int-syslog:inbound-channel-adapter id="fullBoatTcp"
port="1514"
channel="foo"
connection-factory="cf"
error-channel="errors" />
<int-ip:tcp-connection-factory id="cf" type="server" port="1514" />
</beans>

View File

@@ -0,0 +1,208 @@
/*
* Copyright 2002-2013 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* 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.syslog.config;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetSocketAddress;
import java.net.Socket;
import javax.net.SocketFactory;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.BeanCreationException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.parsing.BeanDefinitionParsingException;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.integration.Message;
import org.springframework.integration.core.PollableChannel;
import org.springframework.integration.ip.tcp.connection.AbstractServerConnectionFactory;
import org.springframework.integration.syslog.MessageConverter;
import org.springframework.integration.syslog.inbound.TcpSyslogReceivingChannelAdapter;
import org.springframework.integration.syslog.inbound.UdpSyslogReceivingChannelAdapter;
import org.springframework.integration.test.util.TestUtils;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
/**
* @author Gary Russell
* @since 3.0
*
*/
@ContextConfiguration
@RunWith(SpringJUnit4ClassRunner.class)
public class SyslogReceivingChannelAdapterParserTests {
@Autowired @Qualifier("foo.adapter")
private UdpSyslogReceivingChannelAdapter adapter1;
@Autowired
private UdpSyslogReceivingChannelAdapter foobar;
@Autowired
private PollableChannel foo;
@Autowired @Qualifier("explicitUdp.adapter")
private UdpSyslogReceivingChannelAdapter explicitUdpAdapter;
@Autowired
private PollableChannel explicitUdp;
@Autowired
private PollableChannel errors;
@Autowired
private UdpSyslogReceivingChannelAdapter fullBoatUdp;
@Autowired
private PassThruConverter converter;
@Autowired @Qualifier("bar.adapter")
private TcpSyslogReceivingChannelAdapter adapter2;
@Autowired
private PollableChannel bar;
@Autowired
private TcpSyslogReceivingChannelAdapter fullBoatTcp;
@Autowired
private AbstractServerConnectionFactory cf;
@Test
public void testSimplestUdp() throws Exception {
int port = TestUtils.getPropertyValue(adapter1, "udpAdapter.port", Integer.class);
byte[] buf = "<157>JUL 26 22:08:35 WEBERN TESTING[70729]: TEST SYSLOG MESSAGE".getBytes("UTF-8");
DatagramPacket packet = new DatagramPacket(buf, buf.length, new InetSocketAddress("localhost", port));
DatagramSocket socket = new DatagramSocket();
Thread.sleep(1000);
socket.send(packet);
socket.close();
Message<?> message = foo.receive(10000);
assertNotNull(message);
adapter1.stop();
}
@Test
public void testExplicitChannelUdp() throws Exception {
assertEquals(1514, TestUtils.getPropertyValue(foobar, "udpAdapter.port"));
assertSame(foo, TestUtils.getPropertyValue(foobar, "outputChannel"));
}
@Test
public void testExplicitUdp() throws Exception {
assertSame(explicitUdp, TestUtils.getPropertyValue(explicitUdpAdapter, "outputChannel"));
}
@Test
public void testFullBoatUdp() {
assertSame(foo, TestUtils.getPropertyValue(fullBoatUdp, "outputChannel"));
assertFalse(fullBoatUdp.isAutoStartup());
assertEquals(123, fullBoatUdp.getPhase());
assertEquals(456L, TestUtils.getPropertyValue(fullBoatUdp, "messagingTemplate.sendTimeout"));
assertSame(converter, TestUtils.getPropertyValue(fullBoatUdp, "converter"));
assertSame(errors, TestUtils.getPropertyValue(fullBoatUdp, "errorChannel"));
assertFalse(TestUtils.getPropertyValue(fullBoatUdp, "udpAdapter.mapper.lookupHost", Boolean.class));
}
@Test
public void testSimplestTcp() throws Exception {
byte[] buf = "<157>JUL 26 22:08:35 WEBERN TESTING[70729]: TEST SYSLOG MESSAGE\n".getBytes("UTF-8");
Socket socket = SocketFactory.getDefault().createSocket("localhost", 1514);
Thread.sleep(1000);
socket.getOutputStream().write(buf);
socket.close();
Message<?> message = bar.receive(10000);
assertNotNull(message);
adapter2.stop();
}
@Test
public void testFullBoatTcp() {
assertSame(bar, TestUtils.getPropertyValue(fullBoatTcp, "outputChannel"));
assertFalse(fullBoatTcp.isAutoStartup());
assertEquals(123, fullBoatTcp.getPhase());
assertEquals(456L, TestUtils.getPropertyValue(fullBoatUdp, "messagingTemplate.sendTimeout"));
assertSame(converter, TestUtils.getPropertyValue(fullBoatTcp, "converter"));
assertSame(errors, TestUtils.getPropertyValue(fullBoatTcp, "errorChannel"));
assertSame(cf, TestUtils.getPropertyValue(fullBoatTcp, "connectionFactory"));
}
@Test
public void testPortOnUdpChild() {
try {
new ClassPathXmlApplicationContext(this.getClass().getSimpleName() + "-fail1-context.xml", this.getClass());
fail("Expected exception");
}
catch (BeanDefinitionParsingException e) {
assertTrue(e.getMessage().startsWith(
"Configuration problem: When child element 'udp-attributes' is present, 'port' must be defined there"));
}
}
@Test
public void testPortWithTCPFactory() {
try {
new ClassPathXmlApplicationContext(this.getClass().getSimpleName() + "-fail2-context.xml", this.getClass());
fail("Expected exception");
}
catch (BeanCreationException e) {
assertEquals("Cannot specify both 'port' and 'connectionFactory'", e.getCause().getMessage());
}
}
@Test
public void testUdpChildWithTcp() {
try {
new ClassPathXmlApplicationContext(this.getClass().getSimpleName() + "-fail3-context.xml", this.getClass());
fail("Expected exception");
}
catch (BeanCreationException e) {
e.printStackTrace();
assertEquals("Cannot specifiy 'udp-attributes' when the protocol is 'tcp'", e.getCause().getMessage());
}
}
@Test
public void testUDPWithTCPFactory() {
try {
new ClassPathXmlApplicationContext(this.getClass().getSimpleName() + "-fail4-context.xml", this.getClass());
fail("Expected exception");
}
catch (BeanCreationException e) {
assertEquals("Cannot specifiy 'connection-factory' unless the protocol is 'tcp'", e.getCause().getMessage());
}
}
public static class PassThruConverter implements MessageConverter {
@Override
public Message<?> fromSyslog(Message<?> syslog) throws Exception {
return syslog;
}
}
}

View File

@@ -0,0 +1,82 @@
/*
* Copyright 2002-2013 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* 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.syslog.inbound;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetSocketAddress;
import java.net.Socket;
import javax.net.SocketFactory;
import org.junit.Test;
import org.springframework.integration.Message;
import org.springframework.integration.channel.QueueChannel;
import org.springframework.integration.core.PollableChannel;
import org.springframework.integration.syslog.config.SyslogReceivingChannelAdapterFactoryBean;
/**
* @author Gary Russell
* @since 3.0
*
*/
public class SyslogReceivingChannelAdapterTests {
@Test
public void testUdp() throws Exception {
SyslogReceivingChannelAdapterFactoryBean factory = new SyslogReceivingChannelAdapterFactoryBean(
SyslogReceivingChannelAdapterFactoryBean.Protocol.udp);
factory.setPort(1514);
PollableChannel outputChannel = new QueueChannel();
factory.setOutputChannel(outputChannel);
factory.afterPropertiesSet();
factory.start();
UdpSyslogReceivingChannelAdapter adapter = (UdpSyslogReceivingChannelAdapter) factory.getObject();
Thread.sleep(1000);
byte[] buf = "<157>JUL 26 22:08:35 WEBERN TESTING[70729]: TEST SYSLOG MESSAGE".getBytes("UTF-8");
DatagramPacket packet = new DatagramPacket(buf, buf.length, new InetSocketAddress("localhost", 1514));
DatagramSocket socket = new DatagramSocket();
socket.send(packet);
socket.close();
Message<?> message = outputChannel.receive(10000);
assertNotNull(message);
assertEquals("WEBERN", message.getHeaders().get("syslog_HOST"));
}
@Test
public void testTcp() throws Exception {
SyslogReceivingChannelAdapterFactoryBean factory = new SyslogReceivingChannelAdapterFactoryBean(
SyslogReceivingChannelAdapterFactoryBean.Protocol.tcp);
factory.setPort(1514);
PollableChannel outputChannel = new QueueChannel();
factory.setOutputChannel(outputChannel);
factory.afterPropertiesSet();
factory.start();
TcpSyslogReceivingChannelAdapter adapter = (TcpSyslogReceivingChannelAdapter) factory.getObject();
Thread.sleep(1000);
byte[] buf = "<157>JUL 26 22:08:35 WEBERN TESTING[70729]: TEST SYSLOG MESSAGE\n".getBytes("UTF-8");
Socket socket = SocketFactory.getDefault().createSocket("localhost", 1514);
socket.getOutputStream().write(buf);
socket.close();
Message<?> message = outputChannel.receive(10000);
assertNotNull(message);
assertEquals("WEBERN", message.getHeaders().get("syslog_HOST"));
}
}

View File

@@ -150,6 +150,7 @@
<xi:include href="./rmi.xml"/>
<xi:include href="./sftp.xml"/>
<xi:include href="./stream.xml"/>
<xi:include href="./syslog.xml"/>
<xi:include href="./twitter.xml"/>
<xi:include href="./ws.xml"/>
<xi:include href="./xml.xml"/>

View File

@@ -0,0 +1,92 @@
<?xml version="1.0" encoding="UTF-8"?>
<chapter xmlns="http://docbook.org/ns/docbook" version="5.0" xml:id="syslog"
xmlns:xlink="http://www.w3.org/1999/xlink">
<title>Syslog Support</title>
<section id="syslog-intro">
<title>Introduction</title>
<para>
Spring Integration 2.2 introduced the Syslog transformer
<classname>SyslogToMapTransformer</classname>. This transformer, together with
a <code>UDP</code> or <code>TCP</code> inbound adapter could be used to receive
and analyze syslog records from other hosts. The transformer creates a message
payload containing a map of the elements from the syslog message.
</para>
<para>
Spring Integration 3.0 introduced convenient namespace support for configuring a
Syslog inbound adapter in a single element.
</para>
</section>
<section id="syslog-inbound-adapter">
<title>Syslog &lt;inbound-channel-adapter&gt;</title>
<para>
This element encompases a <code>UDP</code> or <code>TCP</code> inbound channel adapter
and a <interfacename>MessageConverter</interfacename> to convert the Syslog message to
a Spring Integration message. The <classname>DefaultMessageConverter</classname> delegates
to the <classname>SyslogToMapTransformer</classname>, creating a message with its payload
being the <code>Map</code> of Syslog fields. In addition, all fields except the message
are also made available as headers in the message, prefixed with <code>syslog_</code>.
</para>
<section id="syslog-inbound-examplers">
<title>Example Configuration</title>
<programlisting language="xml"><![CDATA[<int-syslog:inbound-channel-adapter id="syslogIn" port="1514" />]]></programlisting>
<para>
A <code>UDP</code> adapter that sends messages to channel <code>syslogIn</code> (the adapter bean
name is <code>syslogIn.adapter</code>). The adapter listens on port <code>1514</code>.
</para>
<programlisting language="xml"><![CDATA[<int-syslog:inbound-channel-adapter id="syslogIn"
channel="fromSyslog" port="1514" />]]></programlisting>
<para>
A <code>UDP</code> adapter that sends message to channel <code>fromSyslog</code> (the adapter bean
name is <code>syslogIn</code>). The adapter listens on port <code>1514</code>.
</para>
<programlisting language="xml"><![CDATA[<int-syslog:inbound-channel-adapter id="bar" protocol="tcp" port="1514" />]]></programlisting>
<para>
A <code>TCP</code> adapter that sends messages to channel <code>syslogIn</code> (the adapter bean
name is <code>syslogIn.adapter</code>). The adapter listens on port <code>1514</code>.
</para>
<para>
Note the addition of the <code>protocol</code> attribute. This attribute can contain <code>udp</code>
or <code>tcp</code>; it defaults to <code>udp</code>.
</para>
<programlisting language="xml"><![CDATA[<int-syslog:inbound-channel-adapter id="udpSyslog"
channel="fromSyslog"
auto-startup="false"
phase="10000"
converter="converter"
send-timeout="1000"
error-channel="errors">
<int-syslog:udp-attributes port="1514" lookup-host="false" />
</int-syslog:inbound-channel-adapter>]]></programlisting>
<para>
A <code>UDP</code> adapter that sends messages to channel <code>fromSyslog</code>. It also shows the
<interfacename>SmartLifecyle</interfacename> attributes <code>auto-startup</code> and
<code>phase</code>. It has a reference to a custom <interfacename>
org.springframework.integration.syslog.MessageConverter</interfacename>
with id <code>converter</code> and an <code>error-channel</code>. Also notice the
<code>udp-attributes</code> child element. You can set various UDP attributes here, as defined
in <xref linkend="ip-ib-adapter-attributes"/>.
</para>
<note>
When using the <code>udp-attributes</code> element, the <code>port</code> attribute must be
provided there rather than on the <code>inbound-channel-adapter</code> element itself.
</note>
<programlisting language="xml"><![CDATA[<int-syslog:inbound-channel-adapter id="TcpSyslog"
protocol="tcp"
channel="fromSyslog"
connection-factory="cf" />
<int-ip:tcp-connection-factory id="cf" type="server" port="1514" />]]></programlisting>
<para>
A <code>TCP</code> adapter that sends messages to channel <code>fromSyslog</code>. It also shows
how to reference an externally defined connection factory, which can be used for advanced
configuration (socket keep alive etc). For more information, see <xref linkend="connection-factories"/>.
</para>
<note>
The externally configured <code>connection-factory</code> must be of type <code>server</code> and,
the port is defined there rather than on the <code>inbound-channel-adapter</code> element itself.
</note>
</section>
</section>
</chapter>

View File

@@ -50,6 +50,16 @@
For more information see <xref linkend="tcp-events"/>.
</para>
</section>
<section id="3.0-syslog">
<title>Syslog Support</title>
<para>
Building on the 2.2 <classname>SyslogToMapTransformer</classname> Spring
Integration 3.0 now introduces
<code>UDP</code> and <code>TCP</code> inbound channel adapters especially tailored
for receiving SYSLOG messages. For more information, see
<xref linkend="syslog"/>.
</para>
</section>
</section>
<section id="3.0-general">