restructuring: branches/tags/trunk moved to top-level of repo
This commit is contained in:
15
build-spring-integration/build.xml
Normal file
15
build-spring-integration/build.xml
Normal file
@@ -0,0 +1,15 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project name="build-spring-integration" default="precommit">
|
||||
|
||||
<target name="precommit" depends="clean,clean-integration,jar,test"/>
|
||||
|
||||
<path id="bundles">
|
||||
<pathelement location="../spring-integration-core"/>
|
||||
<pathelement location="../spring-integration-samples"/>
|
||||
</path>
|
||||
|
||||
<property name="integration.repo.dir" value="${basedir}/../integration-repo"/>
|
||||
|
||||
<import file="../spring-build/multi-bundle/default.xml"/>
|
||||
|
||||
</project>
|
||||
19
spring-integration-core/.classpath
Normal file
19
spring-integration-core/.classpath
Normal file
@@ -0,0 +1,19 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<classpath>
|
||||
<classpathentry kind="src" path="src/main/java"/>
|
||||
<classpathentry kind="src" output="target/test-classes" path="src/test/java"/>
|
||||
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
|
||||
<classpathentry kind="var" path="IVY_CACHE/org.aopalliance/aopalliance/aopalliance-1.0.jar" sourcepath="IVY_CACHE/org.aopalliance/aopalliance/aopalliance-sources-1.0.jar"/>
|
||||
<classpathentry kind="var" path="IVY_CACHE/org.apache/commons-logging/commons-logging-1.1.jar" sourcepath="/IVY_CACHE/org.apache/commons-logging/commons-logging-sources-1.1.jar"/>
|
||||
<classpathentry kind="var" path="IVY_CACHE/org.junit/junit/junit-4.4.jar" sourcepath="/IVY_CACHE/org.junit/junit/junit-sources-4.4.jar"/>
|
||||
<classpathentry kind="var" path="IVY_CACHE/org.springframework/spring-aop/spring-aop-2.5.0.jar" sourcepath="/IVY_CACHE/org.springframework/spring-aop/spring-aop-sources-2.5.0.jar"/>
|
||||
<classpathentry kind="var" path="IVY_CACHE/org.springframework/spring-beans/spring-beans-2.5.0.jar" sourcepath="/IVY_CACHE/org.springframework/spring-beans/spring-beans-sources-2.5.0.jar"/>
|
||||
<classpathentry kind="var" path="IVY_CACHE/org.springframework/spring-context/spring-context-2.5.0.jar" sourcepath="/IVY_CACHE/org.springframework/spring-context/spring-context-sources-2.5.0.jar"/>
|
||||
<classpathentry kind="var" path="IVY_CACHE/org.springframework/spring-core/spring-core-2.5.0.jar" sourcepath="/IVY_CACHE/org.springframework/spring-core/spring-core-sources-2.5.0.jar"/>
|
||||
<classpathentry kind="var" path="IVY_CACHE/org.springframework/spring-context-support/spring-context-support-2.5.0.jar" sourcepath="/IVY_CACHE/org.springframework/spring-context-support/spring-context-support-sources-2.5.0.jar"/>
|
||||
<classpathentry kind="var" path="IVY_CACHE/org.springframework/spring-jms/spring-jms-2.5.0.jar" sourcepath="/IVY_CACHE/org.springframework/spring-jms/spring-jms-sources-2.5.0.jar"/>
|
||||
<classpathentry kind="var" path="IVY_CACHE/org.springframework/spring-tx/spring-tx-2.5.0.jar"/>
|
||||
<classpathentry kind="var" path="IVY_CACHE/org.apache/commons-pool/commons-pool-1.3.jar"/>
|
||||
<classpathentry kind="var" path="IVY_CACHE/javax.jms/jms/jms-1.1.jar"/>
|
||||
<classpathentry kind="output" path="target/classes"/>
|
||||
</classpath>
|
||||
17
spring-integration-core/.project
Normal file
17
spring-integration-core/.project
Normal file
@@ -0,0 +1,17 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<projectDescription>
|
||||
<name>spring-integration-core</name>
|
||||
<comment></comment>
|
||||
<projects>
|
||||
</projects>
|
||||
<buildSpec>
|
||||
<buildCommand>
|
||||
<name>org.eclipse.jdt.core.javabuilder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
</buildSpec>
|
||||
<natures>
|
||||
<nature>org.eclipse.jdt.core.javanature</nature>
|
||||
</natures>
|
||||
</projectDescription>
|
||||
9
spring-integration-core/build.xml
Normal file
9
spring-integration-core/build.xml
Normal file
@@ -0,0 +1,9 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project name="spring-integration-core">
|
||||
|
||||
<property name="version" value="0.5-SNAPSHOT"/>
|
||||
<property name="integration.repo.dir" value="${basedir}/../integration-repo"/>
|
||||
|
||||
<import file="../spring-build/standard/default.xml"/>
|
||||
|
||||
</project>
|
||||
26
spring-integration-core/ivy.xml
Normal file
26
spring-integration-core/ivy.xml
Normal file
@@ -0,0 +1,26 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<?xml-stylesheet type="text/xsl" href="http://ivyrep.jayasoft.org/ivy-doc.xsl"?>
|
||||
<ivy-module
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:noNamespaceSchemaLocation="http://incubator.apache.org/ivy/schemas/ivy.xsd"
|
||||
version="1.3">
|
||||
|
||||
<info organisation="org.springframework" module="${ant.project.name}">
|
||||
<license name="Apache 2.0" url="http://www.apache.org/licenses/LICENSE-2.0"/>
|
||||
<ivyauthor name="Mark Fisher"/>
|
||||
</info>
|
||||
|
||||
<configurations>
|
||||
<include file="${spring.build.dir}/common/default-ivy-configurations.xml"/>
|
||||
</configurations>
|
||||
|
||||
<dependencies>
|
||||
<dependency org="javax.jms" name="jms" rev="1.1" conf="compile->default"/>
|
||||
<dependency org="org.junit" name="junit" rev="4.4" conf="test->default"/>
|
||||
<dependency org="org.springframework" name="spring-context" rev="2.5.0" conf="compile->default"/>
|
||||
<dependency org="org.springframework" name="spring-aop" rev="2.5.0" conf="compile->default"/>
|
||||
<dependency org="org.springframework" name="spring-jms" rev="2.5.0" conf="compile->default"/>
|
||||
<dependency org="org.springframework" name="spring-tx" rev="2.5.0" conf="compile->default"/>
|
||||
</dependencies>
|
||||
|
||||
</ivy-module>
|
||||
6
spring-integration-core/resources/changelog.txt
Normal file
6
spring-integration-core/resources/changelog.txt
Normal file
@@ -0,0 +1,6 @@
|
||||
SPRING INTEGRATION CHANGELOG
|
||||
============================
|
||||
|
||||
Changes in version 1.0 M1 (Jan 04, 2008)
|
||||
----------------------------------------
|
||||
|
||||
201
spring-integration-core/resources/license.txt
Normal file
201
spring-integration-core/resources/license.txt
Normal file
@@ -0,0 +1,201 @@
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright [yyyy] [name of copyright owner]
|
||||
|
||||
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.
|
||||
21
spring-integration-core/resources/notice.txt
Normal file
21
spring-integration-core/resources/notice.txt
Normal file
@@ -0,0 +1,21 @@
|
||||
========================================================================
|
||||
== NOTICE file corresponding to section 4 d of the Apache License, ==
|
||||
== Version 2.0, in this case for the Spring Integration distribution. ==
|
||||
========================================================================
|
||||
|
||||
This product includes software developed by
|
||||
the Apache Software Foundation (http://www.apache.org).
|
||||
|
||||
The end-user documentation included with a redistribution, if any,
|
||||
must include the following acknowledgement:
|
||||
|
||||
"This product includes software developed by the Spring Framework
|
||||
Project (http://www.springframework.org)."
|
||||
|
||||
Alternatively, this acknowledgement may appear in the software itself,
|
||||
if and wherever such third-party acknowledgements normally appear.
|
||||
|
||||
The names "Spring", "Spring Framework", and "Spring Integration" must
|
||||
not be used to endorse or promote products derived from this software
|
||||
without prior written permission. For written permission, please contact
|
||||
rod.johnson@springsource.com or juergen.hoeller@springsource.com.
|
||||
3
spring-integration-core/resources/readme.txt
Normal file
3
spring-integration-core/resources/readme.txt
Normal file
@@ -0,0 +1,3 @@
|
||||
SPRING INTEGRATION 1.0 M1 (JAN 04 2008)
|
||||
---------------------------------------
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
http\://www.springframework.org/schema/integration=org.springframework.integration.config.IntegrationNamespaceHandler
|
||||
@@ -0,0 +1 @@
|
||||
http\://www.springframework.org/schema/integration/spring-integration-1.0.xsd=org/springframework/integration/config/spring-integration-1.0.xsd
|
||||
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Copyright 2002-2007 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;
|
||||
|
||||
/**
|
||||
* Exception that indicates an error during message delivery.
|
||||
*
|
||||
* @author Mark Fisher
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
public class MessageDeliveryException extends MessagingException {
|
||||
|
||||
public MessageDeliveryException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
public MessageDeliveryException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Copyright 2002-2007 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;
|
||||
|
||||
/**
|
||||
* Exception that indicates an error during message handling.
|
||||
*
|
||||
* @author Mark Fisher
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
public class MessageHandlingException extends MessagingException {
|
||||
|
||||
public MessageHandlingException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
public MessageHandlingException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Copyright 2002-2007 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;
|
||||
|
||||
/**
|
||||
* Exception that indicates an incorrectly configured messaging component.
|
||||
*
|
||||
* @author Mark Fisher
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
public class MessagingConfigurationException extends MessagingException {
|
||||
|
||||
public MessagingConfigurationException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
public MessagingConfigurationException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Copyright 2002-2007 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;
|
||||
|
||||
/**
|
||||
* The base exception for any failures within the messaging system.
|
||||
*
|
||||
* @author Mark Fisher
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
public class MessagingException extends RuntimeException {
|
||||
|
||||
public MessagingException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
public MessagingException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* Copyright 2002-2007 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;
|
||||
|
||||
/**
|
||||
* An unchecked wrapper exception for InterruptedExceptions.
|
||||
*
|
||||
* @author Mark Fisher
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
public class SystemInterruptedException extends MessagingException {
|
||||
|
||||
public SystemInterruptedException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
* Copyright 2002-2007 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.integration.adapter;
|
||||
|
||||
import org.springframework.integration.channel.MessageChannel;
|
||||
import org.springframework.integration.message.Message;
|
||||
import org.springframework.integration.message.MessageMapper;
|
||||
import org.springframework.integration.message.SimplePayloadMessageMapper;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* A base class providing common behavior for source adapters.
|
||||
*
|
||||
* @author Mark Fisher
|
||||
*/
|
||||
public class AbstractSourceAdapter<T> implements SourceAdapter {
|
||||
|
||||
private MessageChannel channel;
|
||||
|
||||
private MessageMapper<?,T> mapper = new SimplePayloadMessageMapper<T>();
|
||||
|
||||
private long sendTimeout = -1;
|
||||
|
||||
|
||||
public void setChannel(MessageChannel channel) {
|
||||
Assert.notNull(channel, "'channel' must not be null");
|
||||
this.channel = channel;
|
||||
}
|
||||
|
||||
public void setSendTimeout(long sendTimeout) {
|
||||
this.sendTimeout = sendTimeout;
|
||||
}
|
||||
|
||||
public void setMessageMapper(MessageMapper<?,T> mapper) {
|
||||
Assert.notNull(mapper, "'mapper' must not be null");
|
||||
this.mapper = mapper;
|
||||
}
|
||||
|
||||
protected MessageMapper<?,T> getMessageMapper() {
|
||||
return this.mapper;
|
||||
}
|
||||
|
||||
protected boolean sendToChannel(T object) {
|
||||
Message<?> message = this.mapper.toMessage(object);
|
||||
if (this.sendTimeout < 0) {
|
||||
return this.channel.send(message);
|
||||
}
|
||||
return this.channel.send(message, this.sendTimeout);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
/*
|
||||
* Copyright 2002-2007 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.integration.adapter;
|
||||
|
||||
import org.springframework.integration.bus.ConsumerPolicy;
|
||||
import org.springframework.integration.channel.MessageChannel;
|
||||
import org.springframework.integration.message.Message;
|
||||
import org.springframework.integration.message.MessageMapper;
|
||||
import org.springframework.integration.message.SimplePayloadMessageMapper;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Base class providing common behavior for target adapters.
|
||||
*
|
||||
* @author Mark Fisher
|
||||
*/
|
||||
public abstract class AbstractTargetAdapter<T> implements TargetAdapter<T> {
|
||||
|
||||
private String name;
|
||||
|
||||
private MessageChannel channel;
|
||||
|
||||
private MessageMapper<?,T> mapper = new SimplePayloadMessageMapper<T>();
|
||||
|
||||
private ConsumerPolicy policy = ConsumerPolicy.newPollingPolicy(5);
|
||||
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return this.name;
|
||||
}
|
||||
|
||||
public void setChannel(MessageChannel channel) {
|
||||
Assert.notNull(channel, "'channel' must not be null");
|
||||
this.channel = channel;
|
||||
}
|
||||
|
||||
public MessageChannel getChannel() {
|
||||
return this.channel;
|
||||
}
|
||||
|
||||
public void setMessageMapper(MessageMapper<?,T> mapper) {
|
||||
Assert.notNull(mapper, "'mapper' must not be null");
|
||||
this.mapper = mapper;
|
||||
}
|
||||
|
||||
protected MessageMapper<?,T> getMessageMapper() {
|
||||
return this.mapper;
|
||||
}
|
||||
|
||||
public void setConsumerPolicy(ConsumerPolicy policy) {
|
||||
Assert.notNull(policy, "'policy' must not be null");
|
||||
this.policy = policy;
|
||||
}
|
||||
|
||||
public ConsumerPolicy getConsumerPolicy() {
|
||||
return this.policy;
|
||||
}
|
||||
|
||||
public final void messageReceived(Message message) {
|
||||
this.sendToTarget(this.mapper.fromMessage(message));
|
||||
}
|
||||
|
||||
protected abstract boolean sendToTarget(T object);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
* Copyright 2002-2007 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.integration.adapter;
|
||||
|
||||
/**
|
||||
* A strategy for preparing an argument list from a single source object.
|
||||
*
|
||||
* @author Mark Fisher
|
||||
*/
|
||||
public interface ArgumentListPreparer {
|
||||
|
||||
Object[] prepare(Object source);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* Copyright 2002-2007 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.integration.adapter;
|
||||
|
||||
import org.springframework.integration.message.MessageMapper;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Target adapter implementation that delegates to a {@link MessageMapper}
|
||||
* and then passes the resulting object to the provided {@link Target}.
|
||||
*
|
||||
* @author Mark Fisher
|
||||
*/
|
||||
public class DefaultTargetAdapter<T> extends AbstractTargetAdapter<T> {
|
||||
|
||||
private Target<T> target;
|
||||
|
||||
|
||||
public DefaultTargetAdapter(Target<T> target) {
|
||||
Assert.notNull(target, "'target' must not be null");
|
||||
this.target = target;
|
||||
}
|
||||
|
||||
public boolean sendToTarget(T object) {
|
||||
return this.target.send(object);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,76 @@
|
||||
/*
|
||||
* Copyright 2002-2007 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.integration.adapter;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.integration.MessagingConfigurationException;
|
||||
import org.springframework.integration.util.MethodValidator;
|
||||
import org.springframework.integration.util.SimpleMethodInvoker;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* A pollable source that invokes a no-argument method so that its return value
|
||||
* may be sent to a channel.
|
||||
*
|
||||
* @author Mark Fisher
|
||||
*/
|
||||
public class MethodInvokingSource<T> implements PollableSource<Object>, InitializingBean {
|
||||
|
||||
private T object;
|
||||
|
||||
private String method;
|
||||
|
||||
private SimpleMethodInvoker<T> invoker;
|
||||
|
||||
|
||||
public void setObject(T object) {
|
||||
Assert.notNull(object, "'object' must not be null");
|
||||
this.object = object;
|
||||
}
|
||||
|
||||
public void setMethod(String method) {
|
||||
Assert.notNull(method, "'method' must not be null");
|
||||
this.method = method;
|
||||
}
|
||||
|
||||
public void afterPropertiesSet() {
|
||||
this.invoker = new SimpleMethodInvoker<T>(this.object, this.method);
|
||||
this.invoker.setMethodValidator(new MessageReceivingMethodValidator());
|
||||
}
|
||||
|
||||
public Collection<Object> poll(int limit) {
|
||||
if (this.invoker == null) {
|
||||
this.afterPropertiesSet();
|
||||
}
|
||||
return Arrays.asList(this.invoker.invokeMethod(new Object[] {}));
|
||||
}
|
||||
|
||||
|
||||
private static class MessageReceivingMethodValidator implements MethodValidator {
|
||||
|
||||
public void validate(Method method) {
|
||||
if (method.getReturnType().equals(void.class)) {
|
||||
throw new MessagingConfigurationException("MethodInvokingSource requires a non-void returning method.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
/*
|
||||
* Copyright 2002-2007 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.integration.adapter;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.integration.util.SimpleMethodInvoker;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* A messaging target that invokes the specified method on the provided object.
|
||||
*
|
||||
* @author Mark Fisher
|
||||
*/
|
||||
public class MethodInvokingTarget<T> implements Target<Object>, InitializingBean {
|
||||
|
||||
private Log logger = LogFactory.getLog(this.getClass());
|
||||
|
||||
private T object;
|
||||
|
||||
private String method;
|
||||
|
||||
private SimpleMethodInvoker<T> invoker;
|
||||
|
||||
private ArgumentListPreparer argumentListPreparer;
|
||||
|
||||
|
||||
public void setObject(T object) {
|
||||
Assert.notNull(object, "'object' must not be null");
|
||||
this.object = object;
|
||||
}
|
||||
|
||||
public void setMethod(String method) {
|
||||
Assert.notNull(method, "'method' must not be null");
|
||||
this.method = method;
|
||||
}
|
||||
|
||||
public void setArgumentListPreparer(ArgumentListPreparer argumentListPreparer) {
|
||||
this.argumentListPreparer = argumentListPreparer;
|
||||
}
|
||||
|
||||
public void afterPropertiesSet() {
|
||||
this.invoker = new SimpleMethodInvoker<T>(this.object, this.method);
|
||||
}
|
||||
|
||||
public boolean send(Object object) {
|
||||
Object args[] = null;
|
||||
if (this.argumentListPreparer != null) {
|
||||
args = this.argumentListPreparer.prepare(object);
|
||||
}
|
||||
else {
|
||||
args = new Object[] { object };
|
||||
}
|
||||
Object result = this.invoker.invokeMethod(args);
|
||||
if (result != null && logger.isWarnEnabled()) {
|
||||
logger.warn("ignoring outbound channel adapter's return value");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
* Copyright 2002-2007 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.integration.adapter;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
/**
|
||||
* Interface for any external data source that can be polled.
|
||||
*
|
||||
* @author Mark Fisher
|
||||
*/
|
||||
public interface PollableSource<T> {
|
||||
|
||||
Collection<T> poll(int limit);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
/*
|
||||
* Copyright 2002-2007 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.integration.adapter;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
import org.springframework.integration.MessageHandlingException;
|
||||
import org.springframework.integration.bus.ConsumerPolicy;
|
||||
import org.springframework.integration.bus.MessageDispatcher;
|
||||
import org.springframework.integration.channel.MessageChannel;
|
||||
import org.springframework.integration.message.MessageMapper;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* A channel adapter that retrieves objects from a {@link PollableSource},
|
||||
* delegates to a {@link MessageMapper} to create messages from those objects,
|
||||
* and then sends the resulting messages to the provided {@link MessageChannel}.
|
||||
*
|
||||
* @author Mark Fisher
|
||||
*/
|
||||
public class PollingSourceAdapter<T> extends AbstractSourceAdapter<T> implements MessageDispatcher {
|
||||
|
||||
private static int DEFAULT_PERIOD = 1000;
|
||||
|
||||
private PollableSource<T> source;
|
||||
|
||||
private ConsumerPolicy policy = ConsumerPolicy.newPollingPolicy(DEFAULT_PERIOD);
|
||||
|
||||
|
||||
public PollingSourceAdapter(PollableSource<T> source) {
|
||||
Assert.notNull(source, "'source' must not be null");
|
||||
this.source = source;
|
||||
}
|
||||
|
||||
public void setPeriod(int period) {
|
||||
Assert.isTrue(period > 0, "'period' must be a positive value");
|
||||
this.policy.setPeriod(period);
|
||||
}
|
||||
|
||||
public void setMaxMessagesPerTask(int maxMessagesPerTask) {
|
||||
Assert.isTrue(maxMessagesPerTask > 0, "'maxMessagesPerTask' must be a positive value");
|
||||
this.policy.setMaxMessagesPerTask(maxMessagesPerTask);
|
||||
}
|
||||
|
||||
public ConsumerPolicy getConsumerPolicy() {
|
||||
return this.policy;
|
||||
}
|
||||
|
||||
public int dispatch() {
|
||||
int messagesProcessed = 0;
|
||||
int limit = this.policy.getMaxMessagesPerTask();
|
||||
Collection<T> results = this.source.poll(limit);
|
||||
if (results != null) {
|
||||
if (results.size() > limit) {
|
||||
throw new MessageHandlingException("source returned too many results, the limit is " + limit);
|
||||
}
|
||||
for (T next : results) {
|
||||
if (this.sendToChannel(next)) {
|
||||
messagesProcessed++;
|
||||
}
|
||||
}
|
||||
}
|
||||
return messagesProcessed;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
* Copyright 2002-2007 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.integration.adapter;
|
||||
|
||||
import org.springframework.integration.channel.MessageChannel;
|
||||
|
||||
/**
|
||||
* Base interface for source adapters.
|
||||
*
|
||||
* @author Mark Fisher
|
||||
*/
|
||||
public interface SourceAdapter {
|
||||
|
||||
void setChannel(MessageChannel channel);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
* Copyright 2002-2007 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.integration.adapter;
|
||||
|
||||
/**
|
||||
* Interface for any external target that may receive data from an outgoing
|
||||
* channel adapter.
|
||||
*
|
||||
* @author Mark Fisher
|
||||
*/
|
||||
public interface Target<T> {
|
||||
|
||||
boolean send(T t);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Copyright 2002-2007 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.integration.adapter;
|
||||
|
||||
import org.springframework.integration.bus.ConsumerPolicy;
|
||||
import org.springframework.integration.channel.MessageChannel;
|
||||
import org.springframework.integration.message.MessageReceiver;
|
||||
|
||||
/**
|
||||
* Base interface for target adapters.
|
||||
*
|
||||
* @author Mark Fisher
|
||||
*/
|
||||
public interface TargetAdapter<T> extends MessageReceiver<T> {
|
||||
|
||||
String getName();
|
||||
|
||||
void setChannel(MessageChannel channel);
|
||||
|
||||
ConsumerPolicy getConsumerPolicy();
|
||||
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
* Copyright 2002-2007 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.integration.adapter.event;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.context.ApplicationEvent;
|
||||
import org.springframework.context.ApplicationListener;
|
||||
import org.springframework.integration.adapter.AbstractSourceAdapter;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
|
||||
/**
|
||||
* A source adapter for passing Spring
|
||||
* {@link ApplicationEvent ApplicationEvents} within messages.
|
||||
*
|
||||
* @author Mark Fisher
|
||||
*/
|
||||
public class ApplicationEventSourceAdapter extends AbstractSourceAdapter<ApplicationEvent> implements
|
||||
ApplicationListener {
|
||||
|
||||
private List<Class<? extends ApplicationEvent>> eventTypes = new ArrayList<Class<? extends ApplicationEvent>>();
|
||||
|
||||
|
||||
/**
|
||||
* Set the list of event types (classes that extend ApplicationEvent) that
|
||||
* this adapter should send to the message channel. By default, all event
|
||||
* types will be sent.
|
||||
*/
|
||||
public void setEventTypes(List<Class<? extends ApplicationEvent>> eventTypes) {
|
||||
Assert.notEmpty(eventTypes, "at least one event type is required");
|
||||
this.eventTypes = eventTypes;
|
||||
}
|
||||
|
||||
public void onApplicationEvent(ApplicationEvent event) {
|
||||
if (CollectionUtils.isEmpty(this.eventTypes)) {
|
||||
this.sendToChannel(event);
|
||||
return;
|
||||
}
|
||||
for (Class<? extends ApplicationEvent> eventType : this.eventTypes) {
|
||||
if (eventType.isAssignableFrom(event.getClass())) {
|
||||
this.sendToChannel(event);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
* Copyright 2002-2007 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.integration.adapter.event;
|
||||
|
||||
import org.springframework.context.ApplicationEventPublisher;
|
||||
import org.springframework.context.ApplicationEventPublisherAware;
|
||||
import org.springframework.integration.adapter.AbstractTargetAdapter;
|
||||
|
||||
/**
|
||||
* A target adapter for publishing {@link MessagingEvent MessagingEvents}. The
|
||||
* {@link MessagingEvent} is a subclass of Spring's {@link ApplicationEvent}
|
||||
* used by this adapter to wrap any {@link Message} received on its channel.
|
||||
*
|
||||
* @author Mark Fisher
|
||||
*/
|
||||
public class ApplicationEventTargetAdapter extends AbstractTargetAdapter<MessagingEvent> implements
|
||||
ApplicationEventPublisherAware {
|
||||
|
||||
private ApplicationEventPublisher applicationEventPublisher;
|
||||
|
||||
|
||||
public ApplicationEventTargetAdapter() {
|
||||
this.setMessageMapper(new MessagingEventMapper());
|
||||
}
|
||||
|
||||
|
||||
public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {
|
||||
this.applicationEventPublisher = applicationEventPublisher;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean sendToTarget(MessagingEvent event) {
|
||||
this.applicationEventPublisher.publishEvent(event);
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* Copyright 2002-2007 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.integration.adapter.event;
|
||||
|
||||
import org.springframework.context.ApplicationEvent;
|
||||
import org.springframework.integration.message.Message;
|
||||
|
||||
/**
|
||||
* A subclass of {@link ApplicationEvent} that wraps a {@link Message}.
|
||||
*
|
||||
* @author Mark Fisher
|
||||
*/
|
||||
public class MessagingEvent<T> extends ApplicationEvent {
|
||||
|
||||
public MessagingEvent(Message<T> message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
public Message<T> getMessage() {
|
||||
return (Message<T>) this.getSource();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* Copyright 2002-2007 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.integration.adapter.event;
|
||||
|
||||
import org.springframework.integration.message.Message;
|
||||
import org.springframework.integration.message.MessageMapper;
|
||||
|
||||
/**
|
||||
* A {@link MessageMapper} implementation for mapping to and from
|
||||
* {@link MessagingEvent MessagingEvents}.
|
||||
*
|
||||
* @author Mark Fisher
|
||||
*/
|
||||
public class MessagingEventMapper<T> implements MessageMapper<T, MessagingEvent<T>> {
|
||||
|
||||
public MessagingEvent<T> fromMessage(Message<T> message) {
|
||||
return new MessagingEvent<T>(message);
|
||||
}
|
||||
|
||||
public Message<T> toMessage(MessagingEvent<T> event) {
|
||||
return event.getMessage();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,101 @@
|
||||
/*
|
||||
* Copyright 2002-2007 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.integration.adapter.file;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileReader;
|
||||
import java.io.FileWriter;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import org.springframework.integration.MessageHandlingException;
|
||||
import org.springframework.integration.message.AbstractMessageMapper;
|
||||
import org.springframework.integration.message.GenericMessage;
|
||||
import org.springframework.integration.message.Message;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.FileCopyUtils;
|
||||
|
||||
/**
|
||||
* Base class providing common behavior for file-based message mappers.
|
||||
*
|
||||
* @author Mark Fisher
|
||||
*/
|
||||
public abstract class AbstractFileMapper<T> extends AbstractMessageMapper<T, File> {
|
||||
|
||||
protected Log logger = LogFactory.getLog(this.getClass());
|
||||
|
||||
private File parentDirectory;
|
||||
|
||||
private File backupDirectory;
|
||||
|
||||
private FileNameGenerator fileNameGenerator = new DefaultFileNameGenerator();
|
||||
|
||||
|
||||
public AbstractFileMapper(File parentDirectory) {
|
||||
this.parentDirectory = parentDirectory;
|
||||
}
|
||||
|
||||
public void setBackupDirectory(File backupDirectory) {
|
||||
this.backupDirectory = backupDirectory;
|
||||
}
|
||||
|
||||
public void setFileNameGenerator(FileNameGenerator fileNameGenerator) {
|
||||
Assert.notNull(fileNameGenerator, "'fileNameGenerator' must not be null");
|
||||
this.fileNameGenerator = fileNameGenerator;
|
||||
}
|
||||
|
||||
public File fromMessage(Message<T> message) {
|
||||
try {
|
||||
File file = new File(parentDirectory, this.fileNameGenerator.generateFileName(message));
|
||||
this.writeToFile(file, message.getPayload());
|
||||
return file;
|
||||
}
|
||||
catch (Exception e) {
|
||||
throw new MessageHandlingException("failure occurred mapping file to message", e);
|
||||
}
|
||||
}
|
||||
|
||||
public Message<T> toMessage(File file) {
|
||||
try {
|
||||
T payload = this.readMessagePayload(file);
|
||||
if (payload == null) {
|
||||
return null;
|
||||
}
|
||||
Message<T> message = new GenericMessage<T>(this.getUidGenerator().generateUid(), payload);
|
||||
if (this.backupDirectory != null) {
|
||||
FileWriter writer = new FileWriter(this.backupDirectory.getAbsolutePath() +
|
||||
File.separator + file.getName());
|
||||
FileCopyUtils.copy(new FileReader(file), writer);
|
||||
}
|
||||
file.delete();
|
||||
return message;
|
||||
}
|
||||
catch (Exception e) {
|
||||
String errorMessage = "failure occurred mapping file to message";
|
||||
if (logger.isWarnEnabled()) {
|
||||
logger.warn(errorMessage, e);
|
||||
}
|
||||
throw new MessageHandlingException(errorMessage, e);
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract T readMessagePayload(File file) throws Exception;
|
||||
|
||||
protected abstract void writeToFile(File file, T payload) throws Exception;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* Copyright 2002-2007 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.integration.adapter.file;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
import org.springframework.util.FileCopyUtils;
|
||||
|
||||
/**
|
||||
* A {@link org.springframework.integration.message.MessageMapper}
|
||||
* implementation for messages with a byte array payload.
|
||||
*
|
||||
* @author Mark Fisher
|
||||
*/
|
||||
public class ByteArrayFileMapper extends AbstractFileMapper<byte[]> {
|
||||
|
||||
public ByteArrayFileMapper(File parentDirectory) {
|
||||
super(parentDirectory);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected byte[] readMessagePayload(File file) throws Exception {
|
||||
return FileCopyUtils.copyToByteArray(file);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void writeToFile(File file, byte[] payload) throws Exception {
|
||||
FileCopyUtils.copy(payload, file);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Copyright 2002-2007 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.integration.adapter.file;
|
||||
|
||||
import org.springframework.integration.message.Message;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* Default implementation of the filename generator strategy. Concatenates the
|
||||
* message id and the current timestamp.
|
||||
*
|
||||
* @author Mark Fisher
|
||||
*/
|
||||
public class DefaultFileNameGenerator implements FileNameGenerator {
|
||||
|
||||
public String generateFileName(Message<?> message) {
|
||||
String filenameProperty = message.getHeader().getProperty(FILENAME_PROPERTY_KEY);
|
||||
return StringUtils.hasText(filenameProperty) ?
|
||||
filenameProperty : message.getId() + "-" + System.currentTimeMillis() + ".msg";
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* Copyright 2002-2007 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.integration.adapter.file;
|
||||
|
||||
import org.springframework.integration.message.Message;
|
||||
|
||||
/**
|
||||
* Strategy interface for generating a file name from a message.
|
||||
*
|
||||
* @author Mark Fisher
|
||||
*/
|
||||
public interface FileNameGenerator {
|
||||
|
||||
String FILENAME_PROPERTY_KEY = "filename";
|
||||
|
||||
|
||||
String generateFileName(Message<?> message);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
/*
|
||||
* Copyright 2002-2007 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.integration.adapter.file;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileFilter;
|
||||
import java.io.FilenameFilter;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.integration.MessageHandlingException;
|
||||
import org.springframework.integration.adapter.PollableSource;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* A messaging source that polls a directory to retrieve files.
|
||||
*
|
||||
* @author Mark Fisher
|
||||
*/
|
||||
public class FileSource implements PollableSource<File> {
|
||||
|
||||
private File directory;
|
||||
|
||||
private FileFilter fileFilter;
|
||||
|
||||
private FilenameFilter filenameFilter;
|
||||
|
||||
|
||||
public FileSource(File directory) {
|
||||
Assert.notNull("directory must not be null");
|
||||
this.directory = directory;
|
||||
}
|
||||
|
||||
public void setFileFilter(FileFilter fileFilter) {
|
||||
this.fileFilter = fileFilter;
|
||||
}
|
||||
|
||||
public void setFilenameFilter(FilenameFilter filenameFilter) {
|
||||
this.filenameFilter = filenameFilter;
|
||||
}
|
||||
|
||||
public Collection<File> poll(int limit) {
|
||||
File[] files = null;
|
||||
if (this.fileFilter != null) {
|
||||
files = this.directory.listFiles(fileFilter);
|
||||
}
|
||||
else if (this.filenameFilter != null) {
|
||||
files = this.directory.listFiles(filenameFilter);
|
||||
}
|
||||
else {
|
||||
files = this.directory.listFiles();
|
||||
}
|
||||
if (files == null) {
|
||||
throw new MessageHandlingException("Problem occurred while polling for files. " +
|
||||
"Is '" + directory.getAbsolutePath() + "' a directory?");
|
||||
}
|
||||
int size = Math.min(limit, files.length);
|
||||
List<File> results = new ArrayList<File>(size);
|
||||
for (int i = 0; i < size; i++) {
|
||||
results.add(files[i]);
|
||||
}
|
||||
return results;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
* Copyright 2002-2007 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.integration.adapter.file;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
import org.springframework.integration.adapter.PollingSourceAdapter;
|
||||
import org.springframework.integration.channel.MessageChannel;
|
||||
import org.springframework.integration.message.MessageMapper;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Channel adapter for polling a directory and creating messages from its files.
|
||||
*
|
||||
* @author Mark Fisher
|
||||
*/
|
||||
public class FileSourceAdapter extends PollingSourceAdapter<File> {
|
||||
|
||||
public FileSourceAdapter(File directory, MessageChannel channel, int period) {
|
||||
this(directory, channel, period, true);
|
||||
}
|
||||
|
||||
public FileSourceAdapter(File directory, MessageChannel channel, int period, boolean isTextBased) {
|
||||
super(new FileSource(directory));
|
||||
this.setChannel(channel);
|
||||
this.setPeriod(period);
|
||||
if (isTextBased) {
|
||||
this.setMessageMapper(new TextFileMapper(directory));
|
||||
}
|
||||
else {
|
||||
this.setMessageMapper(new ByteArrayFileMapper(directory));
|
||||
}
|
||||
}
|
||||
|
||||
public void setFileNameGenerator(FileNameGenerator fileNameGenerator) {
|
||||
Assert.notNull(fileNameGenerator, "'fileNameGenerator' must not be null");
|
||||
MessageMapper<?,?> mapper = this.getMessageMapper();
|
||||
if (mapper instanceof AbstractFileMapper<?>) {
|
||||
((AbstractFileMapper<?>) mapper).setFileNameGenerator(fileNameGenerator);
|
||||
}
|
||||
}
|
||||
|
||||
public void setBackupDirectory(File backupDirectory) {
|
||||
Assert.notNull(backupDirectory, "'backupDirectory' must not be null");
|
||||
MessageMapper<?, File> mapper = this.getMessageMapper();
|
||||
if (mapper != null && (mapper instanceof AbstractFileMapper<?>)) {
|
||||
((AbstractFileMapper<?>) mapper).setBackupDirectory(backupDirectory);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
* Copyright 2002-2007 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.integration.adapter.file;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
import org.springframework.integration.adapter.AbstractTargetAdapter;
|
||||
import org.springframework.integration.message.MessageMapper;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* A convenience adapter for writing files. The actual file writing occurs in
|
||||
* the message mapper ({@link TextFileMapper} or {@link ByteArrayFileMapper}).
|
||||
*
|
||||
* @author Mark Fisher
|
||||
*/
|
||||
public class FileTargetAdapter extends AbstractTargetAdapter<File> {
|
||||
|
||||
public FileTargetAdapter(File directory) {
|
||||
this(directory, true);
|
||||
}
|
||||
|
||||
public FileTargetAdapter(File directory, boolean isTextBased) {
|
||||
if (isTextBased) {
|
||||
this.setMessageMapper(new TextFileMapper(directory));
|
||||
}
|
||||
else {
|
||||
this.setMessageMapper(new ByteArrayFileMapper(directory));
|
||||
}
|
||||
}
|
||||
|
||||
public void setFileNameGenerator(FileNameGenerator fileNameGenerator) {
|
||||
Assert.notNull(fileNameGenerator, "'fileNameGenerator' must not be null");
|
||||
MessageMapper<?,?> mapper = this.getMessageMapper();
|
||||
if (mapper instanceof AbstractFileMapper<?>) {
|
||||
((AbstractFileMapper<?>) mapper).setFileNameGenerator(fileNameGenerator);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean sendToTarget(File file) {
|
||||
return file.exists();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
* Copyright 2002-2007 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.integration.adapter.file;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileReader;
|
||||
import java.io.FileWriter;
|
||||
|
||||
import org.springframework.util.FileCopyUtils;
|
||||
|
||||
/**
|
||||
* A {@link org.springframework.integration.message.MessageMapper}
|
||||
* implementation for messages with a String payload.
|
||||
*
|
||||
* @author Mark Fisher
|
||||
*/
|
||||
public class TextFileMapper extends AbstractFileMapper<String> {
|
||||
|
||||
public TextFileMapper(File parentDirectory) {
|
||||
super(parentDirectory);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected String readMessagePayload(File file) throws Exception {
|
||||
return FileCopyUtils.copyToString(new FileReader(file));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void writeToFile(File file, String payload) throws Exception {
|
||||
FileCopyUtils.copy(payload, new FileWriter(file));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
* Copyright 2002-2007 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.integration.adapter.file.config;
|
||||
|
||||
import org.w3c.dom.Element;
|
||||
|
||||
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
|
||||
import org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser;
|
||||
import org.springframework.integration.adapter.file.FileSourceAdapter;
|
||||
|
||||
/**
|
||||
* Parser for the <file-source/> element.
|
||||
*
|
||||
* @author Mark Fisher
|
||||
*/
|
||||
public class FileSourceAdapterParser extends AbstractSingleBeanDefinitionParser {
|
||||
|
||||
protected Class getBeanClass(Element element) {
|
||||
return FileSourceAdapter.class;
|
||||
}
|
||||
|
||||
protected boolean shouldGenerateId() {
|
||||
return true;
|
||||
}
|
||||
|
||||
protected void doParse(Element element, BeanDefinitionBuilder builder) {
|
||||
String directory = element.getAttribute("directory");
|
||||
String channel = element.getAttribute("channel");
|
||||
String pollPeriod = element.getAttribute("poll-period");
|
||||
builder.addConstructorArg(directory);
|
||||
builder.addConstructorArgReference(channel);
|
||||
builder.addConstructorArg(pollPeriod);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* Copyright 2002-2007 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.integration.adapter.file.config;
|
||||
|
||||
import org.w3c.dom.Element;
|
||||
|
||||
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
|
||||
import org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser;
|
||||
import org.springframework.integration.adapter.file.FileTargetAdapter;
|
||||
|
||||
/**
|
||||
* Parser for the <file-target/> element.
|
||||
*
|
||||
* @author Mark Fisher
|
||||
*/
|
||||
public class FileTargetAdapterParser extends AbstractSingleBeanDefinitionParser {
|
||||
|
||||
protected Class getBeanClass(Element element) {
|
||||
return FileTargetAdapter.class;
|
||||
}
|
||||
|
||||
protected boolean shouldGenerateId() {
|
||||
return true;
|
||||
}
|
||||
|
||||
protected void doParse(Element element, BeanDefinitionBuilder builder) {
|
||||
String directory = element.getAttribute("directory");
|
||||
String channel = element.getAttribute("channel");
|
||||
builder.addConstructorArg(directory);
|
||||
builder.addPropertyReference("channel", channel);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,96 @@
|
||||
/*
|
||||
* Copyright 2002-2007 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.integration.adapter.jms;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
|
||||
import javax.jms.ConnectionFactory;
|
||||
import javax.jms.Destination;
|
||||
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.integration.MessagingConfigurationException;
|
||||
import org.springframework.integration.adapter.PollableSource;
|
||||
import org.springframework.jms.core.JmsTemplate;
|
||||
|
||||
/**
|
||||
* A source for receiving JMS Messages with a polling listener. This source is
|
||||
* only recommended for very low message volume. Otherwise, an event-driven
|
||||
* option that uses one of Spring's MessageListener containers is highly
|
||||
* recommended.
|
||||
*
|
||||
* @author Mark Fisher
|
||||
*/
|
||||
public class JmsPollableSource implements PollableSource<Object>, InitializingBean {
|
||||
|
||||
private ConnectionFactory connectionFactory;
|
||||
|
||||
private Destination destination;
|
||||
|
||||
private JmsTemplate jmsTemplate;
|
||||
|
||||
|
||||
public JmsPollableSource(JmsTemplate jmsTemplate) {
|
||||
this.jmsTemplate = jmsTemplate;
|
||||
}
|
||||
|
||||
public JmsPollableSource(ConnectionFactory connectionFactory, Destination destination) {
|
||||
this.connectionFactory = connectionFactory;
|
||||
this.destination = destination;
|
||||
this.initJmsTemplate();
|
||||
}
|
||||
|
||||
/**
|
||||
* No-arg constructor provided for convenience when configuring with
|
||||
* setters. Note that the initialization callback will validate.
|
||||
*/
|
||||
public JmsPollableSource() {
|
||||
}
|
||||
|
||||
public void setConnectionFactory(ConnectionFactory connectionFactory) {
|
||||
this.connectionFactory = connectionFactory;
|
||||
}
|
||||
|
||||
public void setDestination(Destination destination) {
|
||||
this.destination = destination;
|
||||
}
|
||||
|
||||
public void setJmsTemplate(JmsTemplate jmsTemplate) {
|
||||
this.jmsTemplate = jmsTemplate;
|
||||
}
|
||||
|
||||
public void afterPropertiesSet() {
|
||||
if (this.jmsTemplate == null) {
|
||||
if (this.connectionFactory == null || this.destination == null) {
|
||||
throw new MessagingConfigurationException("Either a 'jmsTemplate' or "
|
||||
+ "*both* 'connectionFactory' and 'destination' are required.");
|
||||
}
|
||||
this.initJmsTemplate();
|
||||
}
|
||||
}
|
||||
|
||||
private void initJmsTemplate() {
|
||||
this.jmsTemplate = new JmsTemplate();
|
||||
this.jmsTemplate.setConnectionFactory(this.connectionFactory);
|
||||
this.jmsTemplate.setDefaultDestination(this.destination);
|
||||
}
|
||||
|
||||
public Collection<Object> poll(int limit) {
|
||||
return Arrays.asList(this.jmsTemplate.receiveAndConvert());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* Copyright 2002-2007 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.integration.adapter.jms;
|
||||
|
||||
import javax.jms.ConnectionFactory;
|
||||
import javax.jms.Destination;
|
||||
|
||||
import org.springframework.integration.adapter.PollingSourceAdapter;
|
||||
import org.springframework.jms.core.JmsTemplate;
|
||||
|
||||
/**
|
||||
* A convenience adapter that wraps a {@link JmsPollableSource}.
|
||||
*
|
||||
* @author Mark Fisher
|
||||
*/
|
||||
public class JmsPollingSourceAdapter extends PollingSourceAdapter<Object> {
|
||||
|
||||
public JmsPollingSourceAdapter(ConnectionFactory connectionFactory, Destination destination) {
|
||||
super(new JmsPollableSource(connectionFactory, destination));
|
||||
}
|
||||
|
||||
public JmsPollingSourceAdapter(JmsTemplate jmsTemplate) {
|
||||
super(new JmsPollableSource(jmsTemplate));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,93 @@
|
||||
/*
|
||||
* Copyright 2002-2007 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.integration.adapter.jms;
|
||||
|
||||
import javax.jms.ConnectionFactory;
|
||||
import javax.jms.Destination;
|
||||
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.integration.MessagingConfigurationException;
|
||||
import org.springframework.integration.adapter.AbstractTargetAdapter;
|
||||
import org.springframework.jms.core.JmsTemplate;
|
||||
|
||||
/**
|
||||
* A target adapter for sending JMS Messages.
|
||||
*
|
||||
* @author Mark Fisher
|
||||
*/
|
||||
public class JmsTargetAdapter extends AbstractTargetAdapter<Object> implements InitializingBean {
|
||||
|
||||
private ConnectionFactory connectionFactory;
|
||||
|
||||
private Destination destination;
|
||||
|
||||
private JmsTemplate jmsTemplate;
|
||||
|
||||
|
||||
public JmsTargetAdapter(JmsTemplate jmsTemplate) {
|
||||
this.jmsTemplate = jmsTemplate;
|
||||
}
|
||||
|
||||
public JmsTargetAdapter(ConnectionFactory connectionFactory, Destination destination) {
|
||||
this.connectionFactory = connectionFactory;
|
||||
this.destination = destination;
|
||||
this.initJmsTemplate();
|
||||
}
|
||||
|
||||
/**
|
||||
* No-arg constructor provided for convenience when configuring with
|
||||
* setters. Note that the initialization callback will validate.
|
||||
*/
|
||||
public JmsTargetAdapter() {
|
||||
}
|
||||
|
||||
|
||||
public void setConnectionFactory(ConnectionFactory connectionFactory) {
|
||||
this.connectionFactory = connectionFactory;
|
||||
}
|
||||
|
||||
public void setDestination(Destination destination) {
|
||||
this.destination = destination;
|
||||
}
|
||||
|
||||
public void setJmsTemplate(JmsTemplate jmsTemplate) {
|
||||
this.jmsTemplate = jmsTemplate;
|
||||
}
|
||||
|
||||
public void afterPropertiesSet() {
|
||||
if (this.jmsTemplate == null) {
|
||||
if (this.connectionFactory == null || this.destination == null) {
|
||||
throw new MessagingConfigurationException("Either a 'jmsTemplate' or " +
|
||||
"*both* 'connectionFactory' and 'destination' are required.");
|
||||
}
|
||||
this.initJmsTemplate();
|
||||
}
|
||||
}
|
||||
|
||||
private void initJmsTemplate() {
|
||||
this.jmsTemplate = new JmsTemplate();
|
||||
this.jmsTemplate.setConnectionFactory(this.connectionFactory);
|
||||
this.jmsTemplate.setDefaultDestination(this.destination);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean sendToTarget(Object object) {
|
||||
this.jmsTemplate.convertAndSend(object);
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,82 @@
|
||||
/*
|
||||
* Copyright 2002-2007 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.integration.adapter.jms.config;
|
||||
|
||||
import org.w3c.dom.Element;
|
||||
|
||||
import org.springframework.beans.factory.BeanCreationException;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
|
||||
import org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser;
|
||||
import org.springframework.integration.adapter.jms.JmsTargetAdapter;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* Parser for the <jms-target/> element.
|
||||
*
|
||||
* @author Mark Fisher
|
||||
*/
|
||||
public class JmsTargetAdapterParser extends AbstractSingleBeanDefinitionParser {
|
||||
|
||||
private static final String JMS_TEMPLATE_ATTRIBUTE = "jms-template";
|
||||
|
||||
private static final String JMS_TEMPLATE_PROPERTY = "jmsTemplate";
|
||||
|
||||
private static final String CONNECTION_FACTORY_ATTRIBUTE = "connection-factory";
|
||||
|
||||
private static final String CONNECTION_FACTORY_PROPERTY = "connectionFactory";
|
||||
|
||||
private static final String DESTINATION_ATTRIBUTE = "destination";
|
||||
|
||||
private static final String DESTINATION_PROPERTY = "destination";
|
||||
|
||||
private static final String CHANNEL_ATTRIBUTE = "channel";
|
||||
|
||||
private static final String CHANNEL_PROPERTY = "channel";
|
||||
|
||||
|
||||
protected Class<?> getBeanClass(Element element) {
|
||||
return JmsTargetAdapter.class;
|
||||
}
|
||||
|
||||
protected boolean shouldGenerateId() {
|
||||
return true;
|
||||
}
|
||||
|
||||
protected void doParse(Element element, BeanDefinitionBuilder builder) {
|
||||
String jmsTemplate = element.getAttribute(JMS_TEMPLATE_ATTRIBUTE);
|
||||
String connectionFactory = element.getAttribute(CONNECTION_FACTORY_ATTRIBUTE);
|
||||
String destination = element.getAttribute(DESTINATION_ATTRIBUTE);
|
||||
if (StringUtils.hasText(jmsTemplate)) {
|
||||
if (StringUtils.hasText(connectionFactory) || StringUtils.hasText(destination)) {
|
||||
throw new BeanCreationException("when providing a 'jms-template' reference, neither " +
|
||||
"'connection-factory' or 'destination' should be provided.");
|
||||
}
|
||||
builder.addPropertyReference(JMS_TEMPLATE_PROPERTY, jmsTemplate);
|
||||
}
|
||||
else if (StringUtils.hasText(connectionFactory) && StringUtils.hasText(destination)) {
|
||||
builder.addPropertyReference(CONNECTION_FACTORY_PROPERTY, connectionFactory);
|
||||
builder.addPropertyReference(DESTINATION_PROPERTY, destination);
|
||||
}
|
||||
else {
|
||||
throw new BeanCreationException("either a 'jms-template' reference or both " +
|
||||
"'connection-factory' and 'destination' references must be provided.");
|
||||
}
|
||||
String channel = element.getAttribute(CHANNEL_ATTRIBUTE);
|
||||
builder.addPropertyReference(CHANNEL_PROPERTY, channel);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* Copyright 2002-2007 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.annotation;
|
||||
|
||||
import java.lang.annotation.Documented;
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Inherited;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
|
||||
import org.springframework.integration.message.Message;
|
||||
|
||||
/**
|
||||
* Indicates that a method is capable of sending messages. The method must
|
||||
* accept a single parameter that is either a {@link Message} or an Object to
|
||||
* be passed as a message payload. The enclosing class should be annotated with
|
||||
* {@link MessageEndpoint @MessageEndpoint}.
|
||||
*
|
||||
* @author Mark Fisher
|
||||
*/
|
||||
@java.lang.annotation.Target(ElementType.METHOD)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Inherited
|
||||
@Documented
|
||||
public @interface DefaultOutput {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* Copyright 2002-2007 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.annotation;
|
||||
|
||||
import java.lang.annotation.Documented;
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Inherited;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
|
||||
/**
|
||||
* Indicates that a method is capable of handling a message or message payload.
|
||||
* The method may only accept a single parameter, and the enclosing class should
|
||||
* be annotated with {@link MessageEndpoint @MessageEndpoint}.
|
||||
*
|
||||
* @author Mark Fisher
|
||||
*/
|
||||
@Target({ElementType.METHOD, ElementType.ANNOTATION_TYPE})
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Inherited
|
||||
@Documented
|
||||
public @interface Handler {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* Copyright 2002-2007 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.annotation;
|
||||
|
||||
import java.lang.annotation.Documented;
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Inherited;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* Indicates that a class is capable of serving as a message endpoint.
|
||||
*
|
||||
* @author Mark Fisher
|
||||
*/
|
||||
@Target(ElementType.TYPE)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Inherited
|
||||
@Documented
|
||||
@Component
|
||||
public @interface MessageEndpoint {
|
||||
|
||||
String input() default "";
|
||||
|
||||
String defaultOutput() default "";
|
||||
|
||||
int pollPeriod() default 0;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* Copyright 2002-2007 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.annotation;
|
||||
|
||||
import java.lang.annotation.Documented;
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Inherited;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* Indicates that a method is capable of providing messages. The method must not
|
||||
* accept any parameters but can return either a single object or collection.
|
||||
* The enclosing class should be annotated with
|
||||
* {@link MessageEndpoint @MessageEndpoint}.
|
||||
*
|
||||
* @author Mark Fisher
|
||||
*/
|
||||
@Target(ElementType.METHOD)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Inherited
|
||||
@Documented
|
||||
public @interface Polled {
|
||||
|
||||
int period() default 1000;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* Copyright 2002-2007 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.annotation;
|
||||
|
||||
import java.lang.annotation.Documented;
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Inherited;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* Indicates that the method's return value should be published to the specified
|
||||
* channel. The value will only be published if non-null.
|
||||
*
|
||||
* @author Mark Fisher
|
||||
*/
|
||||
@Target(ElementType.METHOD)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Inherited
|
||||
@Documented
|
||||
public @interface Publisher {
|
||||
|
||||
String channel();
|
||||
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
* Copyright 2002-2007 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.annotation;
|
||||
|
||||
import java.lang.annotation.Documented;
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Inherited;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* Indicates that a method is capable of resolving to a channel or channel name
|
||||
* based on a message, message payload, message attribute, or message property.
|
||||
*
|
||||
* @author Mark Fisher
|
||||
*/
|
||||
@Target(ElementType.METHOD)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Inherited
|
||||
@Documented
|
||||
@Handler
|
||||
public @interface Router {
|
||||
|
||||
/**
|
||||
* String value representing the name of the property that should be passed
|
||||
* into the router method. This and 'attribute' should not both be provided.
|
||||
*/
|
||||
String property() default "";
|
||||
|
||||
/**
|
||||
* String value representing the name of the attribute that should be passed
|
||||
* into the router method. This and 'property' should not both be provided.
|
||||
*/
|
||||
String attribute() default "";
|
||||
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* Copyright 2002-2007 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.annotation;
|
||||
|
||||
import java.lang.annotation.Documented;
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* Indicates that a method is capable of splitting a single message or message
|
||||
* payload to produce multiple messages which are then sent to the channel whose
|
||||
* name is provided with the 'channel' attribute.
|
||||
*
|
||||
* @author Mark Fisher
|
||||
*/
|
||||
@Target(ElementType.METHOD)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Documented
|
||||
@Handler
|
||||
public @interface Splitter {
|
||||
|
||||
String channel();
|
||||
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* Copyright 2002-2007 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.annotation;
|
||||
|
||||
import java.lang.annotation.Documented;
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Inherited;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* Indicates that a method-invoking handler adapter should delegate to this
|
||||
* method.
|
||||
*
|
||||
* @author Mark Fisher
|
||||
*/
|
||||
@Target(ElementType.METHOD)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Inherited
|
||||
@Documented
|
||||
public @interface Subscriber {
|
||||
|
||||
String channel();
|
||||
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
/*
|
||||
* Copyright 2002-2007 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.aop;
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
import org.aopalliance.intercept.MethodInvocation;
|
||||
|
||||
import org.springframework.aop.support.AopUtils;
|
||||
import org.springframework.core.annotation.AnnotationUtils;
|
||||
import org.springframework.integration.channel.ChannelRegistry;
|
||||
import org.springframework.integration.channel.MessageChannel;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* {@link MessagePublishingInterceptor} that resolves the channel from the
|
||||
* publisher annotation of the invoked method.
|
||||
*
|
||||
* @author Mark Fisher
|
||||
*/
|
||||
public class AnnotationAwareMessagePublishingInterceptor extends MessagePublishingInterceptor {
|
||||
|
||||
private Class<? extends Annotation> publisherAnnotationType;
|
||||
|
||||
private String channelAttributeName;
|
||||
|
||||
private ChannelRegistry channelRegistry;
|
||||
|
||||
|
||||
public AnnotationAwareMessagePublishingInterceptor(Class<? extends Annotation> publisherAnnotationType,
|
||||
String channelAttributeName, ChannelRegistry channelRegistry) {
|
||||
Assert.notNull(publisherAnnotationType, "'publisherAnnotationType' must not be null");
|
||||
Assert.notNull(channelAttributeName, "'channelAttributeName' must not be null");
|
||||
Assert.notNull(channelRegistry, "'channelRegistry' must not be null");
|
||||
this.publisherAnnotationType = publisherAnnotationType;
|
||||
this.channelAttributeName = channelAttributeName;
|
||||
this.channelRegistry = channelRegistry;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected MessageChannel resolveChannel(MethodInvocation invocation) {
|
||||
Class<?> targetClass = AopUtils.getTargetClass(invocation.getThis());
|
||||
Method method = AopUtils.getMostSpecificMethod(invocation.getMethod(), targetClass);
|
||||
Annotation annotation = AnnotationUtils.getAnnotation(method, this.publisherAnnotationType);
|
||||
if (annotation != null) {
|
||||
String channelName = (String) AnnotationUtils.getValue(annotation, this.channelAttributeName);
|
||||
if (channelName != null) {
|
||||
MessageChannel channel = this.channelRegistry.lookupChannel(channelName);
|
||||
if (channel != null) {
|
||||
return channel;
|
||||
}
|
||||
}
|
||||
}
|
||||
return super.resolveChannel(invocation);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,86 @@
|
||||
/*
|
||||
* Copyright 2002-2007 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.aop;
|
||||
|
||||
import org.aopalliance.intercept.MethodInterceptor;
|
||||
import org.aopalliance.intercept.MethodInvocation;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import org.springframework.integration.channel.MessageChannel;
|
||||
import org.springframework.integration.message.MessageMapper;
|
||||
import org.springframework.integration.message.SimplePayloadMessageMapper;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Interceptor that publishes a target method's return value to a channel.
|
||||
*
|
||||
* @author Mark Fisher
|
||||
*/
|
||||
public class MessagePublishingInterceptor implements MethodInterceptor {
|
||||
|
||||
protected Log logger = LogFactory.getLog(getClass());
|
||||
|
||||
private MessageMapper mapper = new SimplePayloadMessageMapper();
|
||||
|
||||
private MessageChannel defaultChannel;
|
||||
|
||||
|
||||
public void setDefaultChannel(MessageChannel defaultChannel) {
|
||||
this.defaultChannel = defaultChannel;
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify the {@link MessageMapper} to use when creating a message from the
|
||||
* return value Object. The default is a {@link SimplePayloadMessageMapper}.
|
||||
*
|
||||
* @param mapper the mapper to use
|
||||
*/
|
||||
public void setMessageMapper(MessageMapper mapper) {
|
||||
Assert.notNull(mapper, "mapper must not be null");
|
||||
this.mapper = mapper;
|
||||
}
|
||||
|
||||
/**
|
||||
* Invoke the target method and publish its return value.
|
||||
*/
|
||||
public Object invoke(MethodInvocation invocation) throws Throwable {
|
||||
Object retval = invocation.proceed();
|
||||
if (retval != null) {
|
||||
MessageChannel channel = this.resolveChannel(invocation);
|
||||
if (channel == null) {
|
||||
if (logger.isWarnEnabled()) {
|
||||
logger.warn("unable to resolve channel for intercepted method '" +
|
||||
invocation.getMethod().getName() + "'");
|
||||
}
|
||||
}
|
||||
else {
|
||||
channel.send(mapper.toMessage(retval));
|
||||
}
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
/**
|
||||
* Subclasses may override this method to provide custom behavior.
|
||||
*/
|
||||
protected MessageChannel resolveChannel(MethodInvocation invocation) {
|
||||
return this.defaultChannel;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
* Copyright 2002-2007 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.aop;
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
|
||||
import org.aopalliance.aop.Advice;
|
||||
|
||||
import org.springframework.aop.Pointcut;
|
||||
import org.springframework.aop.support.AbstractPointcutAdvisor;
|
||||
import org.springframework.aop.support.annotation.AnnotationMatchingPointcut;
|
||||
import org.springframework.integration.annotation.Publisher;
|
||||
import org.springframework.integration.channel.ChannelRegistry;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Advisor whose pointcut matches a method annotation and whose advice will
|
||||
* publish a message to the channel provided by that annotation.
|
||||
*
|
||||
* @author Mark Fisher
|
||||
* @see Publisher
|
||||
* @see AnnotationAwareMessagePublishingInterceptor
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
public class PublisherAnnotationAdvisor extends AbstractPointcutAdvisor {
|
||||
|
||||
private AnnotationAwareMessagePublishingInterceptor advice;
|
||||
|
||||
private AnnotationMatchingPointcut pointcut;
|
||||
|
||||
|
||||
public PublisherAnnotationAdvisor(ChannelRegistry channelRegistry) {
|
||||
this(Publisher.class, "channel", channelRegistry);
|
||||
}
|
||||
|
||||
public PublisherAnnotationAdvisor(Class<? extends Annotation> publisherAnnotationType, String channelNameAttribute,
|
||||
ChannelRegistry channelRegistry) {
|
||||
Assert.notNull(publisherAnnotationType, "'publisherAnnotationType' must not be null");
|
||||
Assert.notNull(channelNameAttribute, "'channelNameAttribute' must not be null");
|
||||
Assert.notNull(channelRegistry, "'channelRegistry' must not be null");
|
||||
this.pointcut = AnnotationMatchingPointcut.forMethodAnnotation(publisherAnnotationType);
|
||||
this.advice = new AnnotationAwareMessagePublishingInterceptor(publisherAnnotationType, channelNameAttribute,
|
||||
channelRegistry);
|
||||
}
|
||||
|
||||
|
||||
public Pointcut getPointcut() {
|
||||
return this.pointcut;
|
||||
}
|
||||
|
||||
public Advice getAdvice() {
|
||||
return this.advice;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
/*
|
||||
* Copyright 2002-2007 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.bus;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CopyOnWriteArrayList;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import org.springframework.integration.message.Message;
|
||||
|
||||
/**
|
||||
* Abstract base class for message dispatchers. Delegates to a
|
||||
* {@link MessageRetriever} strategy.
|
||||
*
|
||||
* @author Mark Fisher
|
||||
*/
|
||||
public abstract class AbstractMessageDispatcher implements MessageDispatcher {
|
||||
|
||||
protected Log logger = LogFactory.getLog(this.getClass());
|
||||
|
||||
private MessageRetriever retriever;
|
||||
|
||||
private List<MessageReceivingExecutor> executors = new CopyOnWriteArrayList<MessageReceivingExecutor>();
|
||||
|
||||
|
||||
public AbstractMessageDispatcher(MessageRetriever retriever) {
|
||||
this.retriever = retriever;
|
||||
}
|
||||
|
||||
|
||||
public void addExecutor(MessageReceivingExecutor executor) {
|
||||
executor.start();
|
||||
this.executors.add(executor);
|
||||
}
|
||||
|
||||
protected List<MessageReceivingExecutor> getExecutors() {
|
||||
return this.executors;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves messages and dispatches to the executors.
|
||||
*
|
||||
* @return the number of messages processed
|
||||
*/
|
||||
public int dispatch() {
|
||||
int messagesProcessed = 0;
|
||||
Collection<Message<?>> messages = this.retriever.retrieveMessages();
|
||||
if (messages == null) {
|
||||
return 0;
|
||||
}
|
||||
for (Message<?> message : messages) {
|
||||
if (dispatchMessage(message)) {
|
||||
messagesProcessed++;
|
||||
}
|
||||
}
|
||||
return messagesProcessed;
|
||||
}
|
||||
|
||||
|
||||
protected abstract boolean dispatchMessage(Message<?> message);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
* Copyright 2002-2007 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.bus;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.integration.channel.MessageChannel;
|
||||
import org.springframework.integration.message.Message;
|
||||
|
||||
/**
|
||||
* Message retriever that polls a {@link MessageChannel}. The number of
|
||||
* messages retrieved per poll is limited by the '<em>maxMessagesPerTask</em>'
|
||||
* property of the provided {@link ConsumerPolicy}, and the timeout for each
|
||||
* receive call is determined by the policy's '<em>receiveTimeout</em>'
|
||||
* property. In general, it is recommended to use a value of 1 for
|
||||
* 'maxMessagesPerTask' whenever a non-zero timeout is provided. Otherwise the
|
||||
* retriever may be holding on to available messages while waiting for
|
||||
* additional messages.
|
||||
*
|
||||
* @author Mark Fisher
|
||||
*/
|
||||
public class ChannelPollingMessageRetriever implements MessageRetriever {
|
||||
|
||||
private MessageChannel channel;
|
||||
|
||||
private ConsumerPolicy policy;
|
||||
|
||||
|
||||
public ChannelPollingMessageRetriever(MessageChannel channel, ConsumerPolicy policy) {
|
||||
this.channel = channel;
|
||||
this.policy = policy;
|
||||
}
|
||||
|
||||
|
||||
public Collection<Message<?>> retrieveMessages() {
|
||||
List<Message<?>> messages = new LinkedList<Message<?>>();
|
||||
while (messages.size() < this.policy.getMaxMessagesPerTask()) {
|
||||
Message<?> message = this.channel.receive(this.policy.getReceiveTimeout());
|
||||
if (message == null) {
|
||||
return messages;
|
||||
}
|
||||
messages.add(message);
|
||||
}
|
||||
return messages;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,170 @@
|
||||
/*
|
||||
* Copyright 2002-2007 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.bus;
|
||||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* A container for Message consumer configuration metadata.
|
||||
*
|
||||
* @author Mark Fisher
|
||||
*/
|
||||
public class ConsumerPolicy {
|
||||
|
||||
private static final int DEFAULT_CONCURRENCY = 1;
|
||||
|
||||
private static final int DEFAULT_MAX_CONCURRENCY = 10;
|
||||
|
||||
private static final int DEFAULT_MAX_MESSAGES_PER_TASK = 1;
|
||||
|
||||
private static final int DEFAULT_REJECTION_LIMIT = 10;
|
||||
|
||||
private static final int DEFAULT_REJECTION_LIMIT_WAIT = 1000;
|
||||
|
||||
private static final long DEFAULT_RECEIVE_TIMEOUT = 1000;
|
||||
|
||||
|
||||
private int concurrency = DEFAULT_CONCURRENCY;
|
||||
|
||||
private int maxConcurrency = DEFAULT_MAX_CONCURRENCY;
|
||||
|
||||
private int maxMessagesPerTask = DEFAULT_MAX_MESSAGES_PER_TASK;
|
||||
|
||||
private int rejectionLimit = DEFAULT_REJECTION_LIMIT;
|
||||
|
||||
private int rejectionLimitWait = DEFAULT_REJECTION_LIMIT_WAIT;
|
||||
|
||||
private int initialDelay = 0;
|
||||
|
||||
private int period = 5;
|
||||
|
||||
private TimeUnit timeUnit = TimeUnit.MILLISECONDS;
|
||||
|
||||
private boolean fixedRate = false;
|
||||
|
||||
private long receiveTimeout = DEFAULT_RECEIVE_TIMEOUT;
|
||||
|
||||
|
||||
/**
|
||||
* Factory method for a basic polling policy.
|
||||
*
|
||||
* @param period the polling interval
|
||||
*/
|
||||
public static ConsumerPolicy newPollingPolicy(int period) {
|
||||
Assert.isTrue(period > 0, "'period' must be a positive value");
|
||||
ConsumerPolicy policy = new ConsumerPolicy();
|
||||
policy.setPeriod(period);
|
||||
policy.setConcurrency(1);
|
||||
policy.setMaxConcurrency(1);
|
||||
return policy;
|
||||
}
|
||||
|
||||
public int getInitialDelay() {
|
||||
return this.initialDelay;
|
||||
}
|
||||
|
||||
public void setInitialDelay(int initialDelay) {
|
||||
this.initialDelay = initialDelay;
|
||||
}
|
||||
|
||||
public int getPeriod() {
|
||||
return this.period;
|
||||
}
|
||||
|
||||
public void setPeriod(int period) {
|
||||
this.period = period;
|
||||
}
|
||||
|
||||
public TimeUnit getTimeUnit() {
|
||||
return this.timeUnit;
|
||||
}
|
||||
|
||||
public void setTimeUnit(TimeUnit timeUnit) {
|
||||
this.timeUnit = timeUnit;
|
||||
}
|
||||
|
||||
public boolean isFixedRate() {
|
||||
return this.fixedRate;
|
||||
}
|
||||
|
||||
public void setFixedRate(boolean fixedRate) {
|
||||
this.fixedRate = fixedRate;
|
||||
}
|
||||
|
||||
public int getConcurrency() {
|
||||
return this.concurrency;
|
||||
}
|
||||
|
||||
public void setConcurrency(int concurrency) {
|
||||
if (concurrency < 1) {
|
||||
throw new IllegalArgumentException("'concurrency' value must be at least 1");
|
||||
}
|
||||
this.concurrency = concurrency;
|
||||
}
|
||||
|
||||
public int getMaxConcurrency() {
|
||||
return this.maxConcurrency;
|
||||
}
|
||||
|
||||
public void setMaxConcurrency(int maxConcurrency) {
|
||||
if (maxConcurrency < 1) {
|
||||
throw new IllegalArgumentException("'maxConcurrency' value must be at least 1");
|
||||
}
|
||||
this.maxConcurrency = maxConcurrency;
|
||||
}
|
||||
|
||||
public int getMaxMessagesPerTask() {
|
||||
return this.maxMessagesPerTask;
|
||||
}
|
||||
|
||||
public void setMaxMessagesPerTask(int maxMessagesPerTask) {
|
||||
if (maxMessagesPerTask == 0) {
|
||||
throw new IllegalArgumentException("'maxMessagesPerTask' must not be 0");
|
||||
}
|
||||
this.maxMessagesPerTask = maxMessagesPerTask;
|
||||
}
|
||||
|
||||
public int getRejectionLimit() {
|
||||
return this.rejectionLimit;
|
||||
}
|
||||
|
||||
public void setRejectionLimit(int rejectionLimit) {
|
||||
if (rejectionLimit < 1) {
|
||||
throw new IllegalArgumentException("'idleTaskExecutionLimit' must be at least 1");
|
||||
}
|
||||
this.rejectionLimit = rejectionLimit;
|
||||
}
|
||||
|
||||
public int getRejectionLimitWait() {
|
||||
return this.rejectionLimitWait;
|
||||
}
|
||||
|
||||
public void setRejectionLimitWait(int rejectionLimitWait) {
|
||||
this.rejectionLimitWait = rejectionLimitWait;
|
||||
}
|
||||
|
||||
public long getReceiveTimeout() {
|
||||
return this.receiveTimeout;
|
||||
}
|
||||
|
||||
public void setReceiveTimeout(long receiveTimeout) {
|
||||
this.receiveTimeout = receiveTimeout;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,366 @@
|
||||
/*
|
||||
* Copyright 2002-2007 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.bus;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.CopyOnWriteArrayList;
|
||||
import java.util.concurrent.ScheduledThreadPoolExecutor;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.ApplicationContextAware;
|
||||
import org.springframework.context.Lifecycle;
|
||||
import org.springframework.integration.MessagingException;
|
||||
import org.springframework.integration.adapter.AbstractTargetAdapter;
|
||||
import org.springframework.integration.adapter.SourceAdapter;
|
||||
import org.springframework.integration.adapter.TargetAdapter;
|
||||
import org.springframework.integration.channel.ChannelRegistry;
|
||||
import org.springframework.integration.channel.DefaultChannelRegistry;
|
||||
import org.springframework.integration.channel.MessageChannel;
|
||||
import org.springframework.integration.channel.PointToPointChannel;
|
||||
import org.springframework.integration.endpoint.MessageEndpoint;
|
||||
import org.springframework.integration.message.MessageReceiver;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* The messaging bus. Serves as a registry for channels and endpoints, manages their lifecycle,
|
||||
* and activates subscriptions.
|
||||
*
|
||||
* @author Mark Fisher
|
||||
*/
|
||||
public class MessageBus implements ChannelRegistry, ApplicationContextAware, Lifecycle {
|
||||
|
||||
private Log logger = LogFactory.getLog(this.getClass());
|
||||
|
||||
private ChannelRegistry channelRegistry = new DefaultChannelRegistry();
|
||||
|
||||
private Map<String, MessageEndpoint<?>> endpoints = new ConcurrentHashMap<String, MessageEndpoint<?>>();
|
||||
|
||||
private Map<String, TargetAdapter<?>> targetAdapters = new ConcurrentHashMap<String, TargetAdapter<?>>();
|
||||
|
||||
private List<DispatcherTask> dispatcherTasks = new CopyOnWriteArrayList<DispatcherTask>();
|
||||
|
||||
private Map<MessageReceiver<?>, MessageReceivingExecutor> receiverExecutors = new ConcurrentHashMap<MessageReceiver<?>, MessageReceivingExecutor>();
|
||||
|
||||
private ScheduledThreadPoolExecutor dispatcherExecutor;
|
||||
|
||||
private boolean autoCreateChannels;
|
||||
|
||||
private boolean running;
|
||||
|
||||
private Object lifecycleMonitor = new Object();
|
||||
|
||||
|
||||
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
|
||||
Assert.notNull(applicationContext, "applicationContext must not be null");
|
||||
this.registerChannels(applicationContext);
|
||||
this.registerEndpoints(applicationContext);
|
||||
this.registerSourceAdapters(applicationContext);
|
||||
this.registerTargetAdapters(applicationContext);
|
||||
this.activateSubscriptions(applicationContext);
|
||||
}
|
||||
|
||||
public void setAutoCreateChannels(boolean autoCreateChannels) {
|
||||
this.autoCreateChannels = autoCreateChannels;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private void registerChannels(ApplicationContext context) {
|
||||
Map<String, MessageChannel> channelBeans =
|
||||
(Map<String, MessageChannel>) context.getBeansOfType(MessageChannel.class);
|
||||
for (Map.Entry<String, MessageChannel> entry : channelBeans.entrySet()) {
|
||||
this.registerChannel(entry.getKey(), entry.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private void registerEndpoints(ApplicationContext context) {
|
||||
Map<String, MessageEndpoint> endpointBeans =
|
||||
(Map<String, MessageEndpoint>) context.getBeansOfType(MessageEndpoint.class);
|
||||
for (Map.Entry<String, MessageEndpoint> entry : endpointBeans.entrySet()) {
|
||||
this.registerEndpoint(entry.getKey(), entry.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private void registerSourceAdapters(ApplicationContext context) {
|
||||
Map<String, SourceAdapter> sourceAdapterBeans =
|
||||
(Map<String, SourceAdapter>) context.getBeansOfType(SourceAdapter.class);
|
||||
for (Map.Entry<String, SourceAdapter> entry : sourceAdapterBeans.entrySet()) {
|
||||
this.registerSourceAdapter(entry.getKey(), entry.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private void registerTargetAdapters(ApplicationContext context) {
|
||||
Map<String, TargetAdapter> targetAdapterBeans =
|
||||
(Map<String, TargetAdapter>) context.getBeansOfType(TargetAdapter.class);
|
||||
for (Map.Entry<String, TargetAdapter> entry : targetAdapterBeans.entrySet()) {
|
||||
this.registerTargetAdapter(entry.getKey(), entry.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private void activateSubscriptions(ApplicationContext context) {
|
||||
Map<String, Subscription> subscriptionBeans =
|
||||
(Map<String, Subscription>) context.getBeansOfType(Subscription.class);
|
||||
for (Subscription subscription : subscriptionBeans.values()) {
|
||||
this.activateSubscription(subscription);
|
||||
if (logger.isInfoEnabled()) {
|
||||
logger.info("activated subscription to channel '" + subscription.getChannel() +
|
||||
"' for endpoint '" + subscription.getEndpoint() + "'");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void initialize() {
|
||||
this.dispatcherExecutor = new ScheduledThreadPoolExecutor(this.dispatcherTasks.size() > 0 ? this.dispatcherTasks.size() : 1);
|
||||
}
|
||||
|
||||
public MessageChannel getInvalidMessageChannel() {
|
||||
return this.channelRegistry.getInvalidMessageChannel();
|
||||
}
|
||||
|
||||
public void setInvalidMessageChannel(MessageChannel invalidMessageChannel) {
|
||||
this.channelRegistry.setInvalidMessageChannel(invalidMessageChannel);
|
||||
}
|
||||
|
||||
public MessageChannel lookupChannel(String channelName) {
|
||||
return this.channelRegistry.lookupChannel(channelName);
|
||||
}
|
||||
|
||||
public void registerChannel(String name, MessageChannel channel) {
|
||||
this.channelRegistry.registerChannel(name, channel);
|
||||
}
|
||||
|
||||
public void registerEndpoint(String name, MessageEndpoint<?> endpoint) {
|
||||
Assert.notNull(name, "'name' must not be null");
|
||||
Assert.notNull(endpoint, "'endpoint' must not be null");
|
||||
this.endpoints.put(name, endpoint);
|
||||
if (logger.isInfoEnabled()) {
|
||||
logger.info("registered endpoint '" + name + "'");
|
||||
}
|
||||
endpoint.setChannelRegistry(this);
|
||||
if (endpoint.getInputChannelName() != null && endpoint.getConsumerPolicy() != null) {
|
||||
Subscription subscription = new Subscription();
|
||||
subscription.setChannel(endpoint.getInputChannelName());
|
||||
subscription.setEndpoint(name);
|
||||
subscription.setPolicy(endpoint.getConsumerPolicy());
|
||||
this.activateSubscription(subscription);
|
||||
}
|
||||
if (this.autoCreateChannels) {
|
||||
String defaultOutputChannelName = endpoint.getDefaultOutputChannelName();
|
||||
if (StringUtils.hasText(defaultOutputChannelName) && this.lookupChannel(defaultOutputChannelName) == null) {
|
||||
this.registerChannel(defaultOutputChannelName, new PointToPointChannel());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void registerSourceAdapter(String name, SourceAdapter adapter) {
|
||||
// TODO: use the name
|
||||
if (adapter instanceof MessageDispatcher) {
|
||||
MessageDispatcher dispatcher = (MessageDispatcher) adapter;
|
||||
ConsumerPolicy policy = dispatcher.getConsumerPolicy();
|
||||
DispatcherTask dispatcherTask = new DispatcherTask(dispatcher, policy);
|
||||
this.addDispatcherTask(dispatcherTask);
|
||||
if (logger.isInfoEnabled()) {
|
||||
logger.info("registered source adapter '" + name + "'");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void registerTargetAdapter(String name, TargetAdapter<?> targetAdapter) {
|
||||
if (targetAdapter instanceof AbstractTargetAdapter) {
|
||||
AbstractTargetAdapter<?> adapter = (AbstractTargetAdapter<?>) targetAdapter;
|
||||
adapter.setName(name);
|
||||
this.targetAdapters.put(name, targetAdapter);
|
||||
MessageChannel channel = adapter.getChannel();
|
||||
ConsumerPolicy policy = adapter.getConsumerPolicy();
|
||||
MessageRetriever retriever = new ChannelPollingMessageRetriever(channel, policy);
|
||||
UnicastMessageDispatcher dispatcher = new UnicastMessageDispatcher(retriever, policy);
|
||||
dispatcher.addExecutor(new MessageReceivingExecutor(adapter, policy.getConcurrency(), policy.getMaxConcurrency()));
|
||||
this.addDispatcherTask(new DispatcherTask(dispatcher, policy));
|
||||
if (logger.isInfoEnabled()) {
|
||||
logger.info("registered target adapter '" + name + "'");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void activateSubscription(Subscription subscription) {
|
||||
String channelName = subscription.getChannel();
|
||||
String endpointName = subscription.getEndpoint();
|
||||
ConsumerPolicy policy = subscription.getPolicy();
|
||||
MessageChannel channel = this.lookupChannel(channelName);
|
||||
if (channel == null) {
|
||||
if (this.autoCreateChannels == false) {
|
||||
throw new MessagingException("Cannot activate subscription, unknown channel '" + channelName +
|
||||
"'. Consider enabling the 'autoCreateChannels' option for the message bus.");
|
||||
}
|
||||
if (this.logger.isInfoEnabled()) {
|
||||
logger.info("auto-creating channel '" + channelName + "'");
|
||||
}
|
||||
channel = new PointToPointChannel();
|
||||
this.registerChannel(channelName, channel);
|
||||
}
|
||||
MessageEndpoint<?> endpoint = this.endpoints.get(endpointName);
|
||||
if (endpoint == null) {
|
||||
throw new MessagingException("Cannot activate subscription, unknown endpoint '" + endpointName + "'");
|
||||
}
|
||||
if (logger.isInfoEnabled()) {
|
||||
logger.info("activated subscription to channel '" + channelName +
|
||||
"' for endpoint '" + endpointName + "'");
|
||||
}
|
||||
MessageReceivingExecutor executor = new MessageReceivingExecutor(endpoint, policy.getConcurrency(), policy.getMaxConcurrency());
|
||||
receiverExecutors.put(endpoint, executor);
|
||||
MessageRetriever retriever = new ChannelPollingMessageRetriever(channel, policy);
|
||||
UnicastMessageDispatcher dispatcher = new UnicastMessageDispatcher(retriever, policy);
|
||||
dispatcher.addExecutor(executor);
|
||||
DispatcherTask dispatcherTask = new DispatcherTask(dispatcher, policy);
|
||||
if (this.isRunning()) {
|
||||
executor.start();
|
||||
}
|
||||
this.addDispatcherTask(dispatcherTask);
|
||||
if (this.logger.isInfoEnabled()) {
|
||||
logger.info("registered dispatcher task: channel='" +
|
||||
channelName + "' receiver='" + endpointName + "'");
|
||||
}
|
||||
}
|
||||
|
||||
private void addDispatcherTask(DispatcherTask dispatcherTask) {
|
||||
this.dispatcherTasks.add(dispatcherTask);
|
||||
if (this.isRunning()) {
|
||||
scheduleDispatcherTask(dispatcherTask);
|
||||
if (this.logger.isInfoEnabled()) {
|
||||
logger.info("scheduled dispatcher task");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public int getActiveCountForReceiver(String receiverName) {
|
||||
MessageReceiver<?> receiver = this.endpoints.get(receiverName);
|
||||
if (receiver == null) {
|
||||
receiver = this.targetAdapters.get(receiverName);
|
||||
}
|
||||
if (receiver != null) {
|
||||
MessageReceivingExecutor executor = this.receiverExecutors.get(receiver);
|
||||
if (executor != null) {
|
||||
return executor.getActiveCount();
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
private void scheduleDispatcherTask(DispatcherTask task) {
|
||||
ConsumerPolicy policy = task.getPolicy();
|
||||
if (policy.getPeriod() <= 0) {
|
||||
if (policy.getReceiveTimeout() <= 0) {
|
||||
if (logger.isWarnEnabled()) {
|
||||
logger.warn("Scheduling a repeating task with no receive timeout is not recommended! " +
|
||||
"Consider providing a positive value for either 'period' or 'receiveTimeout'");
|
||||
}
|
||||
}
|
||||
dispatcherExecutor.schedule(new RepeatingDispatcherTask(task), policy.getInitialDelay(), policy.getTimeUnit());
|
||||
}
|
||||
else if (policy.isFixedRate()) {
|
||||
dispatcherExecutor.scheduleAtFixedRate(task, policy.getInitialDelay(), policy.getPeriod(), policy.getTimeUnit());
|
||||
}
|
||||
else {
|
||||
dispatcherExecutor.scheduleWithFixedDelay(task, policy.getInitialDelay(), policy.getPeriod(), policy.getTimeUnit());
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isRunning() {
|
||||
synchronized (this.lifecycleMonitor) {
|
||||
return this.running;
|
||||
}
|
||||
}
|
||||
|
||||
public void start() {
|
||||
if (this.dispatcherExecutor == null) {
|
||||
this.initialize();
|
||||
}
|
||||
synchronized (this.lifecycleMonitor) {
|
||||
if (!this.isRunning()) {
|
||||
this.running = true;
|
||||
for (MessageReceivingExecutor executor : receiverExecutors.values()) {
|
||||
executor.start();
|
||||
}
|
||||
for (DispatcherTask task : this.dispatcherTasks) {
|
||||
scheduleDispatcherTask(task);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void stop() {
|
||||
synchronized (this.lifecycleMonitor) {
|
||||
if (this.isRunning()) {
|
||||
this.running = false;
|
||||
for (MessageReceivingExecutor executor : receiverExecutors.values()) {
|
||||
executor.stop();
|
||||
}
|
||||
this.dispatcherExecutor.shutdownNow();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static class DispatcherTask implements Runnable {
|
||||
|
||||
private MessageDispatcher dispatcher;
|
||||
|
||||
private ConsumerPolicy policy;
|
||||
|
||||
|
||||
public DispatcherTask(MessageDispatcher dispatcher, ConsumerPolicy policy) {
|
||||
this.dispatcher = dispatcher;
|
||||
this.policy = policy;
|
||||
}
|
||||
|
||||
|
||||
public ConsumerPolicy getPolicy() {
|
||||
return this.policy;
|
||||
}
|
||||
|
||||
public void run() {
|
||||
dispatcher.dispatch();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
private class RepeatingDispatcherTask implements Runnable {
|
||||
|
||||
private DispatcherTask task;
|
||||
|
||||
RepeatingDispatcherTask(DispatcherTask task) {
|
||||
this.task = task;
|
||||
}
|
||||
|
||||
public void run() {
|
||||
task.run();
|
||||
dispatcherExecutor.execute(new RepeatingDispatcherTask(task));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
* Copyright 2002-2007 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.bus;
|
||||
|
||||
/**
|
||||
* Strategy interface for dispatching messages.
|
||||
*
|
||||
* @author Mark Fisher
|
||||
*/
|
||||
public interface MessageDispatcher {
|
||||
|
||||
ConsumerPolicy getConsumerPolicy();
|
||||
|
||||
int dispatch();
|
||||
|
||||
}
|
||||
@@ -0,0 +1,201 @@
|
||||
/*
|
||||
* Copyright 2002-2007 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.bus;
|
||||
|
||||
import java.util.concurrent.SynchronousQueue;
|
||||
import java.util.concurrent.ThreadPoolExecutor;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import org.springframework.context.Lifecycle;
|
||||
import org.springframework.integration.MessageHandlingException;
|
||||
import org.springframework.integration.message.Message;
|
||||
import org.springframework.integration.message.MessageReceiver;
|
||||
import org.springframework.scheduling.concurrent.CustomizableThreadFactory;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Encapsulates a {@link ThreadPoolExecutor} with configurable error thresholds.
|
||||
*
|
||||
* @author Mark Fisher
|
||||
*/
|
||||
public class MessageReceivingExecutor implements Lifecycle {
|
||||
|
||||
private Log logger = LogFactory.getLog(this.getClass());
|
||||
|
||||
private MessageReceiver receiver;
|
||||
|
||||
private ThreadPoolExecutor threadPoolExecutor;
|
||||
|
||||
private int corePoolSize;
|
||||
|
||||
private int maxPoolSize;
|
||||
|
||||
private volatile boolean running;
|
||||
|
||||
private Object lifecycleMonitor = new Object();
|
||||
|
||||
private int successiveErrorCount;
|
||||
|
||||
private int successiveErrorThreshold = -1;
|
||||
|
||||
private int totalErrorCount;
|
||||
|
||||
private int totalErrorThreshold = -1;
|
||||
|
||||
|
||||
public MessageReceivingExecutor(MessageReceiver receiver, int corePoolSize, int maxPoolSize) {
|
||||
Assert.notNull(receiver, "'receiver' must not be null");
|
||||
Assert.isTrue(corePoolSize > 0, "'corePoolSize' must be at least 1");
|
||||
Assert.isTrue(maxPoolSize > 0, "'maxPoolSize' must be at least 1");
|
||||
Assert.isTrue(maxPoolSize >= corePoolSize, "'corePoolSize' cannot exceed 'maxPoolSize'");
|
||||
this.receiver = receiver;
|
||||
this.corePoolSize = corePoolSize;
|
||||
this.maxPoolSize = maxPoolSize;
|
||||
}
|
||||
|
||||
public void setCorePoolSize(int corePoolSize) {
|
||||
this.corePoolSize = corePoolSize;
|
||||
}
|
||||
|
||||
public void setMaxPoolSize(int maxPoolSize) {
|
||||
this.maxPoolSize = maxPoolSize;
|
||||
}
|
||||
|
||||
public boolean isRunning() {
|
||||
return this.running;
|
||||
}
|
||||
|
||||
public void start() {
|
||||
synchronized (this.lifecycleMonitor) {
|
||||
if (!this.running) {
|
||||
this.threadPoolExecutor = new MessageReceivingThreadPoolExecutor(this.corePoolSize, this.maxPoolSize);
|
||||
}
|
||||
this.running = true;
|
||||
}
|
||||
}
|
||||
|
||||
public void stop() {
|
||||
synchronized (this.lifecycleMonitor) {
|
||||
if (this.isRunning()) {
|
||||
this.threadPoolExecutor.shutdown();
|
||||
this.threadPoolExecutor = null;
|
||||
}
|
||||
this.running = false;
|
||||
}
|
||||
}
|
||||
|
||||
public void processMessage(Message<?> message) {
|
||||
if (threadPoolExecutor == null) {
|
||||
throw new MessageHandlingException("executor is not running");
|
||||
}
|
||||
this.threadPoolExecutor.execute(new MessageReceivingTask(this.receiver, message));
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the maximum number of errors allowed in <em>successive</em>
|
||||
* executions. If this threshold is ever exceeded, the executor
|
||||
* will shutdown.
|
||||
*/
|
||||
public void setSuccessiveErrorThreshold(int successiveErrorThreshold) {
|
||||
this.successiveErrorThreshold = successiveErrorThreshold;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the maximum number of <em>total</em> errors allowed in executions
|
||||
* If this threshold is ever exceeded, the executor will shutdown.
|
||||
*/
|
||||
public void setTotalErrorThreshold(int totalErrorThreshold) {
|
||||
this.totalErrorThreshold = totalErrorThreshold;
|
||||
}
|
||||
|
||||
public int getActiveCount() {
|
||||
if (this.threadPoolExecutor == null) {
|
||||
return 0;
|
||||
}
|
||||
return this.threadPoolExecutor.getActiveCount();
|
||||
}
|
||||
|
||||
public boolean isShutdown() {
|
||||
return this.threadPoolExecutor.isShutdown();
|
||||
}
|
||||
|
||||
|
||||
private static class MessageReceivingTask implements Runnable {
|
||||
|
||||
private MessageReceiver receiver;
|
||||
|
||||
private Message<?> message;
|
||||
|
||||
private Throwable error;
|
||||
|
||||
|
||||
MessageReceivingTask(MessageReceiver receiver, Message<?> message) {
|
||||
this.receiver = receiver;
|
||||
this.message = message;
|
||||
}
|
||||
|
||||
public Throwable getError() {
|
||||
return this.error;
|
||||
}
|
||||
|
||||
public void run() {
|
||||
try {
|
||||
this.receiver.messageReceived(this.message);
|
||||
}
|
||||
catch (Throwable t) {
|
||||
this.error = t;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private class MessageReceivingThreadPoolExecutor extends ThreadPoolExecutor {
|
||||
|
||||
public MessageReceivingThreadPoolExecutor(int corePoolSize, int maximumPoolSize) {
|
||||
super(corePoolSize, maximumPoolSize, 0, TimeUnit.MILLISECONDS, new SynchronousQueue<Runnable>());
|
||||
CustomizableThreadFactory threadFactory = new CustomizableThreadFactory();
|
||||
threadFactory.setThreadNamePrefix("endpoint-executor-");
|
||||
this.setThreadFactory(threadFactory);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void afterExecute(Runnable r, Throwable t) {
|
||||
MessageReceivingTask task = (MessageReceivingTask) r;
|
||||
if (task.getError() != null) {
|
||||
if (logger.isWarnEnabled()) {
|
||||
logger.warn("Exception occurred during task execution", task.getError());
|
||||
}
|
||||
successiveErrorCount++;
|
||||
totalErrorCount++;
|
||||
if ((successiveErrorThreshold >= 0 && successiveErrorCount > successiveErrorThreshold)
|
||||
|| (totalErrorThreshold >= 0 && totalErrorCount > totalErrorThreshold)) {
|
||||
if (logger.isInfoEnabled()) {
|
||||
logger.info("error threshold exceeded, shutting down now");
|
||||
}
|
||||
this.shutdownNow();
|
||||
}
|
||||
}
|
||||
else {
|
||||
successiveErrorCount = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* Copyright 2002-2007 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.bus;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
import org.springframework.integration.message.Message;
|
||||
|
||||
/**
|
||||
* Strategy interface for retrieving messages.
|
||||
*
|
||||
* @author Mark Fisher
|
||||
*/
|
||||
public interface MessageRetriever {
|
||||
|
||||
Collection<Message<?>> retrieveMessages();
|
||||
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
* Copyright 2002-2007 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.bus;
|
||||
|
||||
/**
|
||||
* Configuration metadata for activating a subscription.
|
||||
*
|
||||
* @author Mark Fisher
|
||||
*/
|
||||
public class Subscription {
|
||||
|
||||
private String channel;
|
||||
|
||||
private String endpoint;
|
||||
|
||||
private ConsumerPolicy policy = new ConsumerPolicy();
|
||||
|
||||
|
||||
public String getChannel() {
|
||||
return this.channel;
|
||||
}
|
||||
|
||||
public void setChannel(String channel) {
|
||||
this.channel = channel;
|
||||
}
|
||||
|
||||
public String getEndpoint() {
|
||||
return this.endpoint;
|
||||
}
|
||||
|
||||
public void setEndpoint(String endpoint) {
|
||||
this.endpoint = endpoint;
|
||||
}
|
||||
|
||||
public ConsumerPolicy getPolicy() {
|
||||
return this.policy;
|
||||
}
|
||||
|
||||
public void setPolicy(ConsumerPolicy policy) {
|
||||
this.policy = policy;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,92 @@
|
||||
/*
|
||||
* Copyright 2002-2007 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.bus;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.concurrent.RejectedExecutionException;
|
||||
|
||||
import org.springframework.integration.message.Message;
|
||||
|
||||
/**
|
||||
* A {@link MessageDispatcher} implementation that dispatches each retrieved
|
||||
* {@link Message} to a single {@link MessageReceivingExecutor}.
|
||||
*
|
||||
* @author Mark Fisher
|
||||
*/
|
||||
public class UnicastMessageDispatcher extends AbstractMessageDispatcher {
|
||||
|
||||
private ConsumerPolicy policy;
|
||||
|
||||
|
||||
public UnicastMessageDispatcher(MessageRetriever retriever, ConsumerPolicy policy) {
|
||||
super(retriever);
|
||||
this.policy = policy;
|
||||
}
|
||||
|
||||
|
||||
public ConsumerPolicy getConsumerPolicy() {
|
||||
return this.policy;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean dispatchMessage(Message<?> message) {
|
||||
int attempts = 0;
|
||||
Iterator<MessageReceivingExecutor> iter = this.getExecutors().iterator();
|
||||
if (!iter.hasNext()) {
|
||||
if (logger.isWarnEnabled()) {
|
||||
logger.warn("dispatcher has no active executors");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
while (iter.hasNext()) {
|
||||
MessageReceivingExecutor executor = iter.next();
|
||||
try {
|
||||
if (executor == null || !executor.isRunning()) {
|
||||
if (logger.isInfoEnabled()) {
|
||||
logger.info("removing inactive executor");
|
||||
}
|
||||
iter.remove();
|
||||
continue;
|
||||
}
|
||||
executor.processMessage(message);
|
||||
return true;
|
||||
}
|
||||
catch (RejectedExecutionException rex) {
|
||||
attempts++;
|
||||
if (attempts == policy.getRejectionLimit()) {
|
||||
attempts = 0;
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("reached rejected execution limit");
|
||||
}
|
||||
try {
|
||||
Thread.sleep(policy.getRejectionLimitWait());
|
||||
}
|
||||
catch (InterruptedException iex) {
|
||||
Thread.currentThread().interrupt();
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception e) {
|
||||
if (logger.isWarnEnabled()) {
|
||||
logger.warn("error occurred during dispatch", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright 2002-2007 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.channel;
|
||||
|
||||
/**
|
||||
* A strategy interface for registration and lookup of message channels by name.
|
||||
*
|
||||
* @author Mark Fisher
|
||||
*/
|
||||
public interface ChannelRegistry {
|
||||
|
||||
void registerChannel(String name, MessageChannel channel);
|
||||
|
||||
MessageChannel lookupChannel(String channelName);
|
||||
|
||||
void setInvalidMessageChannel(MessageChannel invalidMessageChannel);
|
||||
|
||||
MessageChannel getInvalidMessageChannel();
|
||||
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
* Copyright 2002-2007 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.channel;
|
||||
|
||||
/**
|
||||
* Interface to be implemented by components that need access to the
|
||||
* {@link ChannelRegistry}.
|
||||
*
|
||||
* @author Mark Fisher
|
||||
*/
|
||||
public interface ChannelRegistryAware {
|
||||
|
||||
void setChannelRegistry(ChannelRegistry channelRegistry);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright 2002-2007 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.channel;
|
||||
|
||||
/**
|
||||
* Enumeration of the different types of message consumer.
|
||||
*
|
||||
* @author Mark Fisher
|
||||
*/
|
||||
public enum ConsumerType {
|
||||
|
||||
EVENT_DRIVEN,
|
||||
|
||||
FIXED_RATE,
|
||||
|
||||
FIXED_DELAY,
|
||||
|
||||
SCHEDULED
|
||||
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
* Copyright 2002-2007 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.channel;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* A simple map-backed implementation of {@link ChannelRegistry}.
|
||||
*
|
||||
* @author Mark Fisher
|
||||
*/
|
||||
public class DefaultChannelRegistry implements ChannelRegistry {
|
||||
|
||||
private Log logger = LogFactory.getLog(this.getClass());
|
||||
|
||||
private Map<String, MessageChannel> channels = new ConcurrentHashMap<String, MessageChannel>();
|
||||
|
||||
private MessageChannel invalidMessageChannel;
|
||||
|
||||
|
||||
public void setInvalidMessageChannel(MessageChannel invalidMessageChannel) {
|
||||
this.invalidMessageChannel = invalidMessageChannel;
|
||||
}
|
||||
|
||||
public MessageChannel getInvalidMessageChannel() {
|
||||
return this.invalidMessageChannel;
|
||||
}
|
||||
|
||||
public MessageChannel lookupChannel(String channelName) {
|
||||
return this.channels.get(channelName);
|
||||
}
|
||||
|
||||
public void registerChannel(String name, MessageChannel channel) {
|
||||
Assert.notNull(name, "'name' must not be null");
|
||||
Assert.notNull(channel, "'channel' must not be null");
|
||||
channel.setName(name);
|
||||
this.channels.put(name, channel);
|
||||
if (logger.isInfoEnabled()) {
|
||||
logger.info("registered channel '" + name + "'");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
/*
|
||||
* Copyright 2002-2007 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.channel;
|
||||
|
||||
import org.springframework.integration.message.Message;
|
||||
|
||||
/**
|
||||
* Base channel interface defining common behavior for message sending and receiving.
|
||||
*
|
||||
* @author Mark Fisher
|
||||
*/
|
||||
public interface MessageChannel {
|
||||
|
||||
/**
|
||||
* Set the name of this channel. Must be unique within a context.
|
||||
*/
|
||||
void setName(String name);
|
||||
|
||||
/**
|
||||
* Return the name of this channel.
|
||||
*/
|
||||
String getName();
|
||||
|
||||
/**
|
||||
* Send a message, blocking indefinitely if necessary.
|
||||
*
|
||||
* @param message the {@link Message} to send
|
||||
*
|
||||
* @return <code>true</code> if the message is sent successfully,
|
||||
* <code>false</false> if interrupted
|
||||
*/
|
||||
boolean send(Message message);
|
||||
|
||||
/**
|
||||
* Send a message, blocking until either the message is accepted or the
|
||||
* specified timeout period elapses.
|
||||
*
|
||||
* @param message the {@link Message} to send
|
||||
* @param timeout the timeout in milliseconds
|
||||
*
|
||||
* @return <code>true</code> if the message is sent successfully,
|
||||
* <code>false</false> if the specified timeout period elapses or
|
||||
* the send is interrupted
|
||||
*/
|
||||
boolean send(Message message, long timeout);
|
||||
|
||||
/**
|
||||
* Receive a message, blocking indefinitely if necessary.
|
||||
*
|
||||
* @return the next available {@link Message} or <code>null</code> if
|
||||
* interrupted
|
||||
*/
|
||||
Message receive();
|
||||
|
||||
/**
|
||||
* Receive a message, blocking until either a message is available or the
|
||||
* specified timeout period elapses.
|
||||
*
|
||||
* @param timeout the timeout in milliseconds
|
||||
*
|
||||
* @return the next available {@link Message} or <code>null</code> if the
|
||||
* specified timeout period elapses or the message reception is interrupted
|
||||
*/
|
||||
Message receive(long timeout);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,213 @@
|
||||
/*
|
||||
* Copyright 2002-2007 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.channel;
|
||||
|
||||
import java.util.concurrent.BlockingQueue;
|
||||
import java.util.concurrent.LinkedBlockingQueue;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.springframework.beans.factory.BeanNameAware;
|
||||
import org.springframework.integration.message.Message;
|
||||
import org.springframework.integration.message.MessageSelector;
|
||||
|
||||
/**
|
||||
* Simple implementation of a point-to-point message channel. Each Messages is
|
||||
* placed in a queue whose capacity may be specified upon construction. If no
|
||||
* capacity is specified, the {@link #DEFAULT_CAPACITY} will be used.
|
||||
*
|
||||
* @author Mark Fisher
|
||||
*/
|
||||
public class PointToPointChannel implements MessageChannel, BeanNameAware {
|
||||
|
||||
private static final int DEFAULT_CAPACITY = 25;
|
||||
|
||||
private String name;
|
||||
|
||||
private BlockingQueue<Message<?>> queue;
|
||||
|
||||
/**
|
||||
* Create a channel with the specified queue capacity.
|
||||
*/
|
||||
public PointToPointChannel(int capacity) {
|
||||
queue = new LinkedBlockingQueue<Message<?>>(capacity);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a channel with the default queue capacity.
|
||||
*/
|
||||
public PointToPointChannel() {
|
||||
this(DEFAULT_CAPACITY);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Set the name of this channel.
|
||||
*/
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the name of this channel.
|
||||
*/
|
||||
public String getName() {
|
||||
return this.name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the name of this channel to its bean name. This will be invoked
|
||||
* automatically whenever the channel is configured explicitly with a bean
|
||||
* definition.
|
||||
*/
|
||||
public void setBeanName(String beanName) {
|
||||
this.setName(beanName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a message on this channel. If the queue is full, this method will
|
||||
* block until either space becomes available or the sending thread is
|
||||
* interrupted.
|
||||
*
|
||||
* @param message the Message to send
|
||||
*
|
||||
* @return <code>true</code> if the message is sent successfully or
|
||||
* <code>false</code> if the sending thread is interrupted.
|
||||
*/
|
||||
public boolean send(Message message) {
|
||||
try {
|
||||
queue.put(message);
|
||||
return true;
|
||||
}
|
||||
catch (InterruptedException e) {
|
||||
Thread.currentThread().interrupt();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a message on this channel. If the queue is full, this method will
|
||||
* block until either the timeout occurs or the sending thread is
|
||||
* interrupted. If the specified timeout is less than 1, the method will
|
||||
* return immediately.
|
||||
*
|
||||
* @param message the Message to send
|
||||
* @param timeout the timeout in milliseconds
|
||||
*
|
||||
* @return <code>true</code> if the message is sent successfully,
|
||||
* <code>false</code> if the message cannot be sent within the allotted
|
||||
* time or the sending thread is interrupted.
|
||||
*/
|
||||
public boolean send(Message message, long timeout) {
|
||||
try {
|
||||
if (timeout > 0) {
|
||||
return this.queue.offer(message, timeout, TimeUnit.MILLISECONDS);
|
||||
}
|
||||
return this.queue.offer(message);
|
||||
}
|
||||
catch (InterruptedException e) {
|
||||
Thread.currentThread().interrupt();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Receive the message at the head of the queue. If the queue is empty, this
|
||||
* method will block.
|
||||
*
|
||||
* @return the Message at the head of the queue or <code>null</code> if
|
||||
* the receiving thread is interrupted.
|
||||
*/
|
||||
public Message receive() {
|
||||
try {
|
||||
return queue.take();
|
||||
}
|
||||
catch (InterruptedException e) {
|
||||
Thread.currentThread().interrupt();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Receive the message at the head of the queue. If the queue is empty, this
|
||||
* method will block until the allotted timeout elapses. If the specified
|
||||
* timeout is less than 1, the method will return immediately.
|
||||
*
|
||||
* @param timeout the timeout in milliseconds
|
||||
*
|
||||
* @return the message at the head of the queue or <code>null</code> in
|
||||
* case no message is available within the allotted time or the receiving
|
||||
* thread is interrupted.
|
||||
*/
|
||||
public Message receive(long timeout) {
|
||||
try {
|
||||
if (timeout > 0) {
|
||||
return queue.poll(timeout, TimeUnit.MILLISECONDS);
|
||||
}
|
||||
return queue.poll();
|
||||
}
|
||||
catch (InterruptedException e) {
|
||||
Thread.currentThread().interrupt();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Receive the first message that is accepted by the specified selector
|
||||
* starting from the head of the queue. If the queue is empty, this method
|
||||
* will block until the allotted timeout elapses. If the specified timeout
|
||||
* is less than 1, the method will return immediately.
|
||||
*
|
||||
* @param selector the selector to use
|
||||
* @param timeout the timeout in milliseconds
|
||||
*
|
||||
* @return the first accepted message or <code>null</code> in case the
|
||||
* selector does not accept any message within the allotted time or the
|
||||
* receiving thread is interrupted.
|
||||
*/
|
||||
public Message receive(MessageSelector selector, long timeout) {
|
||||
long start = System.currentTimeMillis();
|
||||
while (timeout <= 0 || System.currentTimeMillis() - start < timeout) {
|
||||
Object[] elements = this.queue.toArray();
|
||||
for (int i = (elements.length - 1); i >= 0; i--) {
|
||||
Message<?> m = (Message<?>) elements[i];
|
||||
if (selector.accept(m) && this.queue.remove(m)) {
|
||||
return m;
|
||||
}
|
||||
}
|
||||
if (timeout == 0) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Receive the first message that is accepted by the specified selector
|
||||
* starting from the head of the queue. If the queue is empty, this method
|
||||
* will block.
|
||||
*
|
||||
* @param selector the selector to use
|
||||
*
|
||||
* @return the first accepted message or <code>null</code> in case the
|
||||
* selector does not accept any message or the receiving thread is
|
||||
* interrupted.
|
||||
*/
|
||||
public Message receive(MessageSelector selector) {
|
||||
return this.receive(selector, -1);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
/*
|
||||
* Copyright 2002-2007 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.config;
|
||||
|
||||
import org.w3c.dom.Element;
|
||||
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.beans.factory.config.RuntimeBeanReference;
|
||||
import org.springframework.beans.factory.parsing.BeanComponentDefinition;
|
||||
import org.springframework.beans.factory.support.RootBeanDefinition;
|
||||
import org.springframework.beans.factory.xml.BeanDefinitionParser;
|
||||
import org.springframework.beans.factory.xml.ParserContext;
|
||||
|
||||
/**
|
||||
* Parser for the <em>annotation-driven</em> element of the integration
|
||||
* namespace. Registers the annotation-driven post-processors.
|
||||
*
|
||||
* @author Mark Fisher
|
||||
*/
|
||||
public class AnnotationDrivenParser implements BeanDefinitionParser {
|
||||
|
||||
private static final String PUBLISHER_ANNOTATION_POST_PROCESSOR_BEAN_NAME =
|
||||
"internal.PublisherAnnotationPostProcessor";
|
||||
|
||||
private static final String SUBSCRIBER_ANNOTATION_POST_PROCESSOR_BEAN_NAME =
|
||||
"internal.SubscriberAnnotationPostProcessor";
|
||||
|
||||
private static final String MESSAGE_ENDPOINT_ANNOTATION_POST_PROCESSOR_BEAN_NAME =
|
||||
"internal.MessageEndpointAnnotationPostProcessor";
|
||||
|
||||
|
||||
public BeanDefinition parse(Element element, ParserContext parserContext) {
|
||||
this.createPublisherPostProcessor(parserContext);
|
||||
this.createSubscriberPostProcessor(parserContext);
|
||||
this.createMessageEndpointPostProcessor(parserContext);
|
||||
return null;
|
||||
}
|
||||
|
||||
private void createPublisherPostProcessor(ParserContext parserContext) {
|
||||
BeanDefinition bd = new RootBeanDefinition(PublisherAnnotationPostProcessor.class);
|
||||
bd.getPropertyValues().addPropertyValue("channelRegistry",
|
||||
new RuntimeBeanReference(MessageBusParser.MESSAGE_BUS_BEAN_NAME));
|
||||
BeanComponentDefinition bcd = new BeanComponentDefinition(
|
||||
bd, PUBLISHER_ANNOTATION_POST_PROCESSOR_BEAN_NAME);
|
||||
parserContext.registerBeanComponent(bcd);
|
||||
}
|
||||
|
||||
private void createSubscriberPostProcessor(ParserContext parserContext) {
|
||||
BeanDefinition bd = new RootBeanDefinition(SubscriberAnnotationPostProcessor.class);
|
||||
bd.getPropertyValues().addPropertyValue("messageBus",
|
||||
new RuntimeBeanReference(MessageBusParser.MESSAGE_BUS_BEAN_NAME));
|
||||
BeanComponentDefinition bcd = new BeanComponentDefinition(
|
||||
bd, SUBSCRIBER_ANNOTATION_POST_PROCESSOR_BEAN_NAME);
|
||||
parserContext.registerBeanComponent(bcd);
|
||||
}
|
||||
|
||||
private void createMessageEndpointPostProcessor(ParserContext parserContext) {
|
||||
BeanDefinition bd = new RootBeanDefinition(MessageEndpointAnnotationPostProcessor.class);
|
||||
bd.getPropertyValues().addPropertyValue("messageBus",
|
||||
new RuntimeBeanReference(MessageBusParser.MESSAGE_BUS_BEAN_NAME));
|
||||
BeanComponentDefinition bcd = new BeanComponentDefinition(
|
||||
bd, MESSAGE_ENDPOINT_ANNOTATION_POST_PROCESSOR_BEAN_NAME);
|
||||
parserContext.registerBeanComponent(bcd);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,102 @@
|
||||
/*
|
||||
* Copyright 2002-2007 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.config;
|
||||
|
||||
import org.w3c.dom.Element;
|
||||
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.beans.factory.config.RuntimeBeanReference;
|
||||
import org.springframework.beans.factory.parsing.BeanComponentDefinition;
|
||||
import org.springframework.beans.factory.support.RootBeanDefinition;
|
||||
import org.springframework.beans.factory.xml.BeanDefinitionParser;
|
||||
import org.springframework.beans.factory.xml.ParserContext;
|
||||
import org.springframework.integration.MessagingConfigurationException;
|
||||
import org.springframework.integration.adapter.DefaultTargetAdapter;
|
||||
import org.springframework.integration.adapter.MethodInvokingSource;
|
||||
import org.springframework.integration.adapter.MethodInvokingTarget;
|
||||
import org.springframework.integration.adapter.PollingSourceAdapter;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* Parser for inbound and outbound channel adapters.
|
||||
*
|
||||
* @author Mark Fisher
|
||||
*/
|
||||
public class ChannelAdapterParser implements BeanDefinitionParser {
|
||||
|
||||
private static final String ID_ATTRIBUTE = "id";
|
||||
|
||||
private static final String REF_ATTRIBUTE = "ref";
|
||||
|
||||
private static final String METHOD_ATTRIBUTE = "method";
|
||||
|
||||
private static final String CHANNEL_ATTRIBUTE = "channel";
|
||||
|
||||
private static final String PERIOD_ATTRIBUTE = "period";
|
||||
|
||||
|
||||
private final boolean isInbound;
|
||||
|
||||
|
||||
public ChannelAdapterParser(boolean isInbound) {
|
||||
this.isInbound = isInbound;
|
||||
}
|
||||
|
||||
|
||||
public BeanDefinition parse(Element element, ParserContext parserContext) {
|
||||
String ref = element.getAttribute(REF_ATTRIBUTE);
|
||||
String method = element.getAttribute(METHOD_ATTRIBUTE);
|
||||
String channel = element.getAttribute(CHANNEL_ATTRIBUTE);
|
||||
if (!StringUtils.hasText(ref)) {
|
||||
throw new MessagingConfigurationException("'ref' is required");
|
||||
}
|
||||
if (!StringUtils.hasText(method)) {
|
||||
throw new MessagingConfigurationException("'method' is required");
|
||||
}
|
||||
if (!StringUtils.hasText(channel)) {
|
||||
throw new MessagingConfigurationException("'channel' is required");
|
||||
}
|
||||
RootBeanDefinition adapterDef = null;
|
||||
RootBeanDefinition invokerDef = null;
|
||||
if (this.isInbound) {
|
||||
adapterDef = new RootBeanDefinition(PollingSourceAdapter.class);
|
||||
invokerDef = new RootBeanDefinition(MethodInvokingSource.class);
|
||||
String period = element.getAttribute(PERIOD_ATTRIBUTE);
|
||||
if (StringUtils.hasText(period)) {
|
||||
adapterDef.getPropertyValues().addPropertyValue("period", period);
|
||||
}
|
||||
}
|
||||
else {
|
||||
adapterDef = new RootBeanDefinition(DefaultTargetAdapter.class);
|
||||
invokerDef = new RootBeanDefinition(MethodInvokingTarget.class);
|
||||
}
|
||||
invokerDef.getPropertyValues().addPropertyValue("object", new RuntimeBeanReference(ref));
|
||||
invokerDef.getPropertyValues().addPropertyValue("method", method);
|
||||
String invokerBeanName = parserContext.getReaderContext().generateBeanName(invokerDef);
|
||||
parserContext.registerBeanComponent(new BeanComponentDefinition(invokerDef, invokerBeanName));
|
||||
adapterDef.getConstructorArgumentValues().addGenericArgumentValue(new RuntimeBeanReference(invokerBeanName));
|
||||
adapterDef.getPropertyValues().addPropertyValue("channel", new RuntimeBeanReference(channel));
|
||||
adapterDef.setSource(parserContext.extractSource(element));
|
||||
String beanName = element.getAttribute(ID_ATTRIBUTE);
|
||||
if (!StringUtils.hasText(beanName)) {
|
||||
beanName = parserContext.getReaderContext().generateBeanName(adapterDef);
|
||||
}
|
||||
parserContext.registerBeanComponent(new BeanComponentDefinition(adapterDef, beanName));
|
||||
return adapterDef;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* Copyright 2002-2007 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.config;
|
||||
|
||||
import org.w3c.dom.Element;
|
||||
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.beans.factory.parsing.BeanComponentDefinition;
|
||||
import org.springframework.beans.factory.support.RootBeanDefinition;
|
||||
import org.springframework.beans.factory.xml.BeanDefinitionParser;
|
||||
import org.springframework.beans.factory.xml.ParserContext;
|
||||
import org.springframework.integration.channel.PointToPointChannel;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* Parser for the <em>channel</em> element of the integration namespace.
|
||||
*
|
||||
* @author Mark Fisher
|
||||
*/
|
||||
public class ChannelParser implements BeanDefinitionParser {
|
||||
|
||||
private static final String ID_ATTRIBUTE = "id";
|
||||
|
||||
private static final String CAPACITY_ATTRIBUTE = "capacity";
|
||||
|
||||
|
||||
public BeanDefinition parse(Element element, ParserContext parserContext) {
|
||||
RootBeanDefinition channelDef = new RootBeanDefinition(PointToPointChannel.class);
|
||||
channelDef.setSource(parserContext.extractSource(element));
|
||||
String capacity = element.getAttribute(CAPACITY_ATTRIBUTE);
|
||||
if (StringUtils.hasText(capacity)) {
|
||||
channelDef.getConstructorArgumentValues().addGenericArgumentValue(Integer.parseInt(capacity));
|
||||
}
|
||||
String beanName = element.getAttribute(ID_ATTRIBUTE);
|
||||
if (!StringUtils.hasText(beanName)) {
|
||||
beanName = parserContext.getReaderContext().generateBeanName(channelDef);
|
||||
}
|
||||
parserContext.registerBeanComponent(new BeanComponentDefinition(channelDef, beanName));
|
||||
return channelDef;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,173 @@
|
||||
/*
|
||||
* Copyright 2002-2007 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.config;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.w3c.dom.Element;
|
||||
import org.w3c.dom.Node;
|
||||
import org.w3c.dom.NodeList;
|
||||
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.beans.factory.config.RuntimeBeanReference;
|
||||
import org.springframework.beans.factory.parsing.BeanComponentDefinition;
|
||||
import org.springframework.beans.factory.support.ManagedList;
|
||||
import org.springframework.beans.factory.support.RootBeanDefinition;
|
||||
import org.springframework.beans.factory.xml.BeanDefinitionParser;
|
||||
import org.springframework.beans.factory.xml.ParserContext;
|
||||
import org.springframework.integration.MessagingConfigurationException;
|
||||
import org.springframework.integration.bus.ConsumerPolicy;
|
||||
import org.springframework.integration.endpoint.GenericMessageEndpoint;
|
||||
import org.springframework.integration.handler.DefaultMessageHandlerAdapter;
|
||||
import org.springframework.integration.handler.MessageHandlerChain;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* Parser for the <em>endpoint</em> element of the integration namespace.
|
||||
*
|
||||
* @author Mark Fisher
|
||||
*/
|
||||
public class EndpointParser implements BeanDefinitionParser {
|
||||
|
||||
private static final String ID_ATTRIBUTE = "id";
|
||||
|
||||
private static final String INPUT_CHANNEL_ATTRIBUTE = "input-channel";
|
||||
|
||||
private static final String INPUT_CHANNEL_PROPERTY = "inputChannelName";
|
||||
|
||||
private static final String DEFAULT_OUTPUT_CHANNEL_ATTRIBUTE = "default-output-channel";
|
||||
|
||||
private static final String DEFAULT_OUTPUT_CHANNEL_PROPERTY = "defaultOutputChannelName";
|
||||
|
||||
private static final String HANDLER_ELEMENT = "handler";
|
||||
|
||||
private static final String REF_ATTRIBUTE = "ref";
|
||||
|
||||
private static final String METHOD_ATTRIBUTE = "method";
|
||||
|
||||
private static final String HANDLERS_PROPERTY = "handlers";
|
||||
|
||||
private static final String HANDLER_REF_ATTRIBUTE = "handler-ref";
|
||||
|
||||
private static final String HANDLER_METHOD_ATTRIBUTE = "handler-method";
|
||||
|
||||
private static final String HANDLER_PROPERTY = "handler";
|
||||
|
||||
private static final String OBJECT_PROPERTY = "object";
|
||||
|
||||
private static final String METHOD_NAME_PROPERTY = "methodName";
|
||||
|
||||
private static final String PERIOD_ATTRIBUTE = "period";
|
||||
|
||||
private static final String PERIOD_PROPERTY = "period";
|
||||
|
||||
private static final String CONSUMER_ELEMENT = "consumer";
|
||||
|
||||
private static final String CONSUMER_POLICY_PROPERTY = "consumerPolicy";
|
||||
|
||||
|
||||
public BeanDefinition parse(Element element, ParserContext parserContext) {
|
||||
RootBeanDefinition endpointDef = new RootBeanDefinition(GenericMessageEndpoint.class);
|
||||
endpointDef.setSource(parserContext.extractSource(element));
|
||||
String inputChannel = element.getAttribute(INPUT_CHANNEL_ATTRIBUTE);
|
||||
if (StringUtils.hasText(inputChannel)) {
|
||||
endpointDef.getPropertyValues().addPropertyValue(INPUT_CHANNEL_PROPERTY, inputChannel);
|
||||
}
|
||||
String defaultOutputChannel = element.getAttribute(DEFAULT_OUTPUT_CHANNEL_ATTRIBUTE);
|
||||
if (StringUtils.hasText(defaultOutputChannel)) {
|
||||
endpointDef.getPropertyValues().addPropertyValue(DEFAULT_OUTPUT_CHANNEL_PROPERTY, defaultOutputChannel);
|
||||
}
|
||||
List<String> childHandlerRefs = new ArrayList<String>();
|
||||
NodeList childNodes = element.getChildNodes();
|
||||
for (int i = 0; i < childNodes.getLength(); i++) {
|
||||
Node child = childNodes.item(i);
|
||||
if (child.getNodeType() == Node.ELEMENT_NODE) {
|
||||
String localName = child.getLocalName();
|
||||
if (CONSUMER_ELEMENT.equals(localName)) {
|
||||
String consumerBeanName = parseConsumer((Element) child, parserContext);
|
||||
endpointDef.getPropertyValues().addPropertyValue(
|
||||
CONSUMER_POLICY_PROPERTY, new RuntimeBeanReference(consumerBeanName));
|
||||
}
|
||||
else if (HANDLER_ELEMENT.equals(localName)) {
|
||||
String ref = ((Element) child).getAttribute(REF_ATTRIBUTE);
|
||||
String method = ((Element) child).getAttribute(METHOD_ATTRIBUTE);
|
||||
childHandlerRefs.add(this.parseHandlerAdapter(ref, method, parserContext));
|
||||
}
|
||||
}
|
||||
}
|
||||
if (childHandlerRefs.size() > 0) {
|
||||
if (childHandlerRefs.size() == 1) {
|
||||
endpointDef.getPropertyValues().addPropertyValue(
|
||||
HANDLER_PROPERTY, new RuntimeBeanReference(childHandlerRefs.get(0)));
|
||||
}
|
||||
else {
|
||||
RootBeanDefinition handlerChainDef = new RootBeanDefinition(MessageHandlerChain.class);
|
||||
List handlerList = new ManagedList();
|
||||
for (String ref : childHandlerRefs) {
|
||||
handlerList.add(new RuntimeBeanReference(ref));
|
||||
}
|
||||
handlerChainDef.getPropertyValues().addPropertyValue(HANDLERS_PROPERTY, handlerList);
|
||||
String chainBeanName = parserContext.getReaderContext().generateBeanName(handlerChainDef);
|
||||
parserContext.registerBeanComponent(new BeanComponentDefinition(handlerChainDef, chainBeanName));
|
||||
endpointDef.getPropertyValues().addPropertyValue(HANDLER_PROPERTY, new RuntimeBeanReference(chainBeanName));
|
||||
}
|
||||
}
|
||||
String handlerRef = element.getAttribute(HANDLER_REF_ATTRIBUTE);
|
||||
if (StringUtils.hasText(handlerRef)) {
|
||||
if (childHandlerRefs.size() > 0) {
|
||||
throw new MessagingConfigurationException(
|
||||
"The 'handler-ref' attribute is only supported when no 'handler' child elements are present");
|
||||
}
|
||||
String handlerMethod = element.getAttribute(HANDLER_METHOD_ATTRIBUTE);
|
||||
if (StringUtils.hasText(handlerMethod)) {
|
||||
String adapterBeanName = this.parseHandlerAdapter(handlerRef, handlerMethod, parserContext);
|
||||
endpointDef.getPropertyValues().addPropertyValue(HANDLER_PROPERTY, new RuntimeBeanReference(adapterBeanName));
|
||||
}
|
||||
else {
|
||||
endpointDef.getPropertyValues().addPropertyValue(HANDLER_PROPERTY, new RuntimeBeanReference(handlerRef));
|
||||
}
|
||||
}
|
||||
String beanName = element.getAttribute(ID_ATTRIBUTE);
|
||||
if (!StringUtils.hasText(beanName)) {
|
||||
beanName = parserContext.getReaderContext().generateBeanName(endpointDef);
|
||||
}
|
||||
parserContext.registerBeanComponent(new BeanComponentDefinition(endpointDef, beanName));
|
||||
return endpointDef;
|
||||
}
|
||||
|
||||
private String parseConsumer(Element element, ParserContext parserContext) {
|
||||
RootBeanDefinition consumerDef = new RootBeanDefinition(ConsumerPolicy.class);
|
||||
String period = element.getAttribute(PERIOD_ATTRIBUTE);
|
||||
if (StringUtils.hasText(period)) {
|
||||
consumerDef.getPropertyValues().addPropertyValue(PERIOD_PROPERTY, Integer.parseInt(period));
|
||||
}
|
||||
String beanName = parserContext.getReaderContext().generateBeanName(consumerDef);
|
||||
parserContext.registerBeanComponent(new BeanComponentDefinition(consumerDef, beanName));
|
||||
return beanName;
|
||||
}
|
||||
|
||||
private String parseHandlerAdapter(String handlerRef, String handlerMethod, ParserContext parserContext) {
|
||||
BeanDefinition handlerAdapterDef = new RootBeanDefinition(DefaultMessageHandlerAdapter.class);
|
||||
handlerAdapterDef.getPropertyValues().addPropertyValue(OBJECT_PROPERTY, new RuntimeBeanReference(handlerRef));
|
||||
handlerAdapterDef.getPropertyValues().addPropertyValue(METHOD_NAME_PROPERTY, handlerMethod);
|
||||
String adapterBeanName = parserContext.getReaderContext().generateBeanName(handlerAdapterDef);
|
||||
parserContext.registerBeanComponent(new BeanComponentDefinition(handlerAdapterDef, adapterBeanName));
|
||||
return adapterBeanName;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* Copyright 2002-2007 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.config;
|
||||
|
||||
import org.springframework.beans.factory.xml.NamespaceHandlerSupport;
|
||||
import org.springframework.integration.adapter.file.config.FileSourceAdapterParser;
|
||||
import org.springframework.integration.adapter.file.config.FileTargetAdapterParser;
|
||||
import org.springframework.integration.adapter.jms.config.JmsTargetAdapterParser;
|
||||
|
||||
/**
|
||||
* Namespace handler for the integration namespace.
|
||||
*
|
||||
* @author Mark Fisher
|
||||
*/
|
||||
public class IntegrationNamespaceHandler extends NamespaceHandlerSupport {
|
||||
|
||||
public void init() {
|
||||
registerBeanDefinitionParser("message-bus", new MessageBusParser());
|
||||
registerBeanDefinitionParser("annotation-driven", new AnnotationDrivenParser());
|
||||
registerBeanDefinitionParser("channel", new ChannelParser());
|
||||
registerBeanDefinitionParser("source-adapter", new ChannelAdapterParser(true));
|
||||
registerBeanDefinitionParser("target-adapter", new ChannelAdapterParser(false));
|
||||
registerBeanDefinitionParser("endpoint", new EndpointParser());
|
||||
registerBeanDefinitionParser("file-source", new FileSourceAdapterParser());
|
||||
registerBeanDefinitionParser("file-target", new FileTargetAdapterParser());
|
||||
registerBeanDefinitionParser("jms-target", new JmsTargetAdapterParser());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* Copyright 2002-2007 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.config;
|
||||
|
||||
import org.w3c.dom.Element;
|
||||
|
||||
import org.springframework.beans.factory.BeanDefinitionStoreException;
|
||||
import org.springframework.beans.factory.support.AbstractBeanDefinition;
|
||||
import org.springframework.beans.factory.xml.AbstractSimpleBeanDefinitionParser;
|
||||
import org.springframework.beans.factory.xml.ParserContext;
|
||||
import org.springframework.integration.bus.MessageBus;
|
||||
|
||||
/**
|
||||
* Parser for the <em>message-bus</em> element of the integration namespace.
|
||||
*
|
||||
* @author Mark Fisher
|
||||
*/
|
||||
public class MessageBusParser extends AbstractSimpleBeanDefinitionParser {
|
||||
|
||||
public static final String MESSAGE_BUS_BEAN_NAME = "org.springframework.integration.bus.internalMessageBus";
|
||||
|
||||
@Override
|
||||
protected String resolveId(Element element, AbstractBeanDefinition definition, ParserContext parserContext)
|
||||
throws BeanDefinitionStoreException {
|
||||
return MESSAGE_BUS_BEAN_NAME;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Class<?> getBeanClass(Element element) {
|
||||
return MessageBus.class;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,241 @@
|
||||
/*
|
||||
* Copyright 2002-2007 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.config;
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.beans.factory.config.BeanPostProcessor;
|
||||
import org.springframework.core.OrderComparator;
|
||||
import org.springframework.core.annotation.AnnotationUtils;
|
||||
import org.springframework.integration.MessagingConfigurationException;
|
||||
import org.springframework.integration.adapter.DefaultTargetAdapter;
|
||||
import org.springframework.integration.adapter.MethodInvokingSource;
|
||||
import org.springframework.integration.adapter.MethodInvokingTarget;
|
||||
import org.springframework.integration.adapter.PollingSourceAdapter;
|
||||
import org.springframework.integration.annotation.DefaultOutput;
|
||||
import org.springframework.integration.annotation.Handler;
|
||||
import org.springframework.integration.annotation.MessageEndpoint;
|
||||
import org.springframework.integration.annotation.Polled;
|
||||
import org.springframework.integration.annotation.Router;
|
||||
import org.springframework.integration.annotation.Splitter;
|
||||
import org.springframework.integration.bus.ConsumerPolicy;
|
||||
import org.springframework.integration.bus.MessageBus;
|
||||
import org.springframework.integration.channel.ChannelRegistryAware;
|
||||
import org.springframework.integration.channel.MessageChannel;
|
||||
import org.springframework.integration.channel.PointToPointChannel;
|
||||
import org.springframework.integration.endpoint.GenericMessageEndpoint;
|
||||
import org.springframework.integration.handler.MessageHandler;
|
||||
import org.springframework.integration.handler.MessageHandlerChain;
|
||||
import org.springframework.integration.handler.config.DefaultMessageHandlerCreator;
|
||||
import org.springframework.integration.handler.config.MessageHandlerCreator;
|
||||
import org.springframework.integration.handler.config.RouterMessageHandlerCreator;
|
||||
import org.springframework.integration.handler.config.SplitterMessageHandlerCreator;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ReflectionUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* A {@link BeanPostProcessor} implementation that generates endpoints for
|
||||
* classes annotated with {@link MessageEndpoint @MessageEndpoint}.
|
||||
*
|
||||
* @author Mark Fisher
|
||||
*/
|
||||
public class MessageEndpointAnnotationPostProcessor implements BeanPostProcessor, InitializingBean {
|
||||
|
||||
private Log logger = LogFactory.getLog(this.getClass());
|
||||
|
||||
private Map<Class<? extends Annotation>, MessageHandlerCreator> handlerCreators =
|
||||
new ConcurrentHashMap<Class<? extends Annotation>, MessageHandlerCreator>();
|
||||
|
||||
private MessageBus messageBus;
|
||||
|
||||
|
||||
public void setMessageBus(MessageBus messageBus) {
|
||||
Assert.notNull(messageBus, "messageBus must not be null");
|
||||
this.messageBus = messageBus;
|
||||
}
|
||||
|
||||
public void setCustomHandlerCreators(
|
||||
Map<Class<? extends Annotation>, MessageHandlerCreator> customHandlerCreators) {
|
||||
for (Map.Entry<Class<? extends Annotation>, MessageHandlerCreator> entry : customHandlerCreators.entrySet()) {
|
||||
this.handlerCreators.put(entry.getKey(), entry.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
public void afterPropertiesSet() {
|
||||
Assert.notNull(this.messageBus, "messageBus is required");
|
||||
this.handlerCreators.put(Handler.class, new DefaultMessageHandlerCreator());
|
||||
this.handlerCreators.put(Router.class, new RouterMessageHandlerCreator());
|
||||
this.handlerCreators.put(Splitter.class, new SplitterMessageHandlerCreator());
|
||||
}
|
||||
|
||||
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
|
||||
return bean;
|
||||
}
|
||||
|
||||
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
|
||||
MessageEndpoint endpointAnnotation = bean.getClass().getAnnotation(MessageEndpoint.class);
|
||||
if (endpointAnnotation == null) {
|
||||
return bean;
|
||||
}
|
||||
GenericMessageEndpoint endpoint = new GenericMessageEndpoint();
|
||||
this.configureInputChannel(bean, beanName, endpointAnnotation, endpoint);
|
||||
this.configureDefaultOutputChannel(bean, beanName, endpointAnnotation, endpoint);
|
||||
MessageHandlerChain handlerChain = this.createHandlerChain(bean);
|
||||
if (handlerChain != null) {
|
||||
endpoint.setHandler(handlerChain);
|
||||
}
|
||||
this.messageBus.registerEndpoint(beanName, endpoint);
|
||||
return endpoint;
|
||||
}
|
||||
|
||||
private void configureInputChannel(final Object bean, final String beanName,
|
||||
MessageEndpoint annotation, final GenericMessageEndpoint endpoint) {
|
||||
String channelName = annotation.input();
|
||||
if (StringUtils.hasText(channelName)) {
|
||||
endpoint.setInputChannelName(channelName);
|
||||
ConsumerPolicy consumerPolicy = new ConsumerPolicy();
|
||||
consumerPolicy.setPeriod(annotation.pollPeriod());
|
||||
endpoint.setConsumerPolicy(consumerPolicy);
|
||||
return;
|
||||
}
|
||||
ReflectionUtils.doWithMethods(bean.getClass(), new ReflectionUtils.MethodCallback() {
|
||||
public void doWith(Method method) throws IllegalArgumentException, IllegalAccessException {
|
||||
Annotation annotation = AnnotationUtils.getAnnotation(method, Polled.class);
|
||||
if (annotation != null) {
|
||||
int period = ((Polled) annotation).period();
|
||||
MethodInvokingSource<Object> source = new MethodInvokingSource<Object>();
|
||||
source.setObject(bean);
|
||||
source.setMethod(method.getName());
|
||||
PollingSourceAdapter<Object> adapter = new PollingSourceAdapter<Object>(source);
|
||||
MessageChannel channel = new PointToPointChannel();
|
||||
adapter.setChannel(channel);
|
||||
adapter.setPeriod(period);
|
||||
String channelName = beanName + "-inputChannel";
|
||||
messageBus.registerChannel(channelName, channel);
|
||||
messageBus.registerSourceAdapter(beanName + "-sourceAdapter", adapter);
|
||||
endpoint.setInputChannelName(channelName);
|
||||
endpoint.getConsumerPolicy().setPeriod(period);
|
||||
if (period > 0) {
|
||||
endpoint.getConsumerPolicy().setConcurrency(1);
|
||||
endpoint.getConsumerPolicy().setMaxConcurrency(1);
|
||||
endpoint.getConsumerPolicy().setMaxMessagesPerTask(1);
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void configureDefaultOutputChannel(final Object bean, final String beanName,
|
||||
final MessageEndpoint annotation, final GenericMessageEndpoint endpoint) {
|
||||
String channelName = annotation.defaultOutput();
|
||||
if (StringUtils.hasText(channelName)) {
|
||||
endpoint.setDefaultOutputChannelName(channelName);
|
||||
return;
|
||||
}
|
||||
ReflectionUtils.doWithMethods(bean.getClass(), new ReflectionUtils.MethodCallback() {
|
||||
boolean foundDefaultOutput = false;
|
||||
public void doWith(Method method) throws IllegalArgumentException, IllegalAccessException {
|
||||
Annotation annotation = AnnotationUtils.getAnnotation(method, DefaultOutput.class);
|
||||
if (annotation != null) {
|
||||
if (foundDefaultOutput) {
|
||||
throw new MessagingConfigurationException("only one @DefaultOutput allowed per endpoint");
|
||||
}
|
||||
MethodInvokingTarget<Object> target = new MethodInvokingTarget<Object>();
|
||||
target.setObject(bean);
|
||||
target.setMethod(method.getName());
|
||||
target.afterPropertiesSet();
|
||||
DefaultTargetAdapter adapter = new DefaultTargetAdapter(target);
|
||||
PointToPointChannel channel = new PointToPointChannel();
|
||||
String channelName = beanName + "-defaultOutputChannel";
|
||||
messageBus.registerChannel(channelName, channel);
|
||||
messageBus.registerTargetAdapter(beanName + "-targetAdapter", adapter);
|
||||
endpoint.setDefaultOutputChannelName(channelName);
|
||||
foundDefaultOutput = true;
|
||||
return;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private MessageHandlerChain createHandlerChain(final Object bean) {
|
||||
final List<MessageHandler> handlers = new ArrayList<MessageHandler>();
|
||||
ReflectionUtils.doWithMethods(bean.getClass(), new ReflectionUtils.MethodCallback() {
|
||||
public void doWith(Method method) throws IllegalArgumentException, IllegalAccessException {
|
||||
Annotation[] annotations = AnnotationUtils.getAnnotations(method);
|
||||
for (Annotation annotation : annotations) {
|
||||
if (isHandlerAnnotation(annotation)) {
|
||||
Map<String, ?> attributes = AnnotationUtils.getAnnotationAttributes(annotation);
|
||||
MessageHandlerCreator handlerCreator = handlerCreators.get(annotation.annotationType());
|
||||
if (handlerCreator == null) {
|
||||
if (logger.isWarnEnabled()) {
|
||||
logger.warn("No handler creator has been registered for handler annotation '" +
|
||||
annotation.annotationType() + "'");
|
||||
}
|
||||
}
|
||||
else {
|
||||
MessageHandler handler = handlerCreator.createHandler(bean, method, attributes);
|
||||
if (handler instanceof ChannelRegistryAware) {
|
||||
((ChannelRegistryAware) handler).setChannelRegistry(messageBus);
|
||||
}
|
||||
if (handler instanceof InitializingBean) {
|
||||
try {
|
||||
((InitializingBean) handler).afterPropertiesSet();
|
||||
}
|
||||
catch (Exception e) {
|
||||
throw new MessagingConfigurationException("failed to create handler", e);
|
||||
}
|
||||
}
|
||||
if (handler != null) {
|
||||
handlers.add(handler);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
if (handlers.size() > 0) {
|
||||
MessageHandlerChain handlerChain = new MessageHandlerChain();
|
||||
Collections.sort(handlers, new OrderComparator());
|
||||
for (MessageHandler handler : handlers) {
|
||||
handlerChain.add(handler);
|
||||
}
|
||||
return handlerChain;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private boolean isHandlerAnnotation(Annotation annotation) {
|
||||
return annotation.annotationType().equals(Handler.class)
|
||||
|| annotation.annotationType().isAnnotationPresent(Handler.class)
|
||||
|| this.handlerCreators.keySet().contains(annotation.annotationType());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,109 @@
|
||||
/*
|
||||
* Copyright 2002-2007 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.config;
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
|
||||
import org.springframework.aop.Advisor;
|
||||
import org.springframework.aop.framework.Advised;
|
||||
import org.springframework.aop.framework.ProxyFactory;
|
||||
import org.springframework.aop.support.AopUtils;
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.factory.BeanClassLoaderAware;
|
||||
import org.springframework.beans.factory.config.BeanPostProcessor;
|
||||
import org.springframework.integration.annotation.Publisher;
|
||||
import org.springframework.integration.aop.PublisherAnnotationAdvisor;
|
||||
import org.springframework.integration.channel.ChannelRegistry;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* A {@link BeanPostProcessor} that adds a message publishing interceptor when
|
||||
* it discovers annotated methods.
|
||||
*
|
||||
* @author Mark Fisher
|
||||
*/
|
||||
public class PublisherAnnotationPostProcessor implements BeanPostProcessor, BeanClassLoaderAware {
|
||||
|
||||
private Class<? extends Annotation> publisherAnnotationType = Publisher.class;
|
||||
|
||||
private String channelNameAttribute = "channel";
|
||||
|
||||
private ChannelRegistry channelRegistry;
|
||||
|
||||
private Advisor advisor;
|
||||
|
||||
private ClassLoader beanClassLoader;
|
||||
|
||||
|
||||
public void setBeanClassLoader(ClassLoader beanClassLoader) {
|
||||
Assert.notNull(beanClassLoader, "'beanClassLoader' must not be null");
|
||||
this.beanClassLoader = beanClassLoader;
|
||||
}
|
||||
|
||||
public void setPublisherAnnotationType(Class<? extends Annotation> publisherAnnotationType) {
|
||||
Assert.notNull(publisherAnnotationType, "'publisherAnnotationType' must not be null");
|
||||
this.publisherAnnotationType = publisherAnnotationType;
|
||||
}
|
||||
|
||||
public void setChannelNameAttribute(String channelNameAttribute) {
|
||||
Assert.notNull(channelNameAttribute, "'channelNameAttribute' must not be null");
|
||||
this.channelNameAttribute = channelNameAttribute;
|
||||
}
|
||||
|
||||
public void setChannelRegistry(ChannelRegistry channelRegistry) {
|
||||
Assert.notNull(channelRegistry, "'channelRegistry' must not be null");
|
||||
this.channelRegistry = channelRegistry;
|
||||
}
|
||||
|
||||
private void createAdvisor() {
|
||||
if (this.channelRegistry == null) {
|
||||
throw new IllegalStateException("'channelRegistry' is required");
|
||||
}
|
||||
this.advisor = new PublisherAnnotationAdvisor(this.publisherAnnotationType, this.channelNameAttribute,
|
||||
this.channelRegistry);
|
||||
}
|
||||
|
||||
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
|
||||
return bean;
|
||||
}
|
||||
|
||||
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
|
||||
Class<?> targetClass = bean instanceof Advised ?
|
||||
((Advised) bean).getTargetSource().getTargetClass() : bean.getClass();
|
||||
if (targetClass == null) {
|
||||
return bean;
|
||||
}
|
||||
if (advisor == null) {
|
||||
createAdvisor();
|
||||
}
|
||||
if (AopUtils.canApply(this.advisor, targetClass)) {
|
||||
if (bean instanceof Advised) {
|
||||
((Advised) bean).addAdvisor(this.advisor);
|
||||
return bean;
|
||||
}
|
||||
else {
|
||||
ProxyFactory pf = new ProxyFactory(bean);
|
||||
pf.addAdvisor(this.advisor);
|
||||
return pf.getProxy(this.beanClassLoader);
|
||||
}
|
||||
}
|
||||
else {
|
||||
return bean;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,101 @@
|
||||
/*
|
||||
* Copyright 2002-2007 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.config;
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import org.springframework.aop.framework.Advised;
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.factory.config.BeanPostProcessor;
|
||||
import org.springframework.core.annotation.AnnotationUtils;
|
||||
import org.springframework.integration.annotation.Subscriber;
|
||||
import org.springframework.integration.bus.MessageBus;
|
||||
import org.springframework.integration.endpoint.GenericMessageEndpoint;
|
||||
import org.springframework.integration.handler.DefaultMessageHandlerAdapter;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ClassUtils;
|
||||
import org.springframework.util.ReflectionUtils;
|
||||
|
||||
/**
|
||||
* A {@link BeanPostProcessor} that creates a method-invoking handler adapter
|
||||
* when it discovers methods annotated with {@link Subscriber @Subscriber}.
|
||||
*
|
||||
* @author Mark Fisher
|
||||
*/
|
||||
public class SubscriberAnnotationPostProcessor implements BeanPostProcessor {
|
||||
|
||||
private Log logger = LogFactory.getLog(this.getClass());
|
||||
|
||||
private Class<? extends Annotation> subscriberAnnotationType = Subscriber.class;
|
||||
|
||||
private String channelNameAttribute = "channel";
|
||||
|
||||
private MessageBus messageBus;
|
||||
|
||||
|
||||
public void setSubscriberAnnotationType(Class<? extends Annotation> subscriberAnnotationType) {
|
||||
Assert.notNull(subscriberAnnotationType, "'subscriberAnnotationType' must not be null");
|
||||
this.subscriberAnnotationType = subscriberAnnotationType;
|
||||
}
|
||||
|
||||
public void setChannelNameAttribute(String channelNameAttribute) {
|
||||
Assert.notNull(channelNameAttribute, "'channelNameAttribute' must not be null");
|
||||
this.channelNameAttribute = channelNameAttribute;
|
||||
}
|
||||
|
||||
public void setMessageBus(MessageBus messageBus) {
|
||||
Assert.notNull(messageBus, "'messageBus' must not be null");
|
||||
this.messageBus = messageBus;
|
||||
}
|
||||
|
||||
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
|
||||
return bean;
|
||||
}
|
||||
|
||||
public Object postProcessAfterInitialization(final Object bean, String beanName) throws BeansException {
|
||||
final Class<?> targetClass = bean instanceof Advised ?
|
||||
((Advised) bean).getTargetSource().getTargetClass() : bean.getClass();
|
||||
if (targetClass == null) {
|
||||
return bean;
|
||||
}
|
||||
ReflectionUtils.doWithMethods(targetClass, new ReflectionUtils.MethodCallback() {
|
||||
public void doWith(Method method) throws IllegalArgumentException, IllegalAccessException {
|
||||
Annotation annotation = method.getAnnotation(subscriberAnnotationType);
|
||||
if (annotation != null) {
|
||||
String channelName = (String) AnnotationUtils.getValue(annotation, channelNameAttribute);
|
||||
DefaultMessageHandlerAdapter adapter = new DefaultMessageHandlerAdapter();
|
||||
adapter.setMethodName(method.getName());
|
||||
adapter.setObject(bean);
|
||||
adapter.afterPropertiesSet();
|
||||
GenericMessageEndpoint endpoint = new GenericMessageEndpoint();
|
||||
endpoint.setInputChannelName(channelName);
|
||||
endpoint.setChannelRegistry(messageBus);
|
||||
endpoint.setHandler(adapter);
|
||||
String endpointName = ClassUtils.getShortNameAsProperty(targetClass) +
|
||||
"-" + method.getName() + "-endpoint";
|
||||
messageBus.registerEndpoint(endpointName, endpoint);
|
||||
}
|
||||
}
|
||||
});
|
||||
return bean;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,176 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<xsd:schema xmlns="http://www.springframework.org/schema/integration"
|
||||
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
|
||||
xmlns:beans="http://www.springframework.org/schema/beans"
|
||||
xmlns:tool="http://www.springframework.org/schema/tool"
|
||||
targetNamespace="http://www.springframework.org/schema/integration"
|
||||
elementFormDefault="qualified"
|
||||
attributeFormDefault="unqualified">
|
||||
|
||||
<xsd:import namespace="http://www.springframework.org/schema/beans"/>
|
||||
<xsd:import namespace="http://www.springframework.org/schema/tool"/>
|
||||
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
Defines the configuration elements for Spring Integration.
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
|
||||
<xsd:element name="message-bus">
|
||||
<xsd:complexType>
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
Defines a message bus.
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
<xsd:attribute name="auto-create-channels" type="xsd:boolean"/>
|
||||
<xsd:attribute name="invalid-message-channel" type="xsd:string"/>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
|
||||
<xsd:element name="annotation-driven">
|
||||
<xsd:complexType>
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
Enables the annotation-driven post-processors.
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
|
||||
<xsd:element name="channel">
|
||||
<xsd:complexType>
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
Defines a message channel.
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
<xsd:complexContent>
|
||||
<xsd:extension base="beans:identifiedType">
|
||||
<xsd:attribute name="capacity" type="xsd:integer"/>
|
||||
</xsd:extension>
|
||||
</xsd:complexContent>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
|
||||
<xsd:element name="source-adapter">
|
||||
<xsd:complexType>
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
Defines a source (inbound) channel adapter.
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
<xsd:complexContent>
|
||||
<xsd:extension base="beans:identifiedType">
|
||||
<xsd:attribute name="ref" type="xsd:string" use="required"/>
|
||||
<xsd:attribute name="method" type="xsd:string" use="required"/>
|
||||
<xsd:attribute name="channel" type="xsd:string" use="required"/>
|
||||
<xsd:attribute name="period" type="xsd:int"/>
|
||||
</xsd:extension>
|
||||
</xsd:complexContent>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
|
||||
<xsd:element name="target-adapter">
|
||||
<xsd:complexType>
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
Defines a target (outbound) channel adapter.
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
<xsd:complexContent>
|
||||
<xsd:extension base="beans:identifiedType">
|
||||
<xsd:attribute name="ref" type="xsd:string" use="required"/>
|
||||
<xsd:attribute name="method" type="xsd:string" use="required"/>
|
||||
<xsd:attribute name="channel" type="xsd:string" use="required"/>
|
||||
</xsd:extension>
|
||||
</xsd:complexContent>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
|
||||
<xsd:element name="endpoint">
|
||||
<xsd:complexType>
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
Defines a message endpoint.
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
<xsd:complexContent>
|
||||
<xsd:extension base="beans:identifiedType">
|
||||
<xsd:sequence>
|
||||
<xsd:element ref="consumer" minOccurs="0" maxOccurs="1"/>
|
||||
<xsd:element ref="handler" minOccurs="0" maxOccurs="unbounded"/>
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="input-channel" type="xsd:string"/>
|
||||
<xsd:attribute name="default-output-channel" type="xsd:string"/>
|
||||
<xsd:attribute name="handler-ref" type="xsd:string"/>
|
||||
<xsd:attribute name="handler-method" type="xsd:string"/>
|
||||
</xsd:extension>
|
||||
</xsd:complexContent>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
|
||||
<xsd:element name="consumer">
|
||||
<xsd:complexType>
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
Defines a consumer policy.
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
<xsd:attribute name="period" type="xsd:int"/>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
|
||||
<xsd:element name="handler">
|
||||
<xsd:complexType>
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
Defines a handler.
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
<xsd:attribute name="ref" type="xsd:string" use="required"/>
|
||||
<xsd:attribute name="method" type="xsd:string"/>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
|
||||
<xsd:element name="file-source">
|
||||
<xsd:complexType>
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
Defines a file-based source channel adapter.
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
<xsd:attribute name="directory" type="xsd:string" use="required"/>
|
||||
<xsd:attribute name="channel" type="xsd:string" use="required"/>
|
||||
<xsd:attribute name="poll-period" type="xsd:int" use="required"/>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
|
||||
<xsd:element name="file-target">
|
||||
<xsd:complexType>
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
Defines a file-based target channel adapter.
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
<xsd:attribute name="directory" type="xsd:string" use="required"/>
|
||||
<xsd:attribute name="channel" type="xsd:string" use="required"/>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
|
||||
<xsd:element name="jms-target">
|
||||
<xsd:complexType>
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
Defines a jms-based target channel adapter.
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
<xsd:attribute name="jms-template" type="xsd:string"/>
|
||||
<xsd:attribute name="connection-factory" type="xsd:string"/>
|
||||
<xsd:attribute name="destination" type="xsd:string"/>
|
||||
<xsd:attribute name="channel" type="xsd:string" use="required"/>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
|
||||
</xsd:schema>
|
||||
@@ -0,0 +1,137 @@
|
||||
/*
|
||||
* Copyright 2002-2007 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.endpoint;
|
||||
|
||||
import org.springframework.integration.MessageHandlingException;
|
||||
import org.springframework.integration.MessagingConfigurationException;
|
||||
import org.springframework.integration.bus.ConsumerPolicy;
|
||||
import org.springframework.integration.channel.ChannelRegistry;
|
||||
import org.springframework.integration.channel.MessageChannel;
|
||||
import org.springframework.integration.handler.MessageHandler;
|
||||
import org.springframework.integration.message.Message;
|
||||
|
||||
/**
|
||||
* A generic endpoint implementation designed to accommodate a variety of
|
||||
* strategies including:
|
||||
* <ul>
|
||||
* <li><i>source channel-adapter:</i> source adapter + target channel</li>
|
||||
* <li><i>target channel-adapter:</i> source channel + target adapter</li>
|
||||
* <li><i>one-way:</i> source + handler that returns null and no target</li>
|
||||
* <li><i>request-reply:</i> source + handler and either a reply channel
|
||||
* specified on the request message or a default target on the endpoint</i>
|
||||
* </ul>
|
||||
*
|
||||
* @author Mark Fisher
|
||||
*/
|
||||
public class GenericMessageEndpoint<T> implements MessageEndpoint<T> {
|
||||
|
||||
private String inputChannelName;
|
||||
|
||||
private String defaultOutputChannelName;
|
||||
|
||||
private MessageHandler handler;
|
||||
|
||||
private ChannelRegistry channelRegistry;
|
||||
|
||||
private ConsumerPolicy consumerPolicy = new ConsumerPolicy();
|
||||
|
||||
|
||||
/**
|
||||
* Set the name of the channel from which this endpoint receives messages.
|
||||
*/
|
||||
public void setInputChannelName(String inputChannelName) {
|
||||
this.inputChannelName = inputChannelName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the name of the channel from which this endpoint receives messages.
|
||||
*/
|
||||
public String getInputChannelName() {
|
||||
return this.inputChannelName;
|
||||
}
|
||||
|
||||
public void setConsumerPolicy(ConsumerPolicy consumerPolicy) {
|
||||
this.consumerPolicy = consumerPolicy;
|
||||
}
|
||||
|
||||
public ConsumerPolicy getConsumerPolicy() {
|
||||
return this.consumerPolicy;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the name of the channel to which this endpoint can send reply messages by default.
|
||||
*/
|
||||
public void setDefaultOutputChannelName(String defaultOutputChannelName) {
|
||||
this.defaultOutputChannelName = defaultOutputChannelName;
|
||||
}
|
||||
|
||||
public String getDefaultOutputChannelName() {
|
||||
return this.defaultOutputChannelName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a handler to be invoked for each consumed message.
|
||||
*/
|
||||
public void setHandler(MessageHandler handler) {
|
||||
this.handler = handler;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the channel registry to use for looking up channels by name.
|
||||
*/
|
||||
public void setChannelRegistry(ChannelRegistry channelRegistry) {
|
||||
this.channelRegistry = channelRegistry;
|
||||
}
|
||||
|
||||
|
||||
public void messageReceived(Message<T> message) {
|
||||
if (this.handler == null) {
|
||||
if (this.defaultOutputChannelName == null) {
|
||||
throw new MessagingConfigurationException(
|
||||
"endpoint must have either a 'handler' or 'defaultOutputChannelName'");
|
||||
}
|
||||
MessageChannel replyChannel = this.channelRegistry.lookupChannel(this.defaultOutputChannelName);
|
||||
replyChannel.send(message);
|
||||
return;
|
||||
}
|
||||
Message<?> replyMessage = handler.handle(message);
|
||||
if (replyMessage != null) {
|
||||
MessageChannel replyChannel = this.resolveReplyChannel(message);
|
||||
if (replyChannel == null) {
|
||||
throw new MessageHandlingException("Unable to determine reply channel for message. "
|
||||
+ "Provide a 'replyChannelName' in the message header or a 'defaultOutputChannelName' "
|
||||
+ "on the message endpoint.");
|
||||
}
|
||||
replyChannel.send(replyMessage);
|
||||
}
|
||||
}
|
||||
|
||||
private MessageChannel resolveReplyChannel(Message<?> message) {
|
||||
if (this.channelRegistry == null) {
|
||||
return null;
|
||||
}
|
||||
String replyChannelName = message.getHeader().getReplyChannelName();
|
||||
if (replyChannelName != null && replyChannelName.trim().length() > 0) {
|
||||
return this.channelRegistry.lookupChannel(replyChannelName);
|
||||
}
|
||||
if (this.defaultOutputChannelName != null) {
|
||||
return this.channelRegistry.lookupChannel(this.defaultOutputChannelName);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* Copyright 2002-2007 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.endpoint;
|
||||
|
||||
import org.springframework.integration.bus.ConsumerPolicy;
|
||||
import org.springframework.integration.channel.ChannelRegistry;
|
||||
import org.springframework.integration.message.MessageReceiver;
|
||||
|
||||
/**
|
||||
* Base interface for message endpoints.
|
||||
*
|
||||
* @author Mark Fisher
|
||||
*/
|
||||
public interface MessageEndpoint<T> extends MessageReceiver<T> {
|
||||
|
||||
void setInputChannelName(String inputChannelName);
|
||||
|
||||
String getInputChannelName();
|
||||
|
||||
void setDefaultOutputChannelName(String defaultOutputChannelName);
|
||||
|
||||
String getDefaultOutputChannelName();
|
||||
|
||||
ConsumerPolicy getConsumerPolicy();
|
||||
|
||||
void setChannelRegistry(ChannelRegistry channelRegistry);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,132 @@
|
||||
/*
|
||||
* Copyright 2002-2007 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.handler;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.core.Ordered;
|
||||
import org.springframework.integration.message.Message;
|
||||
import org.springframework.integration.message.MessageMapper;
|
||||
import org.springframework.integration.message.SimplePayloadMessageMapper;
|
||||
import org.springframework.integration.util.SimpleMethodInvoker;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Base implementation of the {@link MessageHandler} interface that creates an
|
||||
* invoker for the specified method and target object. It also accepts an
|
||||
* implementation of the {@link MessageMapper} strategy which it exposes to
|
||||
* subclasses for converting the {@link Message} to an object. Likewise, if the
|
||||
* method has a non-null return value, a reply message will be generated by the
|
||||
* mapper.
|
||||
*
|
||||
* @author Mark Fisher
|
||||
*/
|
||||
public abstract class AbstractMessageHandlerAdapter<T> implements MessageHandler, Ordered, InitializingBean {
|
||||
|
||||
protected Log logger = LogFactory.getLog(this.getClass());
|
||||
|
||||
private T object;
|
||||
|
||||
private String methodName;
|
||||
|
||||
private MessageMapper mapper = new SimplePayloadMessageMapper();
|
||||
|
||||
private SimpleMethodInvoker<T> invoker;
|
||||
|
||||
private int order = Integer.MAX_VALUE;
|
||||
|
||||
private volatile boolean initialized;
|
||||
|
||||
private Object lifecycleMonitor = new Object();
|
||||
|
||||
|
||||
public void setObject(T object) {
|
||||
Assert.notNull(object, "'object' must not be null");
|
||||
this.object = object;
|
||||
}
|
||||
|
||||
protected Object getObject() {
|
||||
return this.object;
|
||||
}
|
||||
|
||||
public void setMethodName(String methodName) {
|
||||
Assert.notNull(methodName, "'methodName' must not be null");
|
||||
this.methodName = methodName;
|
||||
}
|
||||
|
||||
public String getMethodName() {
|
||||
return this.methodName;
|
||||
}
|
||||
|
||||
public void setMapper(MessageMapper mapper) {
|
||||
Assert.notNull(mapper, "'mapper' must not be null");
|
||||
this.mapper = mapper;
|
||||
}
|
||||
|
||||
protected MessageMapper getMapper() {
|
||||
return this.mapper;
|
||||
}
|
||||
|
||||
public void setOrder(int order) {
|
||||
this.order = order;
|
||||
}
|
||||
|
||||
public int getOrder() {
|
||||
return this.order;
|
||||
}
|
||||
|
||||
public final void afterPropertiesSet() {
|
||||
this.validate();
|
||||
synchronized (this.lifecycleMonitor) {
|
||||
this.invoker = new SimpleMethodInvoker<T>(this.object, this.methodName);
|
||||
this.initialized = true;
|
||||
}
|
||||
}
|
||||
|
||||
public final boolean isInitialized() {
|
||||
synchronized (this.lifecycleMonitor) {
|
||||
return this.initialized;
|
||||
}
|
||||
}
|
||||
|
||||
public final Message<?> handle(Message<?> message) {
|
||||
Object result = this.doHandle(message, invoker);
|
||||
if (result != null) {
|
||||
if (result instanceof Message) {
|
||||
return (Message<?>) result;
|
||||
}
|
||||
return this.mapper.toMessage(result);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Subclasses may override this method to provide validation upon initialization.
|
||||
*/
|
||||
protected void validate() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Subclasses must implement this method. The invoker has been created for
|
||||
* the provided target object and method. May return an object of type
|
||||
* {@link Message}, else rely on the message mapper to convert.
|
||||
*/
|
||||
protected abstract Object doHandle(Message message, SimpleMethodInvoker invoker);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* Copyright 2002-2007 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.handler;
|
||||
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.core.Ordered;
|
||||
import org.springframework.integration.message.Message;
|
||||
import org.springframework.integration.message.MessageMapper;
|
||||
import org.springframework.integration.util.SimpleMethodInvoker;
|
||||
|
||||
/**
|
||||
* An implementation of {@link MessageHandler} that invokes the specified method
|
||||
* on the provided target object. It then uses a {@link MessageMapper} strategy
|
||||
* for converting the object to a {@link Message}. If the method has a non-null
|
||||
* return value, a reply message will be generated by the mapper.
|
||||
*
|
||||
* @author Mark Fisher
|
||||
*/
|
||||
public class DefaultMessageHandlerAdapter<T> extends AbstractMessageHandlerAdapter<T>
|
||||
implements Ordered, InitializingBean {
|
||||
|
||||
public Object doHandle(Message message, SimpleMethodInvoker invoker) {
|
||||
return invoker.invokeMethod(this.getMapper().fromMessage(message));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
* Copyright 2002-2007 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.handler;
|
||||
|
||||
import org.springframework.integration.message.Message;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* A message handler implementation that intercepts calls to another handler.
|
||||
*
|
||||
* @author Mark Fisher
|
||||
*/
|
||||
public abstract class InterceptingMessageHandler implements MessageHandler {
|
||||
|
||||
private MessageHandler target;
|
||||
|
||||
|
||||
public InterceptingMessageHandler(MessageHandler target) {
|
||||
Assert.notNull(target, "target must not be null");
|
||||
this.target = target;
|
||||
}
|
||||
|
||||
public Message handle(Message message) {
|
||||
return handle(message, this.target);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* The handler method for subclasses to implement.
|
||||
*
|
||||
* @param message the message to handle
|
||||
* @param target the intercepted handler
|
||||
* @return a reply message or null
|
||||
*/
|
||||
public abstract Message handle(Message message, MessageHandler target);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* Copyright 2002-2007 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.handler;
|
||||
|
||||
import org.springframework.integration.message.Message;
|
||||
|
||||
/**
|
||||
* Generic message handler interface. Typical implementations will translate
|
||||
* between the generic Messages of the integration framework and the domain
|
||||
* objects that are passed-to and returned-from business components.
|
||||
*
|
||||
* @author Mark Fisher
|
||||
*/
|
||||
public interface MessageHandler {
|
||||
|
||||
Message<?> handle(Message<?> message);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
/*
|
||||
* Copyright 2002-2007 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.handler;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CopyOnWriteArrayList;
|
||||
|
||||
import org.springframework.integration.message.Message;
|
||||
|
||||
/**
|
||||
* A message handler implementation that passes incoming messages through a
|
||||
* chain of handlers.
|
||||
*
|
||||
* @author Mark Fisher
|
||||
*/
|
||||
public class MessageHandlerChain implements MessageHandler {
|
||||
|
||||
private List<MessageHandler> handlers = new CopyOnWriteArrayList<MessageHandler>();
|
||||
|
||||
|
||||
/**
|
||||
* Add a handler to the end of the chain.
|
||||
*/
|
||||
public void add(MessageHandler handler) {
|
||||
this.handlers.add(handler);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a handler to the chain at the specified index.
|
||||
*/
|
||||
public void add(int index, MessageHandler handler) {
|
||||
this.handlers.add(index, handler);
|
||||
}
|
||||
|
||||
public void setHandlers(List<MessageHandler> handlers) {
|
||||
this.handlers.clear();
|
||||
this.handlers.addAll(handlers);
|
||||
}
|
||||
|
||||
public Message handle(Message message) {
|
||||
for (MessageHandler next : handlers) {
|
||||
message = next.handle(message);
|
||||
if (message == null) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
return message;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
* Copyright 2002-2007 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.handler.config;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.core.annotation.AnnotationUtils;
|
||||
import org.springframework.core.annotation.Order;
|
||||
import org.springframework.integration.handler.AbstractMessageHandlerAdapter;
|
||||
import org.springframework.integration.handler.MessageHandler;
|
||||
|
||||
/**
|
||||
* Base class for handler creators that generate a {@link MessageHandler}
|
||||
* adapter for the provided object and method.
|
||||
*
|
||||
* @author Mark Fisher
|
||||
*/
|
||||
public abstract class AbstractMessageHandlerCreator implements MessageHandlerCreator {
|
||||
|
||||
public final MessageHandler createHandler(Object object, Method method, Map<String, ?> attributes) {
|
||||
MessageHandler handler = this.doCreateHandler(object, method, attributes);
|
||||
if (handler instanceof AbstractMessageHandlerAdapter<?>) {
|
||||
AbstractMessageHandlerAdapter adapter = ((AbstractMessageHandlerAdapter) handler);
|
||||
adapter.setObject(object);
|
||||
adapter.setMethodName(method.getName());
|
||||
Order orderAnnotation = (Order) AnnotationUtils.getAnnotation(method, Order.class);
|
||||
if (orderAnnotation != null) {
|
||||
adapter.setOrder(orderAnnotation.value());
|
||||
}
|
||||
}
|
||||
return handler;
|
||||
}
|
||||
|
||||
protected abstract MessageHandler doCreateHandler(Object object, Method method, Map<String, ?> attributes);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* Copyright 2002-2007 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.handler.config;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.core.annotation.Order;
|
||||
import org.springframework.integration.handler.DefaultMessageHandlerAdapter;
|
||||
import org.springframework.integration.handler.MessageHandler;
|
||||
|
||||
/**
|
||||
* Default implementation of the handler creator strategy that creates a
|
||||
* {@link DefaultMessageHandlerAdapter} for the provided object and method.
|
||||
* This version does not even consider the attributes. It does however respect
|
||||
* an {@link Order} annotation if present.
|
||||
*
|
||||
* @author Mark Fisher
|
||||
*/
|
||||
public class DefaultMessageHandlerCreator extends AbstractMessageHandlerCreator {
|
||||
|
||||
public MessageHandler doCreateHandler(Object object, Method method, Map<String, ?> attributes) {
|
||||
return new DefaultMessageHandlerAdapter<Object>();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* Copyright 2002-2007 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.handler.config;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.integration.handler.MessageHandler;
|
||||
|
||||
/**
|
||||
* Strategy interface for creating {@link MessageHandler MessageHandlers}.
|
||||
*
|
||||
* @author Mark Fisher
|
||||
*/
|
||||
public interface MessageHandlerCreator {
|
||||
|
||||
MessageHandler createHandler(Object object, Method method, Map<String, ?> attributes);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Copyright 2002-2007 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.handler.config;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.integration.handler.MessageHandler;
|
||||
import org.springframework.integration.router.RouterMessageHandlerAdapter;
|
||||
|
||||
/**
|
||||
* Creates a {@link MessageHandler} adapter for router methods.
|
||||
*
|
||||
* @author Mark Fisher
|
||||
*/
|
||||
public class RouterMessageHandlerCreator extends AbstractMessageHandlerCreator {
|
||||
|
||||
public MessageHandler doCreateHandler(Object object, Method method, Map<String, ?> attributes) {
|
||||
return new RouterMessageHandlerAdapter(object, method, attributes);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Copyright 2002-2007 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.handler.config;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.integration.handler.MessageHandler;
|
||||
import org.springframework.integration.router.SplitterMessageHandlerAdapter;
|
||||
|
||||
/**
|
||||
* Creates a {@link MessageHandler} adapter for splitter methods.
|
||||
*
|
||||
* @author Mark Fisher
|
||||
*/
|
||||
public class SplitterMessageHandlerCreator extends AbstractMessageHandlerCreator {
|
||||
|
||||
public MessageHandler doCreateHandler(Object object, Method method, Map<String, ?> attributes) {
|
||||
return new SplitterMessageHandlerAdapter(object, method, attributes);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* Copyright 2002-2007 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.message;
|
||||
|
||||
import org.springframework.integration.util.RandomGuidUidGenerator;
|
||||
import org.springframework.integration.util.UidGenerator;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Base class that provides the default {@link UidGenerator} as well as a setter
|
||||
* for providing a custom id generator implementation.
|
||||
*
|
||||
* @author Mark Fisher
|
||||
*/
|
||||
public abstract class AbstractMessageMapper<M, O> implements MessageMapper<M, O> {
|
||||
|
||||
private UidGenerator uidGenerator = new RandomGuidUidGenerator();
|
||||
|
||||
|
||||
public void setUidGenerator(UidGenerator uidGenerator) {
|
||||
Assert.notNull(uidGenerator, "'uidGenerator' must not be null");
|
||||
this.uidGenerator = uidGenerator;
|
||||
}
|
||||
|
||||
public UidGenerator getUidGenerator() {
|
||||
return this.uidGenerator;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,84 @@
|
||||
/*
|
||||
* Copyright 2002-2007 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.message;
|
||||
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
|
||||
import org.springframework.integration.SystemInterruptedException;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Base Message class defining common properties such as id, header, and lock.
|
||||
*
|
||||
* @author Mark Fisher
|
||||
*/
|
||||
public class GenericMessage<T> implements Message<T> {
|
||||
|
||||
private Object id;
|
||||
|
||||
private MessageHeader header = new MessageHeader();
|
||||
|
||||
private T payload;
|
||||
|
||||
private ReentrantLock lock;
|
||||
|
||||
|
||||
public GenericMessage(Object id, T payload) {
|
||||
Assert.notNull(id, "id must not be null");
|
||||
Assert.notNull(payload, "payload must not be null");
|
||||
this.id = id;
|
||||
this.payload = payload;
|
||||
}
|
||||
|
||||
public Object getId() {
|
||||
return this.id;
|
||||
}
|
||||
|
||||
public MessageHeader getHeader() {
|
||||
return this.header;
|
||||
}
|
||||
|
||||
protected void setHeader(MessageHeader header) {
|
||||
this.header = header;
|
||||
}
|
||||
|
||||
public T getPayload() {
|
||||
return this.payload;
|
||||
}
|
||||
|
||||
protected void setPayload(T newPayload) {
|
||||
this.payload = newPayload;
|
||||
}
|
||||
|
||||
public void lock() {
|
||||
this.lock.lock();
|
||||
}
|
||||
|
||||
public void lockInterruptibly() {
|
||||
try {
|
||||
lock.lockInterruptibly();
|
||||
}
|
||||
catch (InterruptedException e) {
|
||||
throw new SystemInterruptedException("Unable to obtain lock for message", e);
|
||||
}
|
||||
}
|
||||
|
||||
public void unlock() {
|
||||
lock.unlock();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Copyright 2002-2007 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.message;
|
||||
|
||||
/**
|
||||
* The central interface that any Message type must implement.
|
||||
*
|
||||
* @author Mark Fisher
|
||||
*/
|
||||
public interface Message<T> {
|
||||
|
||||
Object getId();
|
||||
|
||||
MessageHeader getHeader();
|
||||
|
||||
T getPayload();
|
||||
|
||||
void lock();
|
||||
|
||||
void unlock();
|
||||
|
||||
}
|
||||
@@ -0,0 +1,114 @@
|
||||
/*
|
||||
* Copyright 2002-2007 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.message;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
/**
|
||||
* A holder for Message metadata. This includes information that is used by the
|
||||
* messaging system (such <i>correlationId</i>) as well as information that is
|
||||
* relevant for specific messaging endpoints. For the latter, String values may
|
||||
* be stored as <i>properties</i> and Object values may be stored as
|
||||
* <i>attributes</i>.
|
||||
*
|
||||
* @author Mark Fisher
|
||||
*/
|
||||
public class MessageHeader {
|
||||
|
||||
private Object correlationId;
|
||||
|
||||
private String replyChannelName;
|
||||
|
||||
private Date expiration;
|
||||
|
||||
private int sequenceNumber = 1;
|
||||
|
||||
private int sequenceSize = 1;
|
||||
|
||||
private Properties properties = new Properties();
|
||||
|
||||
private Map<String, Object> attributes = new ConcurrentHashMap<String, Object>();
|
||||
|
||||
|
||||
public Object getCorrelationId() {
|
||||
return this.correlationId;
|
||||
}
|
||||
|
||||
public void setCorrelationId(Object correlationId) {
|
||||
this.correlationId = correlationId;
|
||||
}
|
||||
|
||||
public String getReplyChannelName() {
|
||||
return this.replyChannelName;
|
||||
}
|
||||
|
||||
public void setReplyChannelName(String replyChannelName) {
|
||||
this.replyChannelName = replyChannelName;
|
||||
}
|
||||
|
||||
public int getSequenceNumber() {
|
||||
return this.sequenceNumber;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the expiration date for this message or <code>null</code> to
|
||||
* indicate 'never expire'. The default is <code>null</code>.
|
||||
*/
|
||||
public void setExpiration(Date expiration) {
|
||||
this.expiration = expiration;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the expiration date for this message or <code>null</code> to
|
||||
* indicate 'never expire'.
|
||||
*/
|
||||
public Date getExpiration() {
|
||||
return this.expiration;
|
||||
}
|
||||
|
||||
public void setSequenceNumber(int sequenceNumber) {
|
||||
this.sequenceNumber = sequenceNumber;
|
||||
}
|
||||
|
||||
public int getSequenceSize() {
|
||||
return this.sequenceSize;
|
||||
}
|
||||
|
||||
public void setSequenceSize(int sequenceSize) {
|
||||
this.sequenceSize = sequenceSize;
|
||||
}
|
||||
|
||||
public String getProperty(String key) {
|
||||
return this.properties.getProperty(key);
|
||||
}
|
||||
|
||||
public void setProperty(String key, String value) {
|
||||
this.properties.setProperty(key, value);
|
||||
}
|
||||
|
||||
public Object getAttribute(String key) {
|
||||
return this.attributes.get(key);
|
||||
}
|
||||
|
||||
public void setAttribute(String key, Object value) {
|
||||
this.attributes.put(key, value);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Copyright 2002-2007 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.message;
|
||||
|
||||
/**
|
||||
* Strategy interface for mapping between messages and objects.
|
||||
*
|
||||
* @author Mark Fisher
|
||||
*/
|
||||
public interface MessageMapper<M,O> {
|
||||
|
||||
/**
|
||||
* Map to a {@link Message} from the given object.
|
||||
*/
|
||||
Message<M> toMessage(O source);
|
||||
|
||||
/**
|
||||
* Map from the given {@link Message} to an object.
|
||||
*/
|
||||
O fromMessage(Message<M> message);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
* Copyright 2002-2007 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.message;
|
||||
|
||||
/**
|
||||
* The primary callback interface for any component capable of receiving
|
||||
* messages. This includes message endpoints as well as target adapters.
|
||||
*
|
||||
* @author Mark Fisher
|
||||
*/
|
||||
public interface MessageReceiver<T> {
|
||||
|
||||
void messageReceived(Message<T> message);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
* Copyright 2002-2007 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.message;
|
||||
|
||||
/**
|
||||
* Strategy interface for message selection.
|
||||
*
|
||||
* @author Mark Fisher
|
||||
*/
|
||||
public interface MessageSelector {
|
||||
|
||||
boolean accept(Message<?> message);
|
||||
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user