initial commit of my work to make building filesystem based adapters more consistent, cleaner.

This commit is contained in:
Josh Long
2010-08-20 10:06:13 +00:00
parent 59e4b98d39
commit 25b5afa528
151 changed files with 3351 additions and 1767 deletions

View File

@@ -1,52 +1,52 @@
/*
* 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.aggregator;
import org.springframework.integration.store.MessageGroup;
/**
* A {@link ReleaseStrategy} that releases only the first <code>n</code> messages, where <code>n</code> is a threshold.
*
* @author Dave Syer
*
*/
public class MessageCountReleaseStrategy implements ReleaseStrategy {
private final int threshold;
/**
* @param threshold the number of messages to accept before releasing
*/
public MessageCountReleaseStrategy(int threshold) {
super();
this.threshold = threshold;
}
/**
* Convenient constructor is only one message is required (threshold=1).
*/
public MessageCountReleaseStrategy() {
this(1);
}
/**
* Release the group if it has more messages than the threshold and has not previously been released. Previous
* releases leave an imprint on the group in the form of marked messages. It is possible that more messages than the
* threshold could be released, but only if multiple consumers receive messages from the same group concurrently.
*/
public boolean canRelease(MessageGroup group) {
return group.size() >= threshold && group.getMarked().size() == 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.aggregator;
import org.springframework.integration.store.MessageGroup;
/**
* A {@link ReleaseStrategy} that releases only the first <code>n</code> messages, where <code>n</code> is a threshold.
*
* @author Dave Syer
*
*/
public class MessageCountReleaseStrategy implements ReleaseStrategy {
private final int threshold;
/**
* @param threshold the number of messages to accept before releasing
*/
public MessageCountReleaseStrategy(int threshold) {
super();
this.threshold = threshold;
}
/**
* Convenient constructor is only one message is required (threshold=1).
*/
public MessageCountReleaseStrategy() {
this(1);
}
/**
* Release the group if it has more messages than the threshold and has not previously been released. Previous
* releases leave an imprint on the group in the form of marked messages. It is possible that more messages than the
* threshold could be released, but only if multiple consumers receive messages from the same group concurrently.
*/
public boolean canRelease(MessageGroup group) {
return group.size() >= threshold && group.getMarked().size() == 0;
}
}

View File

@@ -1,192 +1,192 @@
/*
* 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.dispatcher;
import java.util.Collection;
import java.util.Comparator;
import java.util.LinkedHashSet;
import java.util.Set;
import java.util.concurrent.locks.ReentrantReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock.ReadLock;
import java.util.concurrent.locks.ReentrantReadWriteLock.WriteLock;
import org.springframework.core.OrderComparator;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
/**
* Special Set that maintains the following semantics:
* All elements that are un-ordered (do not implement {@link Ordered} interface or annotated
* {@link Order} annotation) will be stored in the order in which they were added, maintaining the
* semantics of the {@link LinkedHashSet}. However, for all {@link Ordered} elements a
* {@link Comparator} (instantiated by default) for this implementation of {@link Set}, will be
* used. Those elements will have precedence over un-ordered elements. If elements have the same
* order but themselves do not equal to one another the more recent addition will be placed to the
* right of (appended next to) the existing element with the same order, thus preserving the order
* of the insertion and maintaining {@link LinkedHashSet} semantics for the un-ordered elements.
* <p>
* The class is package-protected and only intended for use by the AbstractDispatcher. It
* <emphasis>must</emphasis> enforce safe concurrent access for all usage by the dispatcher.
*
* @author Oleg Zhurakousky
* @author Mark Fisher
* @since 1.0.3
*/
@SuppressWarnings({"unchecked", "serial"})
class OrderedAwareLinkedHashSet<E> extends LinkedHashSet<E> {
private final OrderComparator comparator = new OrderComparator();
private final ReentrantReadWriteLock rwl = new ReentrantReadWriteLock();
private final ReadLock readLock = rwl.readLock();
private final WriteLock writeLock = rwl.writeLock();
/**
* Every time an Ordered element is added via this method this
* Set will be re-sorted, otherwise the element is simply added
* to the end. Added element must not be null.
*/
public boolean add(E o) {
Assert.notNull(o,"Can not add NULL object");
writeLock.lock();
try {
boolean present = false;
if (o instanceof Ordered){
present = this.addOrderedElement((Ordered) o);
}
else {
present = super.add(o);
}
return present;
}
finally {
writeLock.unlock();
}
}
/**
* Adds all elements in this Collection.
*/
public boolean addAll(Collection<? extends E> c) {
Assert.notNull(c,"Can not merge with NULL set");
writeLock.lock();
try {
for (E object : c) {
this.add(object);
}
return true;
}
finally {
writeLock.unlock();
}
}
/**
* {@inheritDoc}
*/
public boolean remove(Object o) {
writeLock.lock();
try {
return super.remove(o);
}
finally {
writeLock.unlock();
}
}
/**
* {@inheritDoc}
*/
public boolean removeAll(Collection<?> c){
if (CollectionUtils.isEmpty(c)){
return false;
}
writeLock.lock();
try {
return super.removeAll(c);
}
finally {
writeLock.unlock();
}
}
@Override
public <T> T[] toArray(T[] a) {
readLock.lock();
try {
return super.toArray(a);
}
finally {
readLock.unlock();
}
}
@Override
public String toString() {
readLock.lock();
try {
return StringUtils.collectionToCommaDelimitedString(this);
}
finally {
readLock.unlock();
}
}
private boolean addOrderedElement(Ordered adding) {
boolean added = false;
E[] tempUnorderedElements = (E[]) this.toArray();
if (super.contains(adding)) {
return false;
}
super.clear();
if (tempUnorderedElements.length == 0) {
added = super.add((E) adding);
}
else {
Set tempSet = new LinkedHashSet();
for (E current : tempUnorderedElements) {
if (current instanceof Ordered) {
if (this.comparator.compare(adding, current) < 0) {
added = super.add((E) adding);
super.add(current);
}
else {
super.add(current);
}
}
else {
tempSet.add(current);
}
}
if (!added) {
added = super.add((E) adding);
}
for (Object object : tempSet) {
super.add((E) object);
}
}
return added;
}
}
/*
* 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.dispatcher;
import java.util.Collection;
import java.util.Comparator;
import java.util.LinkedHashSet;
import java.util.Set;
import java.util.concurrent.locks.ReentrantReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock.ReadLock;
import java.util.concurrent.locks.ReentrantReadWriteLock.WriteLock;
import org.springframework.core.OrderComparator;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
/**
* Special Set that maintains the following semantics:
* All elements that are un-ordered (do not implement {@link Ordered} interface or annotated
* {@link Order} annotation) will be stored in the order in which they were added, maintaining the
* semantics of the {@link LinkedHashSet}. However, for all {@link Ordered} elements a
* {@link Comparator} (instantiated by default) for this implementation of {@link Set}, will be
* used. Those elements will have precedence over un-ordered elements. If elements have the same
* order but themselves do not equal to one another the more recent addition will be placed to the
* right of (appended next to) the existing element with the same order, thus preserving the order
* of the insertion and maintaining {@link LinkedHashSet} semantics for the un-ordered elements.
* <p>
* The class is package-protected and only intended for use by the AbstractDispatcher. It
* <emphasis>must</emphasis> enforce safe concurrent access for all usage by the dispatcher.
*
* @author Oleg Zhurakousky
* @author Mark Fisher
* @since 1.0.3
*/
@SuppressWarnings({"unchecked", "serial"})
class OrderedAwareLinkedHashSet<E> extends LinkedHashSet<E> {
private final OrderComparator comparator = new OrderComparator();
private final ReentrantReadWriteLock rwl = new ReentrantReadWriteLock();
private final ReadLock readLock = rwl.readLock();
private final WriteLock writeLock = rwl.writeLock();
/**
* Every time an Ordered element is added via this method this
* Set will be re-sorted, otherwise the element is simply added
* to the end. Added element must not be null.
*/
public boolean add(E o) {
Assert.notNull(o,"Can not add NULL object");
writeLock.lock();
try {
boolean present = false;
if (o instanceof Ordered){
present = this.addOrderedElement((Ordered) o);
}
else {
present = super.add(o);
}
return present;
}
finally {
writeLock.unlock();
}
}
/**
* Adds all elements in this Collection.
*/
public boolean addAll(Collection<? extends E> c) {
Assert.notNull(c,"Can not merge with NULL set");
writeLock.lock();
try {
for (E object : c) {
this.add(object);
}
return true;
}
finally {
writeLock.unlock();
}
}
/**
* {@inheritDoc}
*/
public boolean remove(Object o) {
writeLock.lock();
try {
return super.remove(o);
}
finally {
writeLock.unlock();
}
}
/**
* {@inheritDoc}
*/
public boolean removeAll(Collection<?> c){
if (CollectionUtils.isEmpty(c)){
return false;
}
writeLock.lock();
try {
return super.removeAll(c);
}
finally {
writeLock.unlock();
}
}
@Override
public <T> T[] toArray(T[] a) {
readLock.lock();
try {
return super.toArray(a);
}
finally {
readLock.unlock();
}
}
@Override
public String toString() {
readLock.lock();
try {
return StringUtils.collectionToCommaDelimitedString(this);
}
finally {
readLock.unlock();
}
}
private boolean addOrderedElement(Ordered adding) {
boolean added = false;
E[] tempUnorderedElements = (E[]) this.toArray();
if (super.contains(adding)) {
return false;
}
super.clear();
if (tempUnorderedElements.length == 0) {
added = super.add((E) adding);
}
else {
Set tempSet = new LinkedHashSet();
for (E current : tempUnorderedElements) {
if (current instanceof Ordered) {
if (this.comparator.compare(adding, current) < 0) {
added = super.add((E) adding);
super.add(current);
}
else {
super.add(current);
}
}
else {
tempSet.add(current);
}
}
if (!added) {
added = super.add((E) adding);
}
for (Object object : tempSet) {
super.add((E) object);
}
}
return added;
}
}

View File

@@ -1,93 +1,93 @@
/*
* 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.store;
import java.util.Collection;
import java.util.Iterator;
import java.util.LinkedHashSet;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
/**
* @author Dave Syer
*
* @since 2.0
*
*/
public abstract class AbstractMessageGroupStore implements MessageGroupStore, Iterable<MessageGroup> {
protected final Log logger = LogFactory.getLog(getClass());
private Collection<MessageGroupCallback> expiryCallbacks = new LinkedHashSet<MessageGroupCallback>();
/**
*
*/
public AbstractMessageGroupStore() {
super();
}
/**
* Convenient injection point for expiry callbacks in the message store. Each of the callbacks provided will simply
* be registered with the store using {@link #registerMessageGroupExpiryCallback(MessageGroupCallback)}.
*
* @param expiryCallbacks the expiry callbacks to add
*/
public void setExpiryCallbacks(Collection<MessageGroupCallback> expiryCallbacks) {
for (MessageGroupCallback callback : expiryCallbacks) {
registerMessageGroupExpiryCallback(callback);
}
}
public void registerMessageGroupExpiryCallback(MessageGroupCallback callback) {
expiryCallbacks.add(callback);
}
public int expireMessageGroups(long timeout) {
int count = 0;
long threshold = System.currentTimeMillis() - timeout;
for (MessageGroup group : this) {
if (group.getTimestamp() < threshold) {
count++;
expire(group);
}
}
return count;
}
public abstract Iterator<MessageGroup> iterator();
private void expire(MessageGroup group) {
RuntimeException exception = null;
for (MessageGroupCallback callback : expiryCallbacks) {
try {
callback.execute(this, group);
} catch (RuntimeException e) {
if (exception == null) {
exception = e;
}
logger.error("Exception in expiry callback", e);
}
}
if (exception != null) {
throw exception;
}
}
/*
* 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.store;
import java.util.Collection;
import java.util.Iterator;
import java.util.LinkedHashSet;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
/**
* @author Dave Syer
*
* @since 2.0
*
*/
public abstract class AbstractMessageGroupStore implements MessageGroupStore, Iterable<MessageGroup> {
protected final Log logger = LogFactory.getLog(getClass());
private Collection<MessageGroupCallback> expiryCallbacks = new LinkedHashSet<MessageGroupCallback>();
/**
*
*/
public AbstractMessageGroupStore() {
super();
}
/**
* Convenient injection point for expiry callbacks in the message store. Each of the callbacks provided will simply
* be registered with the store using {@link #registerMessageGroupExpiryCallback(MessageGroupCallback)}.
*
* @param expiryCallbacks the expiry callbacks to add
*/
public void setExpiryCallbacks(Collection<MessageGroupCallback> expiryCallbacks) {
for (MessageGroupCallback callback : expiryCallbacks) {
registerMessageGroupExpiryCallback(callback);
}
}
public void registerMessageGroupExpiryCallback(MessageGroupCallback callback) {
expiryCallbacks.add(callback);
}
public int expireMessageGroups(long timeout) {
int count = 0;
long threshold = System.currentTimeMillis() - timeout;
for (MessageGroup group : this) {
if (group.getTimestamp() < threshold) {
count++;
expire(group);
}
}
return count;
}
public abstract Iterator<MessageGroup> iterator();
private void expire(MessageGroup group) {
RuntimeException exception = null;
for (MessageGroupCallback callback : expiryCallbacks) {
try {
callback.execute(this, group);
} catch (RuntimeException e) {
if (exception == null) {
exception = e;
}
logger.error("Exception in expiry callback", e);
}
}
if (exception != null) {
throw exception;
}
}
}

View File

@@ -1,26 +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.store;
/**
* @author Dave Syer
*
* @since 2.0
*
*/
public interface MessageGroupCallback {
void execute(MessageGroupStore messageGroupStore, MessageGroup group);
}
/*
* 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.store;
/**
* @author Dave Syer
*
* @since 2.0
*
*/
public interface MessageGroupCallback {
void execute(MessageGroupStore messageGroupStore, MessageGroup group);
}

View File

@@ -1,100 +1,100 @@
/*
* 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.store;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.context.ApplicationContext;
import org.springframework.util.Assert;
/**
* Convenient configurable component to allow explicit timed expiry of {@link MessageGroup} instances in a
* {@link MessageGroupStore}. This component provides a no-args {@link #run()} method that is useful for remote or timed
* execution and a {@link #destroy()} method that can optionally be called on shutdown.
*
* @author Dave Syer
*
*/
public class MessageGroupStoreReaper implements Runnable, DisposableBean, InitializingBean {
private static Log logger = LogFactory.getLog(MessageGroupStoreReaper.class);
private MessageGroupStore messageGroupStore;
private boolean expireOnDestroy = false;
private long timeout = -1;
public MessageGroupStoreReaper(MessageGroupStore messageGroupStore) {
this.messageGroupStore = messageGroupStore;
}
public MessageGroupStoreReaper() {
}
/**
* Flag to indicate that the stores should be expired when this component is destroyed (i.e. usuually when its
* enclosing {@link ApplicationContext} is closed).
*
* @param expireOnDestroy the flag value to set
*/
public void setExpireOnDestroy(boolean expireOnDestroy) {
this.expireOnDestroy = expireOnDestroy;
}
/**
* Timeout in milliseconds (default -1). If negative then no groups ever time out. If greater than zero then all
* groups older than that value are expired when this component is {@link #run()}.
*
* @param timeout the timeout to set
*/
public void setTimeout(long timeout) {
this.timeout = timeout;
}
/**
* A message group store to expire according the the other configurations.
*
* @param messageGroupStore the {@link MessageGroupStore} to set
*/
public void setMessageGroupStore(MessageGroupStore messageGroupStore) {
this.messageGroupStore = messageGroupStore;
}
public void afterPropertiesSet() throws Exception {
Assert.state(messageGroupStore != null, "A MessageGroupStore must be provided");
}
public void destroy() throws Exception {
if (expireOnDestroy) {
logger.info("Expiring all messages from message group store: " + messageGroupStore);
messageGroupStore.expireMessageGroups(0);
}
}
/**
* Expire all message groups older than the {@link #setTimeout(long) timeout} provided. Normally this method would
* be executed by a scheduled task.
*/
public void run() {
if (timeout >= 0) {
if (logger.isDebugEnabled()) {
logger.debug("Expiring all messages older than timeout=" + timeout + " from message group store: "
+ messageGroupStore);
}
messageGroupStore.expireMessageGroups(timeout);
}
}
}
/*
* 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.store;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.context.ApplicationContext;
import org.springframework.util.Assert;
/**
* Convenient configurable component to allow explicit timed expiry of {@link MessageGroup} instances in a
* {@link MessageGroupStore}. This component provides a no-args {@link #run()} method that is useful for remote or timed
* execution and a {@link #destroy()} method that can optionally be called on shutdown.
*
* @author Dave Syer
*
*/
public class MessageGroupStoreReaper implements Runnable, DisposableBean, InitializingBean {
private static Log logger = LogFactory.getLog(MessageGroupStoreReaper.class);
private MessageGroupStore messageGroupStore;
private boolean expireOnDestroy = false;
private long timeout = -1;
public MessageGroupStoreReaper(MessageGroupStore messageGroupStore) {
this.messageGroupStore = messageGroupStore;
}
public MessageGroupStoreReaper() {
}
/**
* Flag to indicate that the stores should be expired when this component is destroyed (i.e. usuually when its
* enclosing {@link ApplicationContext} is closed).
*
* @param expireOnDestroy the flag value to set
*/
public void setExpireOnDestroy(boolean expireOnDestroy) {
this.expireOnDestroy = expireOnDestroy;
}
/**
* Timeout in milliseconds (default -1). If negative then no groups ever time out. If greater than zero then all
* groups older than that value are expired when this component is {@link #run()}.
*
* @param timeout the timeout to set
*/
public void setTimeout(long timeout) {
this.timeout = timeout;
}
/**
* A message group store to expire according the the other configurations.
*
* @param messageGroupStore the {@link MessageGroupStore} to set
*/
public void setMessageGroupStore(MessageGroupStore messageGroupStore) {
this.messageGroupStore = messageGroupStore;
}
public void afterPropertiesSet() throws Exception {
Assert.state(messageGroupStore != null, "A MessageGroupStore must be provided");
}
public void destroy() throws Exception {
if (expireOnDestroy) {
logger.info("Expiring all messages from message group store: " + messageGroupStore);
messageGroupStore.expireMessageGroups(0);
}
}
/**
* Expire all message groups older than the {@link #setTimeout(long) timeout} provided. Normally this method would
* be executed by a scheduled task.
*/
public void run() {
if (timeout >= 0) {
if (logger.isDebugEnabled()) {
logger.debug("Expiring all messages older than timeout=" + timeout + " from message group store: "
+ messageGroupStore);
}
messageGroupStore.expireMessageGroups(timeout);
}
}
}

View File

@@ -1,80 +1,80 @@
/*
* 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.aggregator.integration;
import static org.junit.Assert.assertTrue;
import java.util.List;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.integration.Message;
import org.springframework.integration.annotation.Aggregator;
import org.springframework.integration.annotation.CorrelationStrategy;
import org.springframework.integration.annotation.ReleaseStrategy;
import org.springframework.integration.channel.DirectChannel;
import org.springframework.integration.core.MessageBuilder;
import org.springframework.integration.core.PollableChannel;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
/**
* @author Mark Fisher
*/
@ContextConfiguration
@RunWith(SpringJUnit4ClassRunner.class)
public class AnnotationAggregatorTests {
@Autowired
DirectChannel input;
@Autowired
PollableChannel output;
@Test
public void testAggregationWithAnnotationStrategies() {
input.send(MessageBuilder.withPayload("a").build());
input.send(MessageBuilder.withPayload("b").build());
@SuppressWarnings("unchecked")
Message<String> result = (Message<String>) output.receive();
String payload = result.getPayload();
assertTrue("Wrong payload: "+payload, payload.contains("Payload=a"));
assertTrue("Wrong payload: "+payload, payload.contains("Payload=b"));
}
@SuppressWarnings("unused")
private static class TestAggregator {
@Aggregator
public Message<?> aggregate(final List<Message<?>> messages) {
return MessageBuilder.withPayload(messages.toString()).build();
}
@ReleaseStrategy
public boolean release(final List<Message<?>> messages) {
return messages.size()>1;
}
@CorrelationStrategy
public Object getKey(Message<?> message) {
return "1";
}
}
}
/*
* 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.aggregator.integration;
import static org.junit.Assert.assertTrue;
import java.util.List;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.integration.Message;
import org.springframework.integration.annotation.Aggregator;
import org.springframework.integration.annotation.CorrelationStrategy;
import org.springframework.integration.annotation.ReleaseStrategy;
import org.springframework.integration.channel.DirectChannel;
import org.springframework.integration.core.MessageBuilder;
import org.springframework.integration.core.PollableChannel;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
/**
* @author Mark Fisher
*/
@ContextConfiguration
@RunWith(SpringJUnit4ClassRunner.class)
public class AnnotationAggregatorTests {
@Autowired
DirectChannel input;
@Autowired
PollableChannel output;
@Test
public void testAggregationWithAnnotationStrategies() {
input.send(MessageBuilder.withPayload("a").build());
input.send(MessageBuilder.withPayload("b").build());
@SuppressWarnings("unchecked")
Message<String> result = (Message<String>) output.receive();
String payload = result.getPayload();
assertTrue("Wrong payload: "+payload, payload.contains("Payload=a"));
assertTrue("Wrong payload: "+payload, payload.contains("Payload=b"));
}
@SuppressWarnings("unused")
private static class TestAggregator {
@Aggregator
public Message<?> aggregate(final List<Message<?>> messages) {
return MessageBuilder.withPayload(messages.toString()).build();
}
@ReleaseStrategy
public boolean release(final List<Message<?>> messages) {
return messages.size()>1;
}
@CorrelationStrategy
public Object getKey(Message<?> message) {
return "1";
}
}
}

View File

@@ -1,28 +1,28 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns:beans="http://www.springframework.org/schema/beans"
xmlns="http://www.springframework.org/schema/integration"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="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">
<channel id="pojoOutput">
<queue/>
</channel>
<channel id="defaultOutput">
<queue/>
</channel>
<splitter input-channel="pojoInput" output-channel="pojoAggregator"/>
<aggregator input-channel="pojoAggregator" output-channel="pojoOutput" method="aggregate">
<beans:bean class="org.springframework.integration.aggregator.integration.MethodInvokingAggregatorReturningMessageTests$TestAggregator"/>
</aggregator>
<splitter input-channel="defaultInput" output-channel="defaultAggregator"/>
<aggregator input-channel="defaultAggregator" output-channel="defaultOutput"/>
<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns:beans="http://www.springframework.org/schema/beans"
xmlns="http://www.springframework.org/schema/integration"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="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">
<channel id="pojoOutput">
<queue/>
</channel>
<channel id="defaultOutput">
<queue/>
</channel>
<splitter input-channel="pojoInput" output-channel="pojoAggregator"/>
<aggregator input-channel="pojoAggregator" output-channel="pojoOutput" method="aggregate">
<beans:bean class="org.springframework.integration.aggregator.integration.MethodInvokingAggregatorReturningMessageTests$TestAggregator"/>
</aggregator>
<splitter input-channel="defaultInput" output-channel="defaultAggregator"/>
<aggregator input-channel="defaultAggregator" output-channel="defaultOutput"/>
</beans:beans>

View File

@@ -1,11 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/integration"
<beans:beans xmlns="http://www.springframework.org/schema/integration"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:beans="http://www.springframework.org/schema/beans"
xsi:schemaLocation="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/spring-integration.xsd">
<transformer id="transformer"
input-channel="input"

View File

@@ -1,14 +1,14 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/integration"
<beans:beans xmlns="http://www.springframework.org/schema/integration"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/integration
http://www.springframework.org/schema/integration/spring-integration.xsd">
http://www.springframework.org/schema/integration/spring-integration.xsd">
<context:property-placeholder
location="/org/springframework/integration/channel/config/ChannelCapacityPlaceholderTests.properties"/>

View File

@@ -7,7 +7,7 @@
http://www.springframework.org/schema/integration/spring-integration.xsd">
<channel id="dispatcherAttribute" dispatcher="failover"/>
<channel id="taskExecutorOnly">
<dispatcher task-executor="taskExecutor"/>
</channel>

View File

@@ -1,11 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/integration"
<beans:beans xmlns="http://www.springframework.org/schema/integration"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:beans="http://www.springframework.org/schema/beans"
xsi:schemaLocation="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/spring-integration.xsd">
<channel id="channelWithInterceptorRef">
<queue capacity="5"/>
@@ -26,5 +26,5 @@
</channel>
<beans:bean id="interceptor" class="org.springframework.integration.config.TestChannelInterceptor"/>
</beans:beans>

View File

@@ -11,7 +11,7 @@
</channel>
<channel id="defaultChannel" />
<channel id="channelWithFailoverAttribute" dispatcher="failover"/>
<channel id="channelWithCustomQueue">

View File

@@ -1,11 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:integration="http://www.springframework.org/schema/integration"
xmlns:integration="http://www.springframework.org/schema/integration"
xsi:schemaLocation="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/spring-integration.xsd">
<integration:channel/>

View File

@@ -1,11 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/integration"
<beans:beans xmlns="http://www.springframework.org/schema/integration"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:beans="http://www.springframework.org/schema/beans"
xsi:schemaLocation="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/spring-integration.xsd">
<channel id="priorityChannelWithDefaultComparator">
<priority-queue capacity="10"/>
@@ -21,5 +21,5 @@
<beans:bean id="payloadComparator"
class="org.springframework.integration.channel.MessagePayloadTestComparator"/>
</beans:beans>

View File

@@ -1,11 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/integration"
<beans:beans xmlns="http://www.springframework.org/schema/integration"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:beans="http://www.springframework.org/schema/beans"
xsi:schemaLocation="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/spring-integration.xsd">
<channel id="channel">
<rendezvous-queue/>

View File

@@ -1,11 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/integration"
<beans:beans xmlns="http://www.springframework.org/schema/integration"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:beans="http://www.springframework.org/schema/beans"
xsi:schemaLocation="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/spring-integration.xsd">
<channel id="channel"/>

View File

@@ -1,23 +1,23 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/integration"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:beans="http://www.springframework.org/schema/beans"
xsi:schemaLocation="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">
<channel id="output">
<queue capacity="5" />
</channel>
<channel id="input" />
<aggregator id="aggregator" ref="aggregatorBean"
input-channel="input" output-channel="output" message-store="messageStore" send-partial-result-on-expiry="true"/>
<beans:bean id="messageStore" class="org.springframework.integration.store.SimpleMessageStore"/>
<beans:bean id="aggregatorBean"
class="org.springframework.integration.config.TestAggregatorBean" />
</beans:beans>
<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/integration"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:beans="http://www.springframework.org/schema/beans"
xsi:schemaLocation="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">
<channel id="output">
<queue capacity="5" />
</channel>
<channel id="input" />
<aggregator id="aggregator" ref="aggregatorBean"
input-channel="input" output-channel="output" message-store="messageStore" send-partial-result-on-expiry="true"/>
<beans:bean id="messageStore" class="org.springframework.integration.store.SimpleMessageStore"/>
<beans:bean id="aggregatorBean"
class="org.springframework.integration.config.TestAggregatorBean" />
</beans:beans>

View File

@@ -1,12 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/integration"
<beans:beans xmlns="http://www.springframework.org/schema/integration"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:beans="http://www.springframework.org/schema/beans"
xsi:schemaLocation="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">
<channel id="queueChannel">
<queue capacity="1"/>
</channel>
@@ -24,5 +24,5 @@
<beans:bean id="consumer" class="org.springframework.integration.config.TestConsumer"/>
<beans:bean id="testBean" class="org.springframework.integration.config.TestBean"/>
</beans:beans>

View File

@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/integration"
<beans:beans xmlns="http://www.springframework.org/schema/integration"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:beans="http://www.springframework.org/schema/beans"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/integration

View File

@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/integration"
<beans:beans xmlns="http://www.springframework.org/schema/integration"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:beans="http://www.springframework.org/schema/beans"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/integration

View File

@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/integration"
<beans:beans xmlns="http://www.springframework.org/schema/integration"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:beans="http://www.springframework.org/schema/beans"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/integration

View File

@@ -1,73 +1,73 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/integration"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:beans="http://www.springframework.org/schema/beans"
xsi:schemaLocation="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">
<channel id="outputChannel">
<queue capacity="5"/>
</channel>
<channel id="discardChannel">
<queue capacity="5"/>
</channel>
<channel id="aggregatorWithReferenceInput"/>
<aggregator id="aggregatorWithReference" ref="aggregatorBean"
input-channel="aggregatorWithReferenceInput" output-channel="outputChannel"/>
<channel id="completelyDefinedAggregatorInput"/>
<aggregator id="completelyDefinedAggregator"
input-channel="completelyDefinedAggregatorInput"
output-channel="outputChannel"
discard-channel="discardChannel"
ref="aggregatorBean"
release-strategy="releaseStrategy"
correlation-strategy="correlationStrategy"
send-timeout="86420000"
send-partial-result-on-expiry="true"/>
<channel id="aggregatorWithExpressionsInput"/>
<channel id="aggregatorWithExpressionsOutput"/>
<aggregator id="aggregatorWithExpressions"
input-channel="aggregatorWithExpressionsInput"
output-channel="aggregatorWithExpressionsOutput"
expression="?[payload.startsWith('1')].![payload]"
release-strategy-expression="#root.size()>2"
correlation-strategy-expression="headers['foo']"/>
<channel id="aggregatorWithReferenceAndMethodInput"/>
<aggregator id="aggregatorWithReferenceAndMethod"
ref="adderBean"
method="add"
input-channel="aggregatorWithReferenceAndMethodInput"
output-channel="outputChannel"/>
<channel id="aggregatorWithPojoReleaseStrategyInput"/>
<aggregator id="aggregatorWithPojoReleaseStrategy"
input-channel="aggregatorWithPojoReleaseStrategyInput"
output-channel="outputChannel"
ref="adderBean"
method="add"
release-strategy="pojoReleaseStrategy"
release-strategy-method="checkCompleteness"/>
<beans:bean id="aggregatorBean"
class="org.springframework.integration.config.TestAggregatorBean" />
<beans:bean id="adderBean"
class="org.springframework.integration.config.Adder" />
<beans:bean id="releaseStrategy"
class="org.springframework.integration.config.TestReleaseStrategy" />
<beans:bean id="correlationStrategy" class="org.springframework.integration.config.TestCorrelationStrategy"/>
<beans:bean id="pojoReleaseStrategy"
class="org.springframework.integration.config.MaxValueReleaseStrategy">
<beans:constructor-arg value="10" />
</beans:bean>
</beans:beans>
<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/integration"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:beans="http://www.springframework.org/schema/beans"
xsi:schemaLocation="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">
<channel id="outputChannel">
<queue capacity="5"/>
</channel>
<channel id="discardChannel">
<queue capacity="5"/>
</channel>
<channel id="aggregatorWithReferenceInput"/>
<aggregator id="aggregatorWithReference" ref="aggregatorBean"
input-channel="aggregatorWithReferenceInput" output-channel="outputChannel"/>
<channel id="completelyDefinedAggregatorInput"/>
<aggregator id="completelyDefinedAggregator"
input-channel="completelyDefinedAggregatorInput"
output-channel="outputChannel"
discard-channel="discardChannel"
ref="aggregatorBean"
release-strategy="releaseStrategy"
correlation-strategy="correlationStrategy"
send-timeout="86420000"
send-partial-result-on-expiry="true"/>
<channel id="aggregatorWithExpressionsInput"/>
<channel id="aggregatorWithExpressionsOutput"/>
<aggregator id="aggregatorWithExpressions"
input-channel="aggregatorWithExpressionsInput"
output-channel="aggregatorWithExpressionsOutput"
expression="?[payload.startsWith('1')].![payload]"
release-strategy-expression="#root.size()>2"
correlation-strategy-expression="headers['foo']"/>
<channel id="aggregatorWithReferenceAndMethodInput"/>
<aggregator id="aggregatorWithReferenceAndMethod"
ref="adderBean"
method="add"
input-channel="aggregatorWithReferenceAndMethodInput"
output-channel="outputChannel"/>
<channel id="aggregatorWithPojoReleaseStrategyInput"/>
<aggregator id="aggregatorWithPojoReleaseStrategy"
input-channel="aggregatorWithPojoReleaseStrategyInput"
output-channel="outputChannel"
ref="adderBean"
method="add"
release-strategy="pojoReleaseStrategy"
release-strategy-method="checkCompleteness"/>
<beans:bean id="aggregatorBean"
class="org.springframework.integration.config.TestAggregatorBean" />
<beans:bean id="adderBean"
class="org.springframework.integration.config.Adder" />
<beans:bean id="releaseStrategy"
class="org.springframework.integration.config.TestReleaseStrategy" />
<beans:bean id="correlationStrategy" class="org.springframework.integration.config.TestCorrelationStrategy"/>
<beans:bean id="pojoReleaseStrategy"
class="org.springframework.integration.config.MaxValueReleaseStrategy">
<beans:constructor-arg value="10" />
</beans:bean>
</beans:beans>

View File

@@ -1,11 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/integration"
<beans:beans xmlns="http://www.springframework.org/schema/integration"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:beans="http://www.springframework.org/schema/beans"
xsi:schemaLocation="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/spring-integration.xsd">
<annotation-config/>

View File

@@ -1,11 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:integration="http://www.springframework.org/schema/integration"
xmlns:integration="http://www.springframework.org/schema/integration"
xsi:schemaLocation="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/spring-integration.xsd">
<integration:annotation-config/>

View File

@@ -1,11 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/integration"
<beans:beans xmlns="http://www.springframework.org/schema/integration"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:beans="http://www.springframework.org/schema/beans"
xsi:schemaLocation="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/spring-integration.xsd">
<annotation-config/>

View File

@@ -1,11 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:integration="http://www.springframework.org/schema/integration"
xmlns:integration="http://www.springframework.org/schema/integration"
xsi:schemaLocation="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/spring-integration.xsd">
<integration:annotation-config/>

View File

@@ -1,11 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:integration="http://www.springframework.org/schema/integration"
xmlns:integration="http://www.springframework.org/schema/integration"
xsi:schemaLocation="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/spring-integration.xsd">
<integration:annotation-config/>

View File

@@ -1,11 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/integration"
<beans:beans xmlns="http://www.springframework.org/schema/integration"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:beans="http://www.springframework.org/schema/beans"
xsi:schemaLocation="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/spring-integration.xsd">
<application-event-multicaster/>

View File

@@ -1,11 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/integration"
<beans:beans xmlns="http://www.springframework.org/schema/integration"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:beans="http://www.springframework.org/schema/beans"
xsi:schemaLocation="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/spring-integration.xsd">
<channel id="test"/>

View File

@@ -1,11 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/integration"
<beans:beans xmlns="http://www.springframework.org/schema/integration"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:beans="http://www.springframework.org/schema/beans"
xsi:schemaLocation="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/spring-integration.xsd">
<channel id="errorChannel"/>

View File

@@ -1,11 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/integration"
<beans:beans xmlns="http://www.springframework.org/schema/integration"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:beans="http://www.springframework.org/schema/beans"
xsi:schemaLocation="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/spring-integration.xsd">
<channel id="test"/>

View File

@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/integration"
<beans:beans xmlns="http://www.springframework.org/schema/integration"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:beans="http://www.springframework.org/schema/beans"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/integration

View File

@@ -1,12 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/integration"
<beans:beans xmlns="http://www.springframework.org/schema/integration"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:beans="http://www.springframework.org/schema/beans"
xsi:schemaLocation="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">
<channel id="testChannel">
<queue capacity="50"/>
</channel>
@@ -20,5 +20,5 @@
<beans:bean id="testHandler" class="org.springframework.integration.config.TestHandler">
<beans:constructor-arg value="1"/>
</beans:bean>
</beans:beans>

View File

@@ -1,11 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/integration"
<beans:beans xmlns="http://www.springframework.org/schema/integration"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:beans="http://www.springframework.org/schema/beans"
xsi:schemaLocation="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/spring-integration.xsd">
<header-enricher input-channel="input" ref="testBean" method="enrich">
<header name="other" value="zzz"/>

View File

@@ -1,11 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/integration"
<beans:beans xmlns="http://www.springframework.org/schema/integration"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:beans="http://www.springframework.org/schema/beans"
xsi:schemaLocation="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/spring-integration.xsd">
<header-filter input-channel="input" header-names="a,d, c"/>

View File

@@ -1,11 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/integration"
<beans:beans xmlns="http://www.springframework.org/schema/integration"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:beans="http://www.springframework.org/schema/beans"
xsi:schemaLocation="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/spring-integration.xsd">
<beans:bean id="abstractParent" class="org.springframework.integration.config.xml.NestedChainParserTests$ParentTestBean" abstract="true">
<beans:property name="chain">

View File

@@ -1,11 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/integration"
<beans:beans xmlns="http://www.springframework.org/schema/integration"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:beans="http://www.springframework.org/schema/beans"
xsi:schemaLocation="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/spring-integration.xsd">
<channel id="directInput"/>

View File

@@ -1,11 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/integration"
<beans:beans xmlns="http://www.springframework.org/schema/integration"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:beans="http://www.springframework.org/schema/beans"
xsi:schemaLocation="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/spring-integration.xsd">
<channel id="directInput"/>

View File

@@ -1,11 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/integration"
<beans:beans xmlns="http://www.springframework.org/schema/integration"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:beans="http://www.springframework.org/schema/beans"
xsi:schemaLocation="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/spring-integration.xsd">
<channel id="directInput"/>

View File

@@ -1,11 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/integration"
<beans:beans xmlns="http://www.springframework.org/schema/integration"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:beans="http://www.springframework.org/schema/beans"
xsi:schemaLocation="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/spring-integration.xsd">
<poller id="defaultPollerWithId" default="true">
<interval-trigger interval="5000"/>

View File

@@ -1,11 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/integration"
<beans:beans xmlns="http://www.springframework.org/schema/integration"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:beans="http://www.springframework.org/schema/beans"
xsi:schemaLocation="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/spring-integration.xsd">
<poller default="true">
<interval-trigger interval="5000"/>

View File

@@ -1,11 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/integration"
<beans:beans xmlns="http://www.springframework.org/schema/integration"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:beans="http://www.springframework.org/schema/beans"
xsi:schemaLocation="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/spring-integration.xsd">
<channel id="requestChannel">
<queue capacity="100"/>

View File

@@ -1,11 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/integration"
<beans:beans xmlns="http://www.springframework.org/schema/integration"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:beans="http://www.springframework.org/schema/beans"
xsi:schemaLocation="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/spring-integration.xsd">
<poller id="defaultPoller1" default="true">
<interval-trigger interval="3000"/>

View File

@@ -1,11 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/integration"
<beans:beans xmlns="http://www.springframework.org/schema/integration"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:beans="http://www.springframework.org/schema/beans"
xsi:schemaLocation="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/spring-integration.xsd">
<poller id="poller">
<interval-trigger interval="5000"/>

View File

@@ -1,11 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/integration"
<beans:beans xmlns="http://www.springframework.org/schema/integration"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:beans="http://www.springframework.org/schema/beans"
xsi:schemaLocation="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/spring-integration.xsd">
<poller id="poller" receive-timeout="1234">
<interval-trigger interval="5" time-unit="SECONDS"/>

View File

@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/integration"
<beans:beans xmlns="http://www.springframework.org/schema/integration"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:beans="http://www.springframework.org/schema/beans"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/integration

View File

@@ -1,11 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/integration"
<beans:beans xmlns="http://www.springframework.org/schema/integration"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:beans="http://www.springframework.org/schema/beans"
xsi:schemaLocation="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/spring-integration.xsd">
<channel id="input">
<queue capacity="1"/>
@@ -33,5 +33,5 @@
<beans:bean id="testBean" class="org.springframework.integration.dispatcher.TestBean"/>
<beans:bean id="txManager" class="org.springframework.integration.util.TestTransactionManager"/>
</beans:beans>

View File

@@ -1,11 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/integration"
<beans:beans xmlns="http://www.springframework.org/schema/integration"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:beans="http://www.springframework.org/schema/beans"
xsi:schemaLocation="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/spring-integration.xsd">
<channel id="input">
<queue capacity="1"/>
@@ -29,5 +29,5 @@
<beans:bean id="testBean" class="org.springframework.integration.dispatcher.TestBean"/>
<beans:bean id="txManager" class="org.springframework.integration.util.TestTransactionManager"/>
</beans:beans>

View File

@@ -1,11 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/integration"
<beans:beans xmlns="http://www.springframework.org/schema/integration"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:beans="http://www.springframework.org/schema/beans"
xsi:schemaLocation="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/spring-integration.xsd">
<channel id="input">
<queue capacity="1"/>
@@ -28,6 +28,6 @@
<beans:bean id="testBean" class="org.springframework.integration.dispatcher.TestBean"/>
<beans:bean id="txManager" class="org.springframework.integration.util.TestTransactionManager"/>
<beans:bean id="txManager" class="org.springframework.integration.util.TestTransactionManager"/>
</beans:beans>

View File

@@ -1,11 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/integration"
<beans:beans xmlns="http://www.springframework.org/schema/integration"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:beans="http://www.springframework.org/schema/beans"
xsi:schemaLocation="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/spring-integration.xsd">
<channel id="input">
<queue capacity="1"/>
@@ -29,5 +29,5 @@
<beans:bean id="testBean" class="org.springframework.integration.dispatcher.TestBean"/>
<beans:bean id="txManager" class="org.springframework.integration.util.TestTransactionManager"/>
</beans:beans>

View File

@@ -1,11 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/integration"
<beans:beans xmlns="http://www.springframework.org/schema/integration"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:beans="http://www.springframework.org/schema/beans"
xsi:schemaLocation="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/spring-integration.xsd">
<channel id="input">
<queue capacity="1"/>
@@ -29,5 +29,5 @@
<beans:bean id="testBean" class="org.springframework.integration.dispatcher.TestBean"/>
<beans:bean id="txManager" class="org.springframework.integration.util.TestTransactionManager"/>
</beans:beans>

View File

@@ -1,11 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/integration"
<beans:beans xmlns="http://www.springframework.org/schema/integration"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:beans="http://www.springframework.org/schema/beans"
xsi:schemaLocation="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/spring-integration.xsd">
<channel id="badInput">
<queue capacity="1"/>
@@ -42,5 +42,5 @@
<beans:bean id="testBean" class="org.springframework.integration.dispatcher.TestBean"/>
<beans:bean id="txManager" class="org.springframework.integration.util.TestTransactionManager"/>
</beans:beans>

View File

@@ -5,7 +5,7 @@
xmlns:task="http://www.springframework.org/schema/task"
xsi:schemaLocation="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
http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task.xsd">
http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task.xsd">
<si:channel id="errorChannel">
<si:queue capacity="10"/>
@@ -15,6 +15,6 @@
<property name="taskExecutor" ref="taskExecutor"/>
</bean>
<task:executor id="taskExecutor" pool-size="1" rejection-policy="CALLER_RUNS"/>
<task:executor id="taskExecutor" pool-size="1" rejection-policy="CALLER_RUNS"/>
</beans>

View File

@@ -1,11 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:si="http://www.springframework.org/schema/integration"
xmlns:si="http://www.springframework.org/schema/integration"
xsi:schemaLocation="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/spring-integration.xsd">
<si:poller id="poller" default="true">
<si:interval-trigger interval="50"/>
@@ -30,5 +30,5 @@
<si:service-activator input-channel="channel4" ref="testBean" method="duplicate" output-channel="replyChannel"/>
<bean id="testBean" class="org.springframework.integration.endpoint.TestBean"/>
</beans>

View File

@@ -1,12 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/integration"
<beans:beans xmlns="http://www.springframework.org/schema/integration"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:beans="http://www.springframework.org/schema/beans"
xsi:schemaLocation="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">
<channel id="input"/>
<channel id="output">
@@ -19,5 +19,5 @@
output-channel="output"/>
<beans:bean id="testBean" class="org.springframework.integration.filter.TestBean"/>
</beans:beans>

View File

@@ -7,7 +7,7 @@
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd">
<context:annotation-config/>
<context:annotation-config/>
<beans:bean id="testClient" class="org.springframework.integration.gateway.GatewayProxyFactoryBeanTests$TestClient"/>

View File

@@ -1,11 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/integration"
<beans:beans xmlns="http://www.springframework.org/schema/integration"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:beans="http://www.springframework.org/schema/beans"
xsi:schemaLocation="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/spring-integration.xsd">
<channel id="requestChannel"/>

View File

@@ -1,11 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/integration"
<beans:beans xmlns="http://www.springframework.org/schema/integration"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:beans="http://www.springframework.org/schema/beans"
xsi:schemaLocation="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/spring-integration.xsd">
<channel id="requestChannel"/>

View File

@@ -1,11 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/integration"
<beans:beans xmlns="http://www.springframework.org/schema/integration"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:beans="http://www.springframework.org/schema/beans"
xsi:schemaLocation="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/spring-integration.xsd">
<channel id="input"/>

View File

@@ -1,11 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/integration"
<beans:beans xmlns="http://www.springframework.org/schema/integration"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:beans="http://www.springframework.org/schema/beans"
xsi:schemaLocation="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/spring-integration.xsd">
<channel id="numbers"/>
<channel id="splits"/>

View File

@@ -1,11 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/integration"
<beans:beans xmlns="http://www.springframework.org/schema/integration"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:beans="http://www.springframework.org/schema/beans"
xsi:schemaLocation="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/spring-integration.xsd">
<channel id="output">
<queue capacity="10"/>

View File

@@ -1,26 +1,26 @@
<?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:task="http://www.springframework.org/schema/task"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-3.0.xsd">
<bean id="messageStore" class="org.springframework.integration.store.SimpleMessageStore">
<property name="expiryCallbacks">
<bean class="org.springframework.integration.store.MessageStoreReaperTests$ExpiryCallback"/>
</property>
</bean>
<bean id="reaper" class="org.springframework.integration.store.MessageGroupStoreReaper">
<property name="messageGroupStore" ref="messageStore"/>
<property name="timeout" value="10"/>
</bean>
<task:scheduled-tasks scheduler="scheduler">
<task:scheduled ref="reaper" method="run" fixed-rate="100"/>
</task:scheduled-tasks>
<task:scheduler id="scheduler"/>
</beans>
<?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:task="http://www.springframework.org/schema/task"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-3.0.xsd">
<bean id="messageStore" class="org.springframework.integration.store.SimpleMessageStore">
<property name="expiryCallbacks">
<bean class="org.springframework.integration.store.MessageStoreReaperTests$ExpiryCallback"/>
</property>
</bean>
<bean id="reaper" class="org.springframework.integration.store.MessageGroupStoreReaper">
<property name="messageGroupStore" ref="messageStore"/>
<property name="timeout" value="10"/>
</bean>
<task:scheduled-tasks scheduler="scheduler">
<task:scheduled ref="reaper" method="run" fixed-rate="100"/>
</task:scheduled-tasks>
<task:scheduler id="scheduler"/>
</beans>

View File

@@ -1,12 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/integration"
<beans:beans xmlns="http://www.springframework.org/schema/integration"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:beans="http://www.springframework.org/schema/beans"
xsi:schemaLocation="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">
<channel id="input"/>
<channel id="output">
@@ -16,5 +16,5 @@
<transformer input-channel="input" ref="testBean" method="upperCase" output-channel="output"/>
<beans:bean id="testBean" class="org.springframework.integration.transformer.TestBean"/>
</beans:beans>

View File

@@ -0,0 +1,148 @@
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;
/**
* This handles a lot of the common ground in our approach for synchronizing a remote file system locally
*
* @author Josh Long
*/
public abstract class AbstractInboundRemoteFileSystemSychronizer<T> extends AbstractEndpoint {
/**
* Should we <emphasis>delete</emphasis> the <b>source</b> file?
* For an FTP server, for example, this would delete the original FTPFile instance
* <p/>
* At the moment I can simply see this triggering the setting
*/
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 <emphasis>remote</emphasis> file system view!
*/
protected volatile EntryListFilter<T> filter = new AcceptAllEntryListFilter<T>();
/**
* 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<T> entryAcknowledgmentStrategy;
/**
* Obviously thread safe - simply provides a NOOP impl so we don't have to keep dancing around NPE's
*/
private EntryAcknowledgmentStrategy<T> noOpEntryAcknowledgmentStrategy = new EntryAcknowledgmentStrategy<T>() {
public void acknowledge(Object o, T msg) {
}
};
public void setEntryAcknowledgmentStrategy(EntryAcknowledgmentStrategy<T> entryAcknowledgmentStrategy) {
this.entryAcknowledgmentStrategy = entryAcknowledgmentStrategy;
}
public void setShouldDeleteSourceFile(boolean shouldDeleteSourceFile) {
this.shouldDeleteSourceFile = shouldDeleteSourceFile;
}
public void setLocalDirectory(Resource localDirectory) {
this.localDirectory = localDirectory;
}
public void setFilter(EntryListFilter<T> filter) {
this.filter = filter;
}
/**
* @param usefulContextOrClientData
* @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
*/
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
*/
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
*
* @author Josh Long
* @param <T> the entry type (file, sftp, ftp, ...)
*/
public static interface EntryAcknowledgmentStrategy<T> {
/**
* 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) ;
}
}
}
}

View File

@@ -0,0 +1,112 @@
package org.springframework.integration.file;
import org.springframework.core.io.FileSystemResource;
import org.springframework.core.io.Resource;
import org.springframework.integration.Message;
import org.springframework.integration.core.MessageSource;
import org.springframework.integration.endpoint.AbstractEndpoint;
import org.springframework.integration.file.entries.*;
import org.springframework.util.Assert;
import java.io.File;
import java.util.regex.Pattern;
/**
* Ultimately, this factors out a lot of the common logic between the FTP and SFTP adapters
*
* @author Josh Long
*/
public abstract class AbstractInboundRemoteFileSystemSynchronizingMessageSource<Y, T extends AbstractInboundRemoteFileSystemSychronizer<Y>> extends AbstractEndpoint implements MessageSource<File> {
/**
* 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 syncing up the remote FS
*/
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<Y> 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<Y> remotePredicate) {
this.remotePredicate = remotePredicate;
}
private EntryListFilter<File> buildFilter() {
FileEntryNamer fileEntryNamer = new FileEntryNamer();
Pattern completePattern = Pattern.compile("^.*(?<!" + INCOMPLETE_EXTENSION + ")$");
return new CompositeEntryListFilter<File>(new AcceptOnceEntryFileListFilter<File>(), new PatternMatchingEntryListFilter<File>(fileEntryNamer, completePattern));
}
@Override
protected void onInit() throws Exception {
if (this.remotePredicate != null) {
this.synchronizer.setFilter(this.remotePredicate);
}
if (this.autoCreateDirectories) {
if((this.localDirectory != null) && !this.localDirectory.exists() && this.localDirectory.getFile().mkdirs())
logger.debug( "the localDirectory " + this.localDirectory + " doesn't exist");
}
/**
* 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();
}
public Message<File> receive() {
return this.fileSource.receive();
}
}

View File

@@ -13,14 +13,17 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.integration.file;
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.
@@ -29,16 +32,17 @@ import java.util.List;
* @since 2.0
*/
public class DefaultDirectoryScanner implements DirectoryScanner {
private FileListFilter filter = new AcceptOnceFileListFilter();
private EntryListFilter<File> filter = new AcceptOnceEntryFileListFilter<File>();
private FileLocker locker;
public final List<File> 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.");
throw new MessagingException("The path [" + directory + "] does not denote a properly accessible directory.");
}
return this.filter.filterFiles(files);
return this.filter.filterEntries(files);
}
/**
@@ -52,10 +56,7 @@ public class DefaultDirectoryScanner implements DirectoryScanner {
return directory.listFiles();
}
/**
* {@inheritDoc}
*/
public final void setFilter(FileListFilter filter) {
public void setFilter(EntryListFilter<File> filter) {
this.filter = filter;
}
@@ -65,7 +66,7 @@ public class DefaultDirectoryScanner implements DirectoryScanner {
* 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) : true;
return (locker == null) || locker.lock(file);
}
/**

View File

@@ -16,13 +16,15 @@
package org.springframework.integration.file;
import org.springframework.integration.file.entries.EntryListFilter;
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 FileListFilter
* directory like RecursiveDirectoryScanner. If the only requirement is to ignore certain files a EntryListFilter
* implementation should suffice.
*
*
@@ -37,6 +39,7 @@ public interface DirectoryScanner {
*
* @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<File> listFiles(File directory) throws IllegalArgumentException;
@@ -47,7 +50,7 @@ public interface DirectoryScanner {
*
* @param filter the custom filter to be used
*/
void setFilter(FileListFilter filter);
void setFilter(EntryListFilter<File> filter);
/**

View File

@@ -13,33 +13,38 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.integration.file;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.integration.Message;
import org.springframework.integration.MessagingException;
import org.springframework.integration.aggregator.ResequencingMessageGroupProcessor;
import org.springframework.integration.core.MessageBuilder;
import org.springframework.integration.core.MessageSource;
import org.springframework.integration.file.entries.EntryListFilter;
import org.springframework.util.Assert;
import java.io.File;
import java.util.*;
import java.util.concurrent.PriorityBlockingQueue;
/**
* {@link MessageSource} that creates messages from a file system directory. To prevent messages for certain files, you
* may supply a {@link FileListFilter}. By default, an {@link AcceptOnceFileListFilter} is used. It ensures files are
* may supply a {@link org.springframework.integration.file.filters.FileListFilter}. By default, an {@link org.springframework.integration.file.filters.AcceptOnceFileListFilter} is used. It ensures files are
* picked up only once from the directory.
* <p/>
* A common problem with reading files is that a file may be detected before it is ready. The default {@link
* AcceptOnceFileListFilter} does not prevent this. In most cases, this can be prevented if the file-writing process
* org.springframework.integration.file.filters.AcceptOnceFileListFilter} 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 AcceptOnceFileListFilter} would allow for
* this. See {@link org.springframework.integration.file.CompositeFileListFilter} for a way to do this.
* ready (e.g. based on a known suffix), composed with the default {@link org.springframework.integration.file.filters.AcceptOnceFileListFilter} would allow for
* this. See {@link org.springframework.integration.file.filters.CompositeFileListFilter} for a way to do this.
* <p/>
* 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
@@ -51,18 +56,11 @@ import java.util.concurrent.PriorityBlockingQueue;
* @author Iwein Fuld
* @author Mark Fisher
*/
public class FileReadingMessageSource implements MessageSource<File>,
InitializingBean {
public class FileReadingMessageSource implements MessageSource<File>, InitializingBean {
private static final int DEFAULT_INTERNAL_QUEUE_CAPACITY = 5;
private static final Log logger = LogFactory
.getLog(FileReadingMessageSource.class);
private static final Log logger = LogFactory.getLog(FileReadingMessageSource.class);
private volatile File directory;
private volatile DirectoryScanner scanner = new DefaultDirectoryScanner();
private volatile boolean autoCreateDirectory = true;
/*
@@ -70,7 +68,6 @@ public class FileReadingMessageSource implements MessageSource<File>,
* There is no locking around the queue, so there is also no iteration.
*/
private final Queue<File> toBeReceived;
private boolean scanEachPoll = false;
/**
@@ -92,7 +89,7 @@ public class FileReadingMessageSource implements MessageSource<File>,
*/
public FileReadingMessageSource(int internalQueueCapacity) {
this(null);
Assert.isTrue(internalQueueCapacity>0, "Cannot create a queue with non positive capacity");
Assert.isTrue(internalQueueCapacity > 0, "Cannot create a queue with non positive capacity");
this.setScanner(new HeadDirectoryScanner(internalQueueCapacity));
}
@@ -108,8 +105,7 @@ public class FileReadingMessageSource implements MessageSource<File>,
* @param receptionOrderComparator the comparator to be used to order the files in the internal queue
*/
public FileReadingMessageSource(Comparator<File> receptionOrderComparator) {
toBeReceived = new PriorityBlockingQueue<File>(DEFAULT_INTERNAL_QUEUE_CAPACITY,
receptionOrderComparator);
toBeReceived = new PriorityBlockingQueue<File>(DEFAULT_INTERNAL_QUEUE_CAPACITY, receptionOrderComparator);
}
/**
@@ -137,13 +133,13 @@ public class FileReadingMessageSource implements MessageSource<File>,
}
/**
* Sets a {@link FileListFilter}. By default a {@link AcceptOnceFileListFilter} with no bounds is used. In most
* cases a customized {@link FileListFilter} will be needed to deal with modification and duplication concerns. If
* multiple filters are required a {@link CompositeFileListFilter} can be used to group them together.
* Sets a {@link org.springframework.integration.file.filters.FileListFilter}. By default a {@link org.springframework.integration.file.filters.AcceptOnceFileListFilter} with no bounds is used. In most
* cases a customized {@link org.springframework.integration.file.filters.FileListFilter} will be needed to deal with modification and duplication concerns. If
* multiple filters are required a {@link org.springframework.integration.file.filters.CompositeFileListFilter} can be used to group them together.
* <p/>
* <b>The supplied filter must be thread safe.</b>.
*/
public void setFilter(FileListFilter filter) {
public void setFilter(EntryListFilter<File> filter) {
Assert.notNull(filter, "'filter' must not be null");
this.scanner.setFilter(filter);
}
@@ -175,43 +171,50 @@ public class FileReadingMessageSource implements MessageSource<File>,
public final void afterPropertiesSet() {
Assert.notNull(directory, "'directory' must not be set before initialization");
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.");
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<File> receive() throws MessagingException {
Message<File> 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)) {
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<File> filteredFiles = scanner.listFiles(directory);
Set<File> freshFiles = new HashSet<File>(filteredFiles);
if (!freshFiles.isEmpty()) {
toBeReceived.addAll(freshFiles);
if (logger.isDebugEnabled()) {
logger.debug("Added to queue: " + freshFiles);
}
@@ -225,6 +228,7 @@ public class FileReadingMessageSource implements MessageSource<File>,
if (logger.isWarnEnabled()) {
logger.warn("Failed to send: " + failedMessage);
}
toBeReceived.offer(failedMessage.getPayload());
}

View File

@@ -13,13 +13,16 @@
* 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;
import java.io.File;
import java.util.Arrays;
import java.util.List;
/**
* A custom scanner that only returns the first <code>maxNumberOfFiles</code> elements from a directory listing. This is
* useful to limit the number of File objects in memory and therefore mutually exclusive with AcceptOnceFileListFilter.
@@ -28,19 +31,18 @@ import java.util.List;
* @since 2.0.0
*/
public class HeadDirectoryScanner extends DefaultDirectoryScanner {
public HeadDirectoryScanner(int maxNumberOfFiles) {
this.setFilter(new HeadFilter(maxNumberOfFiles));
}
private class HeadFilter implements FileListFilter {
private class HeadFilter implements EntryListFilter<File> {
private final int maxNumberOfFiles;
public HeadFilter(int maxNumberOfFiles) {
this.maxNumberOfFiles = maxNumberOfFiles;
}
public List<File> filterFiles(File[] files) {
public List<File> filterEntries(File[] files) {
return Arrays.asList(files).subList(0, Math.min(files.length, maxNumberOfFiles));
}
}

View File

@@ -13,110 +13,114 @@
* 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;
import org.springframework.integration.file.entries.*;
import java.io.File;
import java.util.Collection;
import java.util.regex.Pattern;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.integration.file.AbstractFileListFilter;
import org.springframework.integration.file.AcceptOnceFileListFilter;
import org.springframework.integration.file.CompositeFileListFilter;
import org.springframework.integration.file.FileListFilter;
import org.springframework.integration.file.PatternMatchingFileListFilter;
/**
* @author Mark Fisher
* @since 1.0.3
*/
public class FileListFilterFactoryBean implements FactoryBean<FileListFilter> {
public class FileListFilterFactoryBean implements FactoryBean<EntryListFilter<File>> {
private volatile EntryListFilter<File> fileListFilter;
private volatile EntryListFilter<File> filterReference;
private volatile Pattern filenamePattern;
private volatile Boolean preventDuplicates;
private final Object monitor = new Object();
private volatile Collection<EntryListFilter<File>> filterReferences;
private FileEntryNamer fileNamer = new FileEntryNamer();
private volatile FileListFilter fileListFilter;
public void setFilterReferences(Collection<EntryListFilter<File>> filterReferences) {
this.filterReferences = filterReferences;
}
private volatile FileListFilter filterReference;
public void setFilterReference(EntryListFilter<File> filterReference) {
this.filterReference = filterReference;
}
private volatile Pattern filenamePattern;
public void setFilenamePattern(Pattern filenamePattern) {
this.filenamePattern = filenamePattern;
}
private volatile Boolean preventDuplicates;
public void setPreventDuplicates(Boolean preventDuplicates) {
this.preventDuplicates = preventDuplicates;
}
private final Object monitor = new Object();
public EntryListFilter<File> getObject() throws Exception {
if (this.fileListFilter == null) {
synchronized (this.monitor) {
this.intializeFileListFilter();
}
}
return this.fileListFilter;
}
public void setFilterReference(FileListFilter filterReference) {
this.filterReference = filterReference;
}
public Class<?> getObjectType() {
return (this.fileListFilter != null) ? this.fileListFilter.getClass() : EntryListFilter.class;
}
public void setFilenamePattern(Pattern filenamePattern) {
this.filenamePattern = filenamePattern;
}
public boolean isSingleton() {
return true;
}
public void setPreventDuplicates(Boolean preventDuplicates) {
this.preventDuplicates = preventDuplicates;
}
private void intializeFileListFilter() {
if (this.fileListFilter != null) {
return;
}
public FileListFilter getObject() throws Exception {
if (this.fileListFilter == null) {
synchronized (this.monitor) {
this.intializeFileListFilter();
}
}
return this.fileListFilter;
}
EntryListFilter<File> flf=null;
public Class<?> getObjectType() {
return (this.fileListFilter != null)
? this.fileListFilter.getClass() : FileListFilter.class;
}
if ((this.filterReference != null) && (this.filenamePattern != null)) {
throw new IllegalArgumentException("The 'filter' reference and " + "'filename-pattern' attributes are mutually exclusive.");
}
public boolean isSingleton() {
return true;
}
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) {
PatternMatchingEntryListFilter<File> patternFilter = new PatternMatchingEntryListFilter<File>(fileNamer, this.filenamePattern);
private void intializeFileListFilter() {
if (this.fileListFilter != null) {
return;
}
FileListFilter flf = null;
if (this.filterReference != null && this.filenamePattern != null) {
throw new IllegalArgumentException("The 'filter' reference and " +
"'filename-pattern' attributes are mutually exclusive.");
}
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) {
PatternMatchingFileListFilter patternFilter = new PatternMatchingFileListFilter(this.filenamePattern);
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 AbstractFileListFilter() {
@Override
protected boolean accept(File file) {
return true;
}
};
}
else { // preventDuplicates is either TRUE or NULL
flf = new AcceptOnceFileListFilter();
}
this.fileListFilter = flf;
}
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<File>();
} else { // preventDuplicates is either TRUE or NULL
flf = new AcceptOnceEntryFileListFilter<File>();
}
private FileListFilter createCompositeWithAcceptOnceFilter(FileListFilter otherFilter) {
CompositeFileListFilter compositeFilter = new CompositeFileListFilter();
compositeFilter.addFilter(new AcceptOnceFileListFilter(), otherFilter);
return compositeFilter;
}
// finally, it might be that they simply want a {@link CompositeEntryListFilter}
if ((this.filterReferences != null) && (this.filterReferences.size() > 0) ) {
CompositeEntryListFilter<File> flfc = new CompositeEntryListFilter<File>();
for (EntryListFilter<File> ff : filterReferences)
flfc.addFilter(ff);
flf = flfc;
}
if( flf== null)flf =new CompositeEntryListFilter<File>();
this.fileListFilter = flf;
}
private CompositeEntryListFilter<File> createCompositeWithAcceptOnceFilter(EntryListFilter<File> otherFilter) {
CompositeEntryListFilter<File> compositeFilter = new CompositeEntryListFilter<File>();
compositeFilter.addFilter(new AcceptOnceEntryFileListFilter<File>(), otherFilter);
return compositeFilter;
}
}

View File

@@ -19,10 +19,10 @@ 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.CompositeFileListFilter;
import org.springframework.integration.file.DirectoryScanner;
import org.springframework.integration.file.FileListFilter;
import org.springframework.integration.file.FileReadingMessageSource;
import org.springframework.integration.file.entries.CompositeEntryListFilter;
import org.springframework.integration.file.entries.EntryListFilter;
import org.springframework.integration.file.locking.AbstractFileLockerFilter;
import java.io.File;
@@ -41,7 +41,7 @@ public class FileReadingMessageSourceFactoryBean implements FactoryBean<FileRead
private volatile File directory;
private volatile FileListFilter filter;
private volatile EntryListFilter<File> filter;
private volatile AbstractFileLockerFilter locker;
@@ -69,7 +69,7 @@ public class FileReadingMessageSourceFactoryBean implements FactoryBean<FileRead
this.scanner = scanner;
}
public void setFilter(FileListFilter filter) {
public void setFilter(EntryListFilter<File> filter) {
if (filter instanceof AbstractFileLockerFilter && this.locker == null) {
this.setLocker((AbstractFileLockerFilter) filter);
}
@@ -133,7 +133,7 @@ public class FileReadingMessageSourceFactoryBean implements FactoryBean<FileRead
if (this.locker == null) {
this.source.setFilter(this.filter);
} else {
this.source.setFilter(new CompositeFileListFilter(this.filter, this.locker));
this.source.setFilter(new CompositeEntryListFilter<File>(this.filter, this.locker));
this.source.setLocker(locker);
}
}

View File

@@ -13,16 +13,26 @@
* 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;
import java.util.ArrayList;
import java.util.List;
public abstract class AbstractEntryListFilter<T> implements EntryListFilter<T> {
protected abstract boolean accept(T t);
/**
* 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
* required for evaluation, implement the {@link EntryListFilter} interface directly.
*
* @author Mark Fisher
* @author Iwein Fuld
* @author Josh Long
*/
public abstract class AbstractEntryListFilter<T> implements InitializingBean, EntryListFilter<T> {
public abstract boolean accept(T t);
public List<T> filterEntries(T[] entries) {
List<T> accepted = new ArrayList<T>();
@@ -37,4 +47,8 @@ public abstract class AbstractEntryListFilter<T> implements EntryListFilter<T> {
return accepted;
}
public void afterPropertiesSet() throws Exception {
// its all you!
}
}

View File

@@ -0,0 +1,32 @@
/*
* 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.file.entries;
/**
* Simple NOOP implementation for {@link org.springframework.integration.file.entries.EntryListFilter} implementation.
* Suitable as a default in implementations.
*
* @author Josh Long
* @param <T>
*/
public class AcceptAllEntryListFilter<T> extends AbstractEntryListFilter<T> {
@Override
public boolean accept(T t) {
return true;
}
}

View File

@@ -13,20 +13,29 @@
* 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
* {@link org.springframework.integration.file.FileReadingMessageSource}.
* <p/>
* This implementation is thread safe.
*
* @author Iwein Fuld
* @since 1.0.0
*/
public class AcceptOnceEntryFileListFilter<T> extends AbstractEntryListFilter<T> {
private final Queue<T> seen;
private final Object monitor = new Object();
/**
* Creates an AcceptOnceFileFilter that is based on a bounded queue. If the
* 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.
*
@@ -44,7 +53,7 @@ public class AcceptOnceEntryFileListFilter<T> extends AbstractEntryListFilter<T>
this.seen = new LinkedBlockingQueue<T>();
}
protected boolean accept(T pathname) {
public boolean accept(T pathname) {
synchronized (this.monitor) {
if (seen.contains(pathname)) {
return false;

View File

@@ -13,32 +13,37 @@
* 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;
import org.springframework.util.Assert;
import java.util.*;
public class CompositeEntryListFilter<T> implements EntryListFilter<T> {
private final Set<EntryListFilter> fileFilters;
private final Set<EntryListFilter<T>> fileFilters;
public CompositeEntryListFilter(EntryListFilter... fileFilters) {
this.fileFilters = new LinkedHashSet<EntryListFilter>(Arrays.asList(fileFilters));
public CompositeEntryListFilter(EntryListFilter<T>... fileFilters) {
this.fileFilters = new LinkedHashSet<EntryListFilter<T>>(Arrays.asList(fileFilters));
}
public CompositeEntryListFilter(Collection<EntryListFilter> fileFilters) {
this.fileFilters = new LinkedHashSet<EntryListFilter>(fileFilters);
public CompositeEntryListFilter(Collection<? extends EntryListFilter<T>> fileFilters) {
this.fileFilters = new LinkedHashSet<EntryListFilter<T>>(fileFilters);
}
@SuppressWarnings("unchecked")
public List<T> filterEntries(T[] entries) {
Assert.notNull(entries, "'files' should not be null");
List<T> leftOver = Arrays.asList(entries);
for (EntryListFilter fileFilter : this.fileFilters) {
T[] ts =(T[]) leftOver.toArray();
List<T> leftOver = Arrays.asList(entries);
for (EntryListFilter<T> fileFilter : this.fileFilters) {
T[] ts = (T[]) leftOver.toArray();
leftOver = fileFilter.filterEntries(ts);
}
return leftOver;
}
@@ -47,7 +52,7 @@ public class CompositeEntryListFilter<T> implements EntryListFilter<T> {
* @return this CompositeFileFilter instance with the added filters
* @see #addFilters(Collection)
*/
public CompositeEntryListFilter addFilter(EntryListFilter... filters) {
public CompositeEntryListFilter addFilter(EntryListFilter<T>... filters) {
return addFilters(Arrays.asList(filters));
}
@@ -59,7 +64,16 @@ public class CompositeEntryListFilter<T> implements EntryListFilter<T> {
* @param filtersToAdd a list of filters to add
* @return this CompositeEntryListFilter instance with the added filters
*/
public CompositeEntryListFilter addFilters(Collection<EntryListFilter> filtersToAdd) {
public CompositeEntryListFilter addFilters(Collection<EntryListFilter<T>> filtersToAdd) {
for (EntryListFilter<T> elf : filtersToAdd)
if (elf instanceof InitializingBean) {
try {
((InitializingBean) elf).afterPropertiesSet();
} catch (Exception e) {
throw new RuntimeException(e);
}
}
this.fileFilters.addAll(filtersToAdd);
return this;

View File

@@ -18,6 +18,19 @@ package org.springframework.integration.file.entries;
import java.util.List;
public interface EntryListFilter <T> {
List<T> filterEntries(T [] entries );
/**
* Strategy interface for filtering a group of entries / files.
* <p/>
* {@link EntryListFilter} that passes file entries only one time. This can
* conveniently be used to prevent duplication of files, as is done in
* {@link org.springframework.integration.file.FileReadingMessageSource}.
* <p/>
* This implementation is thread safe.
*
* @author Iwein Fuld
* @author Josh Long
* @since 1.0.0
*/
public interface EntryListFilter<T> {
List<T> filterEntries(T[] entries);
}

View File

@@ -15,6 +15,21 @@
*/
package org.springframework.integration.file.entries;
/**
* Responsible for coercing a String identification out of the {@link T} entry.
* @param <T> the type of entry (there's an implementation for FTP, SFTP, and plain-old java.io.Files)
*
* @author Josh Long
*/
public interface EntryNamer<T> {
/**
* 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 ....
*
*
* @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);
}

View File

@@ -0,0 +1,34 @@
/*
* 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.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...
*
* @author Josh Long
*
*/
public class FileEntryNamer implements EntryNamer<File> {
public String nameOf(File entry) {
return (entry != null) ? entry.getName() : null;
}
}

View File

@@ -24,16 +24,29 @@ import java.util.regex.Pattern;
/**
* experimental
* <emphasis>experimental</emphasis>
* <p/>
* 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})
*
* @author Josh Long
* @param <T> the type of entry
*/
public abstract class PatternMatchingEntryListFilter<T> extends AbstractEntryListFilter<T> implements InitializingBean {
public class PatternMatchingEntryListFilter<T> extends AbstractEntryListFilter<T> implements InitializingBean {
private Pattern pattern;
private String patternExpression;
private EntryNamer<T> entryNamer;
public PatternMatchingEntryListFilter(EntryNamer<T> en, String p) {
this.entryNamer = en;
this.patternExpression = p;
}
public PatternMatchingEntryListFilter(EntryNamer<T> en, Pattern p) {
this.entryNamer = en;
this.pattern = p;
}
public void setPattern(Pattern pattern) {
this.pattern = pattern;
}
@@ -46,13 +59,12 @@ public abstract class PatternMatchingEntryListFilter<T> extends AbstractEntryLis
if (StringUtils.hasText(this.patternExpression) && (pattern == null)) {
this.pattern = Pattern.compile(this.patternExpression);
}
Assert.notNull(this.entryNamer,"'entryNamer' must not be null!");
Assert.notNull(this.entryNamer, "'entryNamer' must not be null!");
Assert.notNull(this.pattern, "'pattern' mustn't be null!");
}
@Override
protected boolean accept(T t) {
public boolean accept(T t) {
return (t != null) && this.pattern.matcher(this.entryNamer.nameOf(t)).matches();
}

View File

@@ -0,0 +1,46 @@
/*
* 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.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 <b>one</b> argument instea of an array
*
* @author Josh Long
*/
public class SingleEntryAdaptingEntryListFilter<T> extends AbstractEntryListFilter<T> {
/**
* the {@link org.springframework.integration.file.entries.EntryListFilter} that you'd like to delegate to
*/
private volatile EntryListFilter<T> entryFilter;
public SingleEntryAdaptingEntryListFilter(EntryListFilter<T> ef) {
this.entryFilter = ef;
Assert.notNull(this.entryFilter, "the entryFilter can't be null");
}
@Override
@SuppressWarnings("unchecked")
public boolean accept(T t) {
T[] ts = (T[]) new Object[] { t };
return this.entryFilter.filterEntries(ts).size() == 1;
}
}

View File

@@ -14,7 +14,7 @@
* limitations under the License.
*/
package org.springframework.integration.file;
package org.springframework.integration.file.filters;
import java.io.File;
import java.util.ArrayList;

View File

@@ -14,7 +14,7 @@
* limitations under the License.
*/
package org.springframework.integration.file;
package org.springframework.integration.file.filters;
import java.io.File;
import java.util.Queue;
@@ -23,13 +23,13 @@ import java.util.concurrent.LinkedBlockingQueue;
/**
* {@link FileListFilter} that passes files only one time. This can
* conveniently be used to prevent duplication of files, as is done in
* {@link FileReadingMessageSource}.
* {@link org.springframework.integration.file.FileReadingMessageSource}.
* <p/>
* This implementation is thread safe.
*
* @author Iwein Fuld
* @since 1.0.0
*/
*/ @Deprecated
public class AcceptOnceFileListFilter extends AbstractFileListFilter {
private final Queue<File> seen;

View File

@@ -13,8 +13,10 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.integration.file.filters;
import java.util.Set;
package org.springframework.integration.file;
import org.springframework.util.Assert;
@@ -22,13 +24,14 @@ import java.io.File;
import java.io.FileFilter;
import java.util.*;
/**
* Composition that delegates to multiple {@link FileFilter}s. The composition is AND based, meaning that a file must
* pass through each filter's {@link #filterFiles(java.io.File[])} method in order to be accepted by the composite.
*
* @author Iwein Fuld
* @author Mark Fisher
*/
*/ @Deprecated
public class CompositeFileListFilter implements FileListFilter {
private final Set<FileListFilter> fileFilters;

View File

@@ -14,7 +14,7 @@
* limitations under the License.
*/
package org.springframework.integration.file;
package org.springframework.integration.file.filters;
import java.io.File;
import java.util.List;
@@ -23,7 +23,7 @@ import java.util.List;
* Strategy interface for filtering a group of files.
*
* @author Iwein Fuld
*/
*/ @Deprecated
public interface FileListFilter {
/**

View File

@@ -14,7 +14,7 @@
* limitations under the License.
*/
package org.springframework.integration.file;
package org.springframework.integration.file.filters;
import java.io.File;
import java.util.regex.Pattern;
@@ -26,6 +26,7 @@ import org.springframework.util.Assert;
*
* @author Mark Fisher
*/
@Deprecated
public class PatternMatchingFileListFilter extends AbstractFileListFilter {
private final Pattern pattern;

View File

@@ -16,8 +16,8 @@
package org.springframework.integration.file.locking;
import org.springframework.integration.file.AbstractFileListFilter;
import org.springframework.integration.file.FileLocker;
import org.springframework.integration.file.entries.AbstractEntryListFilter;
import java.io.File;
@@ -29,9 +29,10 @@ import java.io.File;
* @since 2.0
*
*/
public abstract class AbstractFileLockerFilter extends AbstractFileListFilter implements FileLocker {
public abstract class AbstractFileLockerFilter extends AbstractEntryListFilter<File> implements FileLocker {
protected final boolean accept(File file) {
return isLockable(file);
@Override
public boolean accept(File file) {
return this.isLockable(file);
}
}
}

View File

@@ -0,0 +1,261 @@
package org.springframework.integration.file.monitors;
import org.springframework.core.task.SimpleAsyncTaskExecutor;
import org.springframework.integration.context.IntegrationObjectSupport;
import org.springframework.integration.file.entries.*;
import org.springframework.util.Assert;
import java.io.File;
import java.util.concurrent.Executor;
import java.util.concurrent.LinkedBlockingQueue;
/**
* This component will support event-based (not poller based) notifications of files from a file system.
* Immediate implementations will center around supporting other adapters's delivery of files once they've been synced from a remote system.
* Potential future expansions for consumer consumption might be a push / event-based file adapter based on either native code
* or Java 7's NIO.2 WaterService or other third party implementations.
* <p/>
* In the meantime, this provides us with a base class for building event driven file adapters quickly. The two cases I see are:
* <p/>
* <ol>
* <li></li>
* <li></li>
* </ol>
*
* @author Josh Long
*/
public abstract class AbstractEventDrivenFileMonitor extends IntegrationObjectSupport implements EventDrivenDirectoryMonitor {
/**
* when this component starts up, we can perform a scan of the folder this first time and to pre-seed the #additions queue
*/
private boolean scanDirectoryOnLoad;
/**
* How many files we'll support in the backlog at a time
*/
private volatile int maxQueueSize = 100;
/**
* the backlog
*/
private volatile LinkedBlockingQueue<File> additions;
/**
* An {@link java.util.concurrent.Executor} implementation. Default is {@link org.springframework.core.task.SimpleAsyncTaskExecutor}
*/
private volatile Executor executor;
/**
* Should the director be automatically created?
*/
private volatile boolean autoCreateDirectory;
/**
* The directory to monitor (a {@link java.io.File})
*/
private volatile File directoryToMonitorCached;
/**
* A {@link org.springframework.integration.file.entries.EntryListFilter} reference
*/
private volatile SingleEntryAdaptingEntryListFilter<File> filter;
/**
* state guard (extra for post-init state)
*/
private final Object guard = new Object();
public void setScanDirectoryOnLoad(boolean scanDirectoryOnLoad) {
this.scanDirectoryOnLoad = scanDirectoryOnLoad;
}
/**
* installs directory, and then kicks of an event pump
*
* @param directory the directory to start watching from. Unspecified if this implies recursion or not.
* @param fileAdditionListener the callback
* @throws Exception
*/
public void monitor(File directory, FileAdditionListener fileAdditionListener)
throws Exception {
this.installDirectoryIfRequired(directory);
this.prescan();
this.executor.execute(new FileDeliveryPump(fileAdditionListener));
}
public void setMaxQueueSize(int maxQueueSize) {
this.maxQueueSize = maxQueueSize;
}
public void setFilter(EntryListFilter<File> filter) {
this.filter = new SingleEntryAdaptingEntryListFilter<File>(filter);
}
public void setExecutor(Executor executor) {
this.executor = executor;
}
public void setAutoCreateDirectory(boolean autoCreateDirectory) {
this.autoCreateDirectory = autoCreateDirectory;
}
protected void publishNewFileReceived(String path) {
this.publishNewFileReceived(new File(path));
}
protected void publishNewFileReceived(File file) {
this.additions.add(file);
}
/**
* Obviously, we're trying to keep away from scanning, but this may be necessary at startup to catch up the backlog
*/
protected void prescan() {
synchronized (this.guard) {
if (this.scanDirectoryOnLoad) {
for (File f : this.directoryToMonitorCached.listFiles())
this.publishNewFileReceived(f);
}
}
}
/**
* Handles ensuring that the directory we're monitroring exists or can be created
*
* @param directoryToMonitor the directory to monitor
* @throws Exception
*/
protected void installDirectoryIfRequired(File directoryToMonitor)
throws Exception {
synchronized (this.guard) {
this.directoryToMonitorCached = directoryToMonitor;
Assert.state(null != this.directoryToMonitorCached, "the directory to monitor can't be null");
boolean directoryIsReady = this.directoryToMonitorCached.exists();
if (!directoryIsReady) {
if (!directoryToMonitorCached.exists()) {
if (this.autoCreateDirectory) {
Assert.state(directoryToMonitorCached.mkdirs() && directoryToMonitorCached.exists(),
String.format("Couldn't create the directory %s", directoryToMonitorCached.getAbsolutePath()));
}
}
}
}
}
/**
* Custom initialization hook - override at your discretion
*
* @throws Exception
*/
protected void start() throws Exception{
// noop
}
@Override
protected void onInit() throws Exception {
additions = new LinkedBlockingQueue<File>(this.maxQueueSize);
if (this.executor == null) {
this.executor = new SimpleAsyncTaskExecutor();
}
if (this.filter == null) {
this.filter = new SingleEntryAdaptingEntryListFilter<File>(new AcceptAllEntryListFilter<File>());
}
Assert.notNull(this.filter, "the filter can't be null");
this.start();
}
/**
* a way to remove the responsibility of reacting to the file system from implementations while still being thread safe and handling backlog
*
* @author Josh Long
*/
class FileDeliveryPump implements Runnable {
private volatile FileAdditionListener fileAdditionListener;
public FileDeliveryPump(FileAdditionListener fileAdditionListener) {
this.fileAdditionListener = fileAdditionListener;
Assert.notNull(this.fileAdditionListener, "the FileAdditionListener can't be null");
}
public void run() {
do {
try {
File taken = additions.take();
if (filter.accept(taken)) {
fileAdditionListener.fileAdded(taken);
}
} catch (Throwable th) {
throw new RuntimeException(th);
}
} while (true);
}
}
}
/*
class MyEDFRM extends AbstractEventDrivenFileMonitor {
@Override
protected void start() throws Exception {
System.out.println("start()");
}
public void addToHeap(File file) {
this.publishNewFileReceived(file);
}
public static void main(String[] args) throws Throwable {
SimpleAsyncTaskExecutor simpleAsyncTaskExecutor = new SimpleAsyncTaskExecutor();
final MyEDFRM myEDFRM = new MyEDFRM();
myEDFRM.setExecutor(simpleAsyncTaskExecutor);
myEDFRM.setAutoCreateDirectory(true);
myEDFRM.afterPropertiesSet();
AcceptOnceEntryFileListFilter <File> acceptOnceEntryFileListFilter=new AcceptOnceEntryFileListFilter<File>() ;
acceptOnceEntryFileListFilter.afterPropertiesSet();
PatternMatchingEntryListFilter <File> patternMatchingEntryListFilter=
new PatternMatchingEntryListFilter<File>(new FileEntryNamer(), ".*?jpg");
patternMatchingEntryListFilter.afterPropertiesSet();
Collection<? extends EntryListFilter<File>> l=Arrays.asList( acceptOnceEntryFileListFilter, patternMatchingEntryListFilter);
CompositeEntryListFilter compositeEntryListFilter = new CompositeEntryListFilter<File>(l );
myEDFRM.setFilter(compositeEntryListFilter);
final File desktop = new File(System.getProperty("user.home"), "Desktop");
myEDFRM.monitor(desktop, new FileAdditionListener() {
public void fileAdded(File f) {
System.out.println("Got one! " + f.getAbsolutePath());
}
});
System.out.println("enjoying the world");
simpleAsyncTaskExecutor.execute(new Runnable() {
public void run() {
while (true) {
try {
Thread.sleep(1000 * 10);
for (File f : desktop.listFiles())
myEDFRM.addToHeap(f);
} catch (InterruptedException e) {
//
}
}
}
});
}
}
*/

View File

@@ -0,0 +1,15 @@
package org.springframework.integration.file.monitors;
import java.io.File;
/**
* simply takes a hint and publishes an event as appropriate
*
* @author Josh Long
*/
public class DirectedEventDrivenFileMonitor extends AbstractEventDrivenFileMonitor {
public void directlyNotifyOfNewFile(File file) {
this.publishNewFileReceived(file);
}
}

View File

@@ -0,0 +1,21 @@
package org.springframework.integration.file.monitors;
import java.io.File;
/**
* Defines an interface for a component that reacts to file system events
*
* @author Josh Long
*/
public interface EventDrivenDirectoryMonitor {
/**
* the implementation should know how to publish events on the {@link FileAdditionListener}
* for a given #directory
*
* @param directory the directory to start watching from. Unspecified if this implies recursion or not.
* @param fileAdditionListener the callback
* @throws Exception if anything should go wrong
*/
void monitor(File directory, FileAdditionListener fileAdditionListener) throws Exception;
}

View File

@@ -0,0 +1,19 @@
package org.springframework.integration.file.monitors;
import java.io.File;
/**
* A generic hook into the arrival of a new {@link java.io.File}
*
* @author Josh Long
* @see org.springframework.integration.file.monitors.MessageSendingFileAdditionListener
*/
public interface FileAdditionListener {
/**
* a callback method that's invoked when a new {@link java.io.File} is detected.
*
* @param f the {@link java.io.File} that was detected
*/
void fileAdded(File f);
}

View File

@@ -0,0 +1,47 @@
package org.springframework.integration.file.monitors;
import org.springframework.integration.Message;
import org.springframework.integration.context.IntegrationObjectSupport;
import org.springframework.integration.core.MessageBuilder;
import org.springframework.integration.core.MessageChannel;
import org.springframework.integration.core.MessagingTemplate;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.util.Assert;
import java.io.File;
/**
* Supports propagating a {@link org.springframework.integration.Message} on the receipt of a new {@link java.io.File}
*
* @author Josh Long
*/
public class MessageSendingFileAdditionListener extends IntegrationObjectSupport implements FileAdditionListener {
private MessagingTemplate messagingTemplate = new MessagingTemplate();
private MessageChannel channel;
private PlatformTransactionManager platformTransactionManager;
public void setChannel(MessageChannel channel) {
this.channel = channel;
}
@Override
protected void onInit() throws Exception {
Assert.notNull(this.channel, "'channel' can't be null!");
if (this.platformTransactionManager != null) {
this.messagingTemplate.setTransactionManager(platformTransactionManager);
}
}
public void setPlatformTransactionManager(PlatformTransactionManager platformTransactionManager) {
this.platformTransactionManager = platformTransactionManager;
}
public void fileAdded(File f) {
Message<File> fileMsg = MessageBuilder.withPayload(f).build();
this.messagingTemplate.send(fileMsg);
}
}

View File

@@ -53,7 +53,7 @@
<xsd:annotation>
<xsd:appinfo>
<tool:annotation kind="ref">
<tool:expected-type type="org.springframework.integration.file.FileListFilter"/>
<tool:expected-type type="org.springframework.integration.file.filters.FileListFilter"/>
</tool:annotation>
</xsd:appinfo>
</xsd:annotation>

View File

@@ -56,7 +56,7 @@
<xsd:annotation>
<xsd:appinfo>
<tool:annotation kind="ref">
<tool:expected-type type="org.springframework.integration.file.FileListFilter"/>
<tool:expected-type type="org.springframework.integration.file.entries.EntryListFilter"/>
</tool:annotation>
</xsd:appinfo>
</xsd:annotation>

View File

@@ -26,13 +26,15 @@ import java.util.Arrays;
import java.util.List;
import org.junit.Test;
import org.springframework.integration.file.filters.CompositeFileListFilter;
import org.springframework.integration.file.filters.FileListFilter;
/**
* @author Iwein Fuld
*/
public class CompositeFileListFilterTests {
private FileListFilter fileFilterMock1 = mock(FileListFilter.class);
private FileListFilter fileFilterMock1 = mock( FileListFilter.class);
private FileListFilter fileFilterMock2 = mock(FileListFilter.class);
@@ -51,7 +53,8 @@ public class CompositeFileListFilterTests {
@Test
public void forwardedToAddedFilters() throws Exception {
CompositeFileListFilter compositeFileFilter = new CompositeFileListFilter().addFilter(fileFilterMock1, fileFilterMock2);
CompositeFileListFilter compositeFileFilter = new CompositeFileListFilter();
compositeFileFilter.addFilter(fileFilterMock1, fileFilterMock2);
List<File> returnedFiles = Arrays.asList(new File[] { fileMock });
when(fileFilterMock1.filterFiles(isA(File[].class))).thenReturn(returnedFiles);
when(fileFilterMock2.filterFiles(isA(File[].class))).thenReturn(returnedFiles);

View File

@@ -1,28 +1,49 @@
<?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:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p" xmlns:util="http://www.springframework.org/schema/util"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-2.0.xsd">
<!-- under test -->
<bean id="pollableFileSource" class="org.springframework.integration.file.FileReadingMessageSource"
p:directory="file:${java.io.tmpdir}/FileReadingMessageSourceIntegrationTests"
p:filter-ref="compositeFilter"/>
<!-- under test -->
<bean id="pollableFileSource" class="org.springframework.integration.file.FileReadingMessageSource"
p:directory="file:${java.io.tmpdir}/FileReadingMessageSourceIntegrationTests"
p:filter-ref="compositeFilter"/>
<!-- customized filter -->
<bean id="compositeFilter" class="org.springframework.integration.file.CompositeFileListFilter">
<constructor-arg>
<list>
<bean class="org.springframework.integration.file.AcceptOnceFileListFilter" />
<bean class="org.springframework.integration.file.TestFileListFilter" />
<bean class="org.springframework.integration.file.PatternMatchingFileListFilter">
<constructor-arg value="^test.*$"/>
</bean>
</list>
</constructor-arg>
</bean>
<bean class="org.springframework.integration.file.entries.FileEntryNamer" id="entryNamer"/>
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer" />
<!-- customized filter -->
<!--
<bean id="compositeFilter" class="org.springframework.integration.file.entries.CompositeEntryListFilter">
<constructor-arg>
<list>
<bean class="org.springframework.integration.file.entries.AcceptOnceEntryFileListFilter"/>
<bean class="org.springframework.integration.file.TestFileListFilter"/>
<bean class="org.springframework.integration.file.entries.PatternMatchingEntryListFilter">
<constructor-arg ref="entryNamer"/>
<constructor-arg value="^test.*$"/>
</bean>
</list>
</constructor-arg>
</bean>
-->
</beans>
<bean class="org.springframework.integration.file.config.FileListFilterFactoryBean" id="compositeFilter">
<property name="filterReferences">
<util:list>
<bean class="org.springframework.integration.file.config.FileListFilterFactoryBean" p:preventDuplicates="true"/>
<bean class="org.springframework.integration.file.config.FileListFilterFactoryBean" p:preventDuplicates="false"/>
<bean class="org.springframework.integration.file.config.FileListFilterFactoryBean" p:filenamePattern="^test.*$"/>
</util:list>
</property>
</bean>
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"/>
</beans>

View File

@@ -80,7 +80,8 @@ public class FileReadingMessageSourceIntegrationTests {
@Test
public void getFiles() throws Exception {
Message<File> received1 = pollableFileSource.receive();
assertNotNull("This should return the first message", received1);
System.out.println( "getfiels() round 1");
assertNotNull("This should return the first message", received1);
pollableFileSource.onSend(received1);
Message<File> received2 = pollableFileSource.receive();
assertNotNull(received2);
@@ -154,12 +155,13 @@ public class FileReadingMessageSourceIntegrationTests {
/**
* Convenience method to run part of a test concurrently in multiple threads
*
* @param numberOfThreads
* @param todo the runnable that should be run by all the threads
* @param numberOfThreads how many threads to spawn
* @param runnable the runnable that should be run by all the threads
* @param start the {@link java.util.concurrent.CountDownLatch} instance telling it when to assume everything works
* @return a latch that will be counted down once all threads have run their
* runnable.
*/
private CountDownLatch doConcurrently(int numberOfThreads, final Runnable todo, final CountDownLatch start) {
private CountDownLatch doConcurrently(int numberOfThreads, final Runnable runnable, final CountDownLatch start) {
final CountDownLatch started = new CountDownLatch(numberOfThreads);
final CountDownLatch done = new CountDownLatch(numberOfThreads);
for (int i = 0; i < numberOfThreads; i++) {
@@ -174,7 +176,7 @@ public class FileReadingMessageSourceIntegrationTests {
catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
todo.run();
runnable.run();
done.countDown();
}
}).start();

View File

@@ -1,46 +1,48 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:file="http://www.springframework.org/schema/integration/file"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.springframework.org/schema/beans"
xmlns:si="http://www.springframework.org/schema/integration"
xsi:schemaLocation="http://www.springframework.org/schema/beans
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.springframework.org/schema/beans"
xmlns:p="http://www.springframework.org/schema/p" xmlns:si="http://www.springframework.org/schema/integration" xmlns:util="http://www.springframework.org/schema/util"
xsi:schemaLocation="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/file
http://www.springframework.org/schema/integration/file/spring-integration-file.xsd">
http://www.springframework.org/schema/integration/file/spring-integration-file.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-2.0.xsd">
<!-- under test -->
<file:inbound-channel-adapter
directory="#{inputDirectory.path}"
channel="fileMessages" filter="compositeFilter"/>
<!-- under test -->
<file:inbound-channel-adapter
directory="#{inputDirectory.path}"
channel="fileMessages" filter="compositeFilter"/>
<bean id="temp" class="org.junit.rules.TemporaryFolder"
init-method="create" destroy-method="delete"/>
<bean id="temp" class="org.junit.rules.TemporaryFolder"
init-method="create" destroy-method="delete"/>
<bean id="inputDirectory" class="java.io.File">
<constructor-arg value="#{temp.newFolder('FileToChannelIntegrationTests').path}"/>
</bean>
<bean id="inputDirectory" class="java.io.File">
<constructor-arg value="#{temp.newFolder('FileToChannelIntegrationTests').path}"/>
</bean>
<si:channel id="fileMessages">
<si:queue capacity="10" />
</si:channel>
<si:channel id="fileMessages">
<si:queue capacity="10"/>
</si:channel>
<!-- customized filter -->
<bean id="compositeFilter"
class="org.springframework.integration.file.CompositeFileListFilter">
<constructor-arg>
<list>
<bean class="org.springframework.integration.file.AcceptOnceFileListFilter"/>
<bean class="org.springframework.integration.file.TestFileListFilter"/>
<bean class="org.springframework.integration.file.PatternMatchingFileListFilter">
<constructor-arg value="^test.*$"/>
</bean>
</list>
</constructor-arg>
</bean>
<si:poller default="true" fixed-rate="10"/>
<bean class="org.springframework.integration.file.config.FileListFilterFactoryBean" id="compositeFilter">
<property name="filterReferences">
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"/>
<util:list>
</beans>
<bean class="org.springframework.integration.file.config.FileListFilterFactoryBean" p:preventDuplicates="true"/>
<bean class="org.springframework.integration.file.config.FileListFilterFactoryBean" p:preventDuplicates="false"/>
<bean class="org.springframework.integration.file.config.FileListFilterFactoryBean" p:filenamePattern="^test.*$"/>
</util:list>
</property>
</bean>
<si:poller default="true" fixed-rate="10"/>
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"/>
</beans>

View File

@@ -27,6 +27,8 @@ import org.junit.Test;
import org.springframework.beans.factory.BeanCreationException;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.integration.file.filters.FileListFilter;
import org.springframework.integration.file.filters.PatternMatchingFileListFilter;
/**
* @author Mark Fisher

View File

@@ -16,6 +16,8 @@
package org.springframework.integration.file;
import org.springframework.integration.file.entries.EntryListFilter;
import java.io.File;
import java.util.Arrays;
import java.util.List;
@@ -23,10 +25,8 @@ import java.util.List;
/**
* @author Iwein Fuld
*/
public class TestFileListFilter implements FileListFilter {
public List<File> filterFiles(File[] files) {
return Arrays.asList(files);
}
public class TestFileListFilter implements EntryListFilter<File> {
public List<File> filterEntries(File[] entries) {
return Arrays.asList(entries);
}
}

View File

@@ -20,15 +20,19 @@
</integration:poller>
</inbound-channel-adapter>
<beans:bean id="filter" class="org.springframework.integration.file.CompositeFileListFilter">
<beans:bean id="filter" class="org.springframework.integration.file.config.FileListFilterFactoryBean">
</beans:bean>
<!--
<beans:bean id="filter" class="org.springframework.integration.file.filters.CompositeFileListFilter">
<beans:constructor-arg>
<beans:list></beans:list>
</beans:constructor-arg>
</beans:bean>
</beans:bean>-->
<beans:bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"/>
<beans:bean id="testComparator"
class="org.springframework.integration.file.config.FileInboundChannelAdapterParserTests$TestComparator"/>
</beans:beans>
</beans:beans>

Some files were not shown because too many files have changed in this diff Show More