Migrated to Gradle build
This commit migrates from a Maven-based build system to a Gradle-based one. Changes include: - Removed archetype & parent - Renamed core, support, test, security and xml directories to spring-ws-core, spring-ws-test, spring-ws-security, spring-xml respectively. - Moved samples to separate project (https://github.com/spring-projects/spring-ws-samples)
This commit is contained in:
committed by
Arjen Poutsma
parent
a8c1d2ad97
commit
843ca6d2ef
@@ -0,0 +1,171 @@
|
||||
/*
|
||||
* Copyright 2005-2010 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.ws.transport.http;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.util.Collections;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.FileCopyUtils;
|
||||
import org.springframework.ws.WebServiceMessage;
|
||||
import org.springframework.ws.transport.AbstractReceiverConnection;
|
||||
import org.springframework.ws.transport.EndpointAwareWebServiceConnection;
|
||||
import org.springframework.ws.transport.FaultAwareWebServiceConnection;
|
||||
import org.springframework.ws.transport.WebServiceConnection;
|
||||
|
||||
import com.sun.net.httpserver.HttpExchange;
|
||||
|
||||
/**
|
||||
* Implementation of {@link WebServiceConnection} that is based on the Java 6 HttpServer {@link HttpExchange}.
|
||||
*
|
||||
* @author Arjen Poutsma
|
||||
* @since 1.5.0
|
||||
*/
|
||||
public class HttpExchangeConnection extends AbstractReceiverConnection
|
||||
implements EndpointAwareWebServiceConnection, FaultAwareWebServiceConnection {
|
||||
|
||||
private final HttpExchange httpExchange;
|
||||
|
||||
private ByteArrayOutputStream responseBuffer;
|
||||
|
||||
private int responseStatusCode = HttpTransportConstants.STATUS_ACCEPTED;
|
||||
|
||||
private boolean chunkedEncoding;
|
||||
|
||||
/** Constructs a new exchange connection with the given <code>HttpExchange</code>. */
|
||||
protected HttpExchangeConnection(HttpExchange httpExchange) {
|
||||
Assert.notNull(httpExchange, "'httpExchange' must not be null");
|
||||
this.httpExchange = httpExchange;
|
||||
}
|
||||
|
||||
/** Returns the <code>HttpExchange</code> for this connection. */
|
||||
public HttpExchange getHttpExchange() {
|
||||
return httpExchange;
|
||||
}
|
||||
|
||||
public URI getUri() throws URISyntaxException {
|
||||
return httpExchange.getRequestURI();
|
||||
}
|
||||
|
||||
void setChunkedEncoding(boolean chunkedEncoding) {
|
||||
this.chunkedEncoding = chunkedEncoding;
|
||||
}
|
||||
|
||||
public void endpointNotFound() {
|
||||
responseStatusCode = HttpTransportConstants.STATUS_NOT_FOUND;
|
||||
}
|
||||
|
||||
/*
|
||||
* Errors
|
||||
*/
|
||||
|
||||
public boolean hasError() throws IOException {
|
||||
return false;
|
||||
}
|
||||
|
||||
public String getErrorMessage() throws IOException {
|
||||
return null;
|
||||
}
|
||||
|
||||
/*
|
||||
* Receiving request
|
||||
*/
|
||||
|
||||
@Override
|
||||
protected Iterator<String> getRequestHeaderNames() throws IOException {
|
||||
return httpExchange.getRequestHeaders().keySet().iterator();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Iterator<String> getRequestHeaders(String name) throws IOException {
|
||||
List<String> headers = httpExchange.getRequestHeaders().get(name);
|
||||
return headers != null ? headers.iterator() : Collections.<String>emptyList().iterator();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected InputStream getRequestInputStream() throws IOException {
|
||||
return httpExchange.getRequestBody();
|
||||
}
|
||||
|
||||
/*
|
||||
* Sending response
|
||||
*/
|
||||
|
||||
@Override
|
||||
protected void addResponseHeader(String name, String value) throws IOException {
|
||||
httpExchange.getResponseHeaders().add(name, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected OutputStream getResponseOutputStream() throws IOException {
|
||||
if (chunkedEncoding) {
|
||||
httpExchange.sendResponseHeaders(responseStatusCode, 0);
|
||||
return httpExchange.getResponseBody();
|
||||
}
|
||||
else {
|
||||
if (responseBuffer == null) {
|
||||
responseBuffer = new ByteArrayOutputStream();
|
||||
}
|
||||
return responseBuffer;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onSendAfterWrite(WebServiceMessage message) throws IOException {
|
||||
if (!chunkedEncoding) {
|
||||
byte[] buf = responseBuffer.toByteArray();
|
||||
httpExchange.sendResponseHeaders(responseStatusCode, buf.length);
|
||||
OutputStream responseBody = httpExchange.getResponseBody();
|
||||
FileCopyUtils.copy(buf, responseBody);
|
||||
}
|
||||
responseBuffer = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClose() throws IOException {
|
||||
if (responseStatusCode == HttpTransportConstants.STATUS_ACCEPTED ||
|
||||
responseStatusCode == HttpTransportConstants.STATUS_NOT_FOUND) {
|
||||
httpExchange.sendResponseHeaders(responseStatusCode, -1);
|
||||
}
|
||||
httpExchange.close();
|
||||
}
|
||||
|
||||
/*
|
||||
* Faults
|
||||
*/
|
||||
|
||||
public boolean hasFault() throws IOException {
|
||||
return responseStatusCode == HttpTransportConstants.STATUS_INTERNAL_SERVER_ERROR;
|
||||
}
|
||||
|
||||
public void setFault(boolean fault) throws IOException {
|
||||
if (fault) {
|
||||
responseStatusCode = HttpTransportConstants.STATUS_INTERNAL_SERVER_ERROR;
|
||||
}
|
||||
else {
|
||||
responseStatusCode = HttpTransportConstants.STATUS_OK;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright 2002-2009 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.ws.transport.http;
|
||||
|
||||
/**
|
||||
* Exception that is thrown when an error occurs in the HTTP transport.
|
||||
*
|
||||
* @author Arjen Poutsma
|
||||
* @since 1.5.8
|
||||
*/
|
||||
public class HttpsTransportException extends HttpTransportException {
|
||||
|
||||
public HttpsTransportException(String msg) {
|
||||
super(msg);
|
||||
}
|
||||
|
||||
public HttpsTransportException(String msg, Throwable cause) {
|
||||
super(msg, cause);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,179 @@
|
||||
/*
|
||||
* Copyright 2005-2012 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.ws.transport.http;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.security.KeyManagementException;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.security.NoSuchProviderException;
|
||||
import java.security.SecureRandom;
|
||||
import javax.net.ssl.HostnameVerifier;
|
||||
import javax.net.ssl.HttpsURLConnection;
|
||||
import javax.net.ssl.KeyManager;
|
||||
import javax.net.ssl.SSLContext;
|
||||
import javax.net.ssl.SSLSocketFactory;
|
||||
import javax.net.ssl.TrustManager;
|
||||
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* Extension of {@link HttpUrlConnectionMessageSender} that adds support for (self-signed) HTTPS certificates.
|
||||
*
|
||||
* @author Alex Marshall
|
||||
* @author Arjen Poutsma
|
||||
* @since 1.5.8
|
||||
*/
|
||||
public class HttpsUrlConnectionMessageSender extends HttpUrlConnectionMessageSender implements InitializingBean {
|
||||
|
||||
/** The default SSL protocol. */
|
||||
public static final String DEFAULT_SSL_PROTOCOL = "ssl";
|
||||
|
||||
private String sslProtocol = DEFAULT_SSL_PROTOCOL;
|
||||
|
||||
private String sslProvider;
|
||||
|
||||
private KeyManager[] keyManagers;
|
||||
|
||||
private TrustManager[] trustManagers;
|
||||
|
||||
private HostnameVerifier hostnameVerifier;
|
||||
|
||||
private SecureRandom rnd;
|
||||
|
||||
private SSLSocketFactory sslSocketFactory;
|
||||
|
||||
/**
|
||||
* Sets the SSL protocol to use. Default is {@code ssl}.
|
||||
*
|
||||
* @see SSLContext#getInstance(String, String)
|
||||
*/
|
||||
public void setSslProtocol(String sslProtocol) {
|
||||
Assert.hasLength(sslProtocol, "'sslProtocol' must not be empty");
|
||||
this.sslProtocol = sslProtocol;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the SSL provider to use. Default is empty, to use the default provider.
|
||||
*
|
||||
* @see SSLContext#getInstance(String, String)
|
||||
*/
|
||||
public void setSslProvider(String sslProvider) {
|
||||
this.sslProvider = sslProvider;
|
||||
}
|
||||
|
||||
/**
|
||||
* Specifies the key managers to use for this message sender.
|
||||
* <p/>
|
||||
* Setting either this property or {@link #setTrustManagers(TrustManager[]) trustManagers} is required.
|
||||
*
|
||||
* @see SSLContext#init(KeyManager[], TrustManager[], SecureRandom)
|
||||
*/
|
||||
public void setKeyManagers(KeyManager[] keyManagers) {
|
||||
this.keyManagers = keyManagers;
|
||||
}
|
||||
|
||||
/**
|
||||
* Specifies the trust managers to use for this message sender.
|
||||
* <p/>
|
||||
* Setting either this property or {@link #setKeyManagers(KeyManager[]) keyManagers} is required.
|
||||
*
|
||||
* @see SSLContext#init(KeyManager[], TrustManager[], SecureRandom)
|
||||
*/
|
||||
public void setTrustManagers(TrustManager[] trustManagers) {
|
||||
this.trustManagers = trustManagers;
|
||||
}
|
||||
|
||||
/**
|
||||
* Specifies the host name verifier to use for this message sender.
|
||||
*
|
||||
* @see HttpsURLConnection#setHostnameVerifier(HostnameVerifier)
|
||||
*/
|
||||
public void setHostnameVerifier(HostnameVerifier hostnameVerifier) {
|
||||
this.hostnameVerifier = hostnameVerifier;
|
||||
}
|
||||
|
||||
/**
|
||||
* Specifies the secure random to use for this message sender.
|
||||
*
|
||||
* @see SSLContext#init(KeyManager[], TrustManager[], SecureRandom)
|
||||
*/
|
||||
public void setSecureRandom(SecureRandom rnd) {
|
||||
this.rnd = rnd;
|
||||
}
|
||||
|
||||
/**
|
||||
* Specifies the SSLSocketFactory to use for this message sender.
|
||||
*
|
||||
* @see HttpsURLConnection#setSSLSocketFactory(SSLSocketFactory sf)
|
||||
*/
|
||||
public void setSslSocketFactory(SSLSocketFactory sslSocketFactory) {
|
||||
this.sslSocketFactory = sslSocketFactory;
|
||||
}
|
||||
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
Assert.isTrue(
|
||||
!(ObjectUtils.isEmpty(keyManagers) && ObjectUtils.isEmpty(trustManagers) && (sslSocketFactory == null)),
|
||||
"Setting either 'keyManagers', 'trustManagers' or 'sslSocketFactory' is required");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void prepareConnection(HttpURLConnection connection) throws IOException {
|
||||
super.prepareConnection(connection);
|
||||
if (connection instanceof HttpsURLConnection) {
|
||||
HttpsURLConnection httpsConnection = (HttpsURLConnection) connection;
|
||||
httpsConnection.setSSLSocketFactory(createSslSocketFactory());
|
||||
|
||||
if (hostnameVerifier != null) {
|
||||
httpsConnection.setHostnameVerifier(hostnameVerifier);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private SSLSocketFactory createSslSocketFactory() throws HttpsTransportException {
|
||||
if (this.sslSocketFactory != null) {
|
||||
return this.sslSocketFactory;
|
||||
}
|
||||
try {
|
||||
SSLContext sslContext =
|
||||
StringUtils.hasLength(sslProvider) ? SSLContext.getInstance(sslProtocol, sslProvider) :
|
||||
SSLContext.getInstance(sslProtocol);
|
||||
sslContext.init(keyManagers, trustManagers, rnd);
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Initialized SSL Context with key managers [" +
|
||||
StringUtils.arrayToCommaDelimitedString(keyManagers) + "] trust managers [" +
|
||||
StringUtils.arrayToCommaDelimitedString(trustManagers) + "] secure random [" + rnd +
|
||||
"]");
|
||||
}
|
||||
return sslContext.getSocketFactory();
|
||||
}
|
||||
catch (NoSuchAlgorithmException ex) {
|
||||
throw new HttpsTransportException("Could not create SSLContext: " + ex.getMessage(), ex);
|
||||
}
|
||||
catch (NoSuchProviderException ex) {
|
||||
throw new HttpsTransportException("Could not create SSLContext: " + ex.getMessage(), ex);
|
||||
}
|
||||
catch (KeyManagementException ex) {
|
||||
throw new HttpsTransportException("Could not initialize SSLContext: " + ex.getMessage(), ex);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
* Copyright 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.ws.transport.http;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import com.sun.net.httpserver.HttpExchange;
|
||||
import com.sun.net.httpserver.HttpHandler;
|
||||
|
||||
import org.springframework.ws.transport.support.SimpleWebServiceMessageReceiverObjectSupport;
|
||||
|
||||
/**
|
||||
* {@link HttpHandler} that can be used to handle incoming {@link HttpExchange} service requests. Designed for Sun's JRE
|
||||
* 1.6 HTTP server.
|
||||
* <p/>
|
||||
* Requires a {@link org.springframework.ws.WebServiceMessageFactory} which is used to convert the incoming {@link
|
||||
* HttpExchange} into a {@link org.springframework.ws.WebServiceMessage}, and passes that to the {@link
|
||||
* org.springframework.ws.transport.WebServiceMessageReceiver} {@link #setMessageReceiver(org.springframework.ws.transport.WebServiceMessageReceiver)
|
||||
* registered}.
|
||||
*
|
||||
* @author Arjen Poutsma
|
||||
* @see org.springframework.remoting.support.SimpleHttpServerFactoryBean
|
||||
* @since 1.5.0
|
||||
*/
|
||||
public class WebServiceMessageReceiverHttpHandler extends SimpleWebServiceMessageReceiverObjectSupport
|
||||
implements HttpHandler {
|
||||
|
||||
private boolean chunkedEncoding = false;
|
||||
|
||||
/** Enables chunked encoding on response bodies. Defaults to <code>false</code>. */
|
||||
public void setChunkedEncoding(boolean chunkedEncoding) {
|
||||
this.chunkedEncoding = chunkedEncoding;
|
||||
}
|
||||
|
||||
public void handle(HttpExchange httpExchange) throws IOException {
|
||||
if (HttpTransportConstants.METHOD_POST.equals(httpExchange.getRequestMethod())) {
|
||||
HttpExchangeConnection connection = new HttpExchangeConnection(httpExchange);
|
||||
connection.setChunkedEncoding(chunkedEncoding);
|
||||
try {
|
||||
handleConnection(connection);
|
||||
}
|
||||
catch (Exception ex) {
|
||||
logger.error(ex);
|
||||
}
|
||||
}
|
||||
else {
|
||||
httpExchange.sendResponseHeaders(HttpTransportConstants.STATUS_METHOD_NOT_ALLOWED, -1);
|
||||
httpExchange.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
/*
|
||||
* Copyright 2008 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.ws.transport.http;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import javax.xml.transform.TransformerException;
|
||||
import javax.xml.transform.stream.StreamResult;
|
||||
|
||||
import com.sun.net.httpserver.Headers;
|
||||
import com.sun.net.httpserver.HttpExchange;
|
||||
import com.sun.net.httpserver.HttpHandler;
|
||||
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.FileCopyUtils;
|
||||
import org.springframework.ws.wsdl.WsdlDefinition;
|
||||
import org.springframework.xml.transform.TransformerObjectSupport;
|
||||
|
||||
/**
|
||||
* @author Arjen Poutsma
|
||||
* @since 1.5.0
|
||||
*/
|
||||
public class WsdlDefinitionHttpHandler extends TransformerObjectSupport implements HttpHandler, InitializingBean {
|
||||
|
||||
private static final String CONTENT_TYPE = "text/xml";
|
||||
|
||||
private WsdlDefinition definition;
|
||||
|
||||
public WsdlDefinitionHttpHandler() {
|
||||
}
|
||||
|
||||
public WsdlDefinitionHttpHandler(WsdlDefinition definition) {
|
||||
this.definition = definition;
|
||||
}
|
||||
|
||||
public void setDefinition(WsdlDefinition definition) {
|
||||
this.definition = definition;
|
||||
}
|
||||
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
Assert.notNull(definition, "'definition' is required");
|
||||
}
|
||||
|
||||
public void handle(HttpExchange httpExchange) throws IOException {
|
||||
try {
|
||||
if (HttpTransportConstants.METHOD_GET.equals(httpExchange.getRequestMethod())) {
|
||||
Headers headers = httpExchange.getResponseHeaders();
|
||||
headers.set(HttpTransportConstants.HEADER_CONTENT_TYPE, CONTENT_TYPE);
|
||||
ByteArrayOutputStream os = new ByteArrayOutputStream();
|
||||
transform(definition.getSource(), new StreamResult(os));
|
||||
byte[] buf = os.toByteArray();
|
||||
httpExchange.sendResponseHeaders(HttpTransportConstants.STATUS_OK, buf.length);
|
||||
FileCopyUtils.copy(buf, httpExchange.getResponseBody());
|
||||
}
|
||||
else {
|
||||
httpExchange.sendResponseHeaders(HttpTransportConstants.STATUS_METHOD_NOT_ALLOWED, -1);
|
||||
}
|
||||
}
|
||||
catch (TransformerException ex) {
|
||||
logger.error(ex, ex);
|
||||
}
|
||||
finally {
|
||||
httpExchange.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
/*
|
||||
* Copyright 2005-2010 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.ws.transport.jms;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import javax.jms.BytesMessage;
|
||||
import javax.jms.JMSException;
|
||||
import javax.jms.MessageEOFException;
|
||||
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Input stream that wraps a {@link BytesMessage}.
|
||||
*
|
||||
* @author Arjen Poutsma
|
||||
* @since 1.5.0
|
||||
*/
|
||||
class BytesMessageInputStream extends InputStream {
|
||||
|
||||
private final BytesMessage message;
|
||||
|
||||
BytesMessageInputStream(BytesMessage message) {
|
||||
Assert.notNull(message, "'message' must not be null");
|
||||
this.message = message;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int read(byte b[]) throws IOException {
|
||||
try {
|
||||
return message.readBytes(b);
|
||||
}
|
||||
catch (JMSException ex) {
|
||||
throw new JmsTransportException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int read(byte b[], int off, int len) throws IOException {
|
||||
if (off == 0) {
|
||||
try {
|
||||
return message.readBytes(b, len);
|
||||
}
|
||||
catch (JMSException ex) {
|
||||
throw new JmsTransportException(ex);
|
||||
}
|
||||
}
|
||||
else {
|
||||
return super.read(b, off, len);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int read() throws IOException {
|
||||
try {
|
||||
return message.readByte();
|
||||
}
|
||||
catch (MessageEOFException ex) {
|
||||
return -1;
|
||||
}
|
||||
catch (JMSException ex) {
|
||||
throw new JmsTransportException(ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
/*
|
||||
* Copyright 2005-2010 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.ws.transport.jms;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import javax.jms.BytesMessage;
|
||||
import javax.jms.JMSException;
|
||||
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Output stream that wraps a {@link BytesMessage}.
|
||||
*
|
||||
* @author Arjen Poutsma
|
||||
* @since 1.5.0
|
||||
*/
|
||||
class BytesMessageOutputStream extends OutputStream {
|
||||
|
||||
private final BytesMessage message;
|
||||
|
||||
BytesMessageOutputStream(BytesMessage message) {
|
||||
Assert.notNull(message, "'message' must not be null");
|
||||
this.message = message;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(byte b[]) throws IOException {
|
||||
try {
|
||||
message.writeBytes(b);
|
||||
}
|
||||
catch (JMSException ex) {
|
||||
throw new JmsTransportException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(byte b[], int off, int len) throws IOException {
|
||||
try {
|
||||
message.writeBytes(b, off, len);
|
||||
}
|
||||
catch (JMSException ex) {
|
||||
throw new JmsTransportException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(int b) throws IOException {
|
||||
try {
|
||||
message.writeByte((byte) b);
|
||||
}
|
||||
catch (JMSException ex) {
|
||||
throw new JmsTransportException(ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,84 @@
|
||||
/*
|
||||
* Copyright 2005-2011 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.ws.transport.jms;
|
||||
|
||||
import javax.jms.BytesMessage;
|
||||
import javax.jms.Message;
|
||||
import javax.jms.Session;
|
||||
import javax.jms.TextMessage;
|
||||
|
||||
import org.springframework.jms.core.MessagePostProcessor;
|
||||
import org.springframework.ws.transport.WebServiceMessageReceiver;
|
||||
import org.springframework.ws.transport.support.SimpleWebServiceMessageReceiverObjectSupport;
|
||||
|
||||
/**
|
||||
* Convenience base class for JMS server-side transport objects. Contains a {@link WebServiceMessageReceiver}, and has
|
||||
* methods for handling incoming JMS {@link BytesMessage} and {@link TextMessage} requests. Also contains a
|
||||
* <code>textMessageEncoding</code> property, which determines the encoding used to read from and write to
|
||||
* <code>TextMessages</code>. This property defaults to <code>UTF-8</code>.
|
||||
* <p/>
|
||||
* Used by {@link WebServiceMessageListener} and {@link WebServiceMessageDrivenBean}.
|
||||
*
|
||||
* @author Arjen Poutsma
|
||||
* @since 1.5.0
|
||||
*/
|
||||
public class JmsMessageReceiver extends SimpleWebServiceMessageReceiverObjectSupport {
|
||||
|
||||
/** Default encoding used to read from and write to {@link TextMessage} messages. */
|
||||
public static final String DEFAULT_TEXT_MESSAGE_ENCODING = "UTF-8";
|
||||
|
||||
private String textMessageEncoding = DEFAULT_TEXT_MESSAGE_ENCODING;
|
||||
|
||||
private MessagePostProcessor postProcessor;
|
||||
|
||||
/** Sets the encoding used to read from and write to {@link TextMessage} messages. Defaults to <code>UTF-8</code>. */
|
||||
public void setTextMessageEncoding(String textMessageEncoding) {
|
||||
this.textMessageEncoding = textMessageEncoding;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the optional {@link MessagePostProcessor} to further modify outgoing messages after the XML contents has
|
||||
* been set.
|
||||
*/
|
||||
public void setPostProcessor(MessagePostProcessor postProcessor) {
|
||||
this.postProcessor = postProcessor;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles an incoming message. Uses the given session to create a response message.
|
||||
*
|
||||
* @param request the incoming message
|
||||
* @param session the JMS session used to create a response
|
||||
* @throws IllegalArgumentException when request is not a {@link BytesMessage}
|
||||
*/
|
||||
protected final void handleMessage(Message request, Session session) throws Exception {
|
||||
JmsReceiverConnection connection;
|
||||
if (request instanceof BytesMessage) {
|
||||
connection = new JmsReceiverConnection((BytesMessage) request, session);
|
||||
}
|
||||
else if (request instanceof TextMessage) {
|
||||
connection = new JmsReceiverConnection((TextMessage) request, textMessageEncoding, session);
|
||||
}
|
||||
else {
|
||||
throw new IllegalArgumentException("Wrong message type: [" + request.getClass() +
|
||||
"]. Only BytesMessages or TextMessages can be handled.");
|
||||
}
|
||||
connection.setPostProcessor(postProcessor);
|
||||
|
||||
handleConnection(connection);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,210 @@
|
||||
/*
|
||||
* Copyright 2005-2012 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.ws.transport.jms;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.URI;
|
||||
import javax.jms.BytesMessage;
|
||||
import javax.jms.Connection;
|
||||
import javax.jms.ConnectionFactory;
|
||||
import javax.jms.Destination;
|
||||
import javax.jms.JMSException;
|
||||
import javax.jms.Message;
|
||||
import javax.jms.MessageConsumer;
|
||||
import javax.jms.MessageProducer;
|
||||
import javax.jms.Queue;
|
||||
import javax.jms.Session;
|
||||
import javax.jms.TextMessage;
|
||||
import javax.jms.Topic;
|
||||
|
||||
import org.springframework.jms.connection.ConnectionFactoryUtils;
|
||||
import org.springframework.jms.core.MessagePostProcessor;
|
||||
import org.springframework.jms.support.JmsUtils;
|
||||
import org.springframework.jms.support.destination.JmsDestinationAccessor;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.ws.transport.WebServiceConnection;
|
||||
import org.springframework.ws.transport.WebServiceMessageSender;
|
||||
import org.springframework.ws.transport.jms.support.JmsTransportUtils;
|
||||
|
||||
/**
|
||||
* {@link WebServiceMessageSender} implementation that uses JMS {@link Message}s. Requires a JMS {@link
|
||||
* ConnectionFactory} to operate.
|
||||
* <p/>
|
||||
* This message sender supports URI's of the following format: <blockquote> <tt><b>jms:</b></tt><i>destination</i>[<tt><b>?</b></tt><i>param-name</i><tt><b>=</b></tt><i>param-value</i>][<tt><b>&</b></tt><i>param-name</i><tt><b>=</b></tt><i>param-value</i>]*
|
||||
* </blockquote> where the characters <tt><b>:</b></tt>, <tt><b>?</b></tt>, and <tt><b>&</b></tt> stand for
|
||||
* themselves. The <i>destination</i> represents the name of the {@link Queue} or {@link Topic} that will be resolved by
|
||||
* the {@link #getDestinationResolver() destination resolver}. Valid <i>param-name</i> include:
|
||||
* <p/>
|
||||
* <blockquote>
|
||||
* <table>
|
||||
* <tr><th><i>param-name</i></th><th><i>Description</i></th></tr>
|
||||
* <tr>
|
||||
* <td><tt>deliveryMode</tt></td>
|
||||
* <td>Indicates whether the request message is persistent or not. This may be <tt>PERSISTENT</tt> or
|
||||
* <tt>NON_PERSISTENT</tt>. See {@link MessageProducer#setDeliveryMode(int)}</td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <td><tt>messageType</tt></td>
|
||||
* <td>The message type. This may be <tt>BINARY_MESSAGE</tt> (the default) or <tt>TEXT_MESSAGE</tt></td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <td><tt>priority</tt></td>
|
||||
* <td>The JMS priority (0-9) associated with the request message. See
|
||||
* {@link MessageProducer#setPriority(int)}</td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <td><tt>replyToName</tt></td>
|
||||
* <td>The name of the destination to which the response message must be sent, that will be resolved by
|
||||
* the {@link #getDestinationResolver() destination resolver}.</td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <td><tt>timeToLive</tt></td>
|
||||
* <td>The lifetime, in milliseconds, of the request message. See
|
||||
* {@link MessageProducer#setTimeToLive(long)}</td>
|
||||
* </tr>
|
||||
* </table>
|
||||
* </blockquote>
|
||||
* <p/>
|
||||
* If the <tt>replyToName</tt> is not set, a {@link Session#createTemporaryQueue() temporary queue} is used.
|
||||
* <p/>
|
||||
* This class uses {@link BytesMessage} messages by default, but can be configured to send {@link TextMessage} messages
|
||||
* instead. <b>Note</b> that <code>BytesMessages</code> are preferred, since <code>TextMessages</code> do not support
|
||||
* attachments and character encodings reliably.
|
||||
* <p/>
|
||||
* Some examples of JMS URIs are:
|
||||
* <p/>
|
||||
* <blockquote> <tt>jms:SomeQueue</tt><br> <tt>jms:SomeTopic?priority=3&deliveryMode=NON_PERSISTENT</tt><br>
|
||||
* <tt>jms:RequestQueue?replyToName=ResponseQueueName</tt><br> <tt>jms:Queue?messageType=TEXT_MESSAGE</blockquote>
|
||||
*
|
||||
* @author Arjen Poutsma
|
||||
* @see <a href="http://tools.ietf.org/id/draft-merrick-jms-iri-00.txt">IRI Scheme for Java(tm) Message Service 1.0</a>
|
||||
* @since 1.5.0
|
||||
*/
|
||||
public class JmsMessageSender extends JmsDestinationAccessor implements WebServiceMessageSender {
|
||||
|
||||
/** Default timeout for receive operations: -1 indicates a blocking receive without timeout. */
|
||||
public static final long DEFAULT_RECEIVE_TIMEOUT = -1;
|
||||
|
||||
/** Default encoding used to read fromn and write to {@link TextMessage} messages. */
|
||||
public static final String DEFAULT_TEXT_MESSAGE_ENCODING = "UTF-8";
|
||||
|
||||
private long receiveTimeout = DEFAULT_RECEIVE_TIMEOUT;
|
||||
|
||||
private String textMessageEncoding = DEFAULT_TEXT_MESSAGE_ENCODING;
|
||||
|
||||
private MessagePostProcessor postProcessor;
|
||||
|
||||
/**
|
||||
* Create a new <code>JmsMessageSender</code>
|
||||
* <p/>
|
||||
* <b>Note</b>: The ConnectionFactory has to be set before using the instance. This constructor can be used to
|
||||
* prepare a JmsTemplate via a BeanFactory, typically setting the ConnectionFactory via {@link
|
||||
* #setConnectionFactory(ConnectionFactory)}.
|
||||
*
|
||||
* @see #setConnectionFactory(ConnectionFactory)
|
||||
*/
|
||||
public JmsMessageSender() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new <code>JmsMessageSender</code>, given a ConnectionFactory.
|
||||
*
|
||||
* @param connectionFactory the ConnectionFactory to obtain Connections from
|
||||
*/
|
||||
public JmsMessageSender(ConnectionFactory connectionFactory) {
|
||||
setConnectionFactory(connectionFactory);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the timeout to use for receive calls. The default is -1, which means no timeout.
|
||||
*
|
||||
* @see MessageConsumer#receive(long)
|
||||
*/
|
||||
public void setReceiveTimeout(long receiveTimeout) {
|
||||
this.receiveTimeout = receiveTimeout;
|
||||
}
|
||||
|
||||
/** Sets the encoding used to read from {@link TextMessage} messages. Defaults to <code>UTF-8</code>. */
|
||||
public void setTextMessageEncoding(String textMessageEncoding) {
|
||||
this.textMessageEncoding = textMessageEncoding;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the optional {@link MessagePostProcessor} to further modify outgoing messages after the XML contents has
|
||||
* been set.
|
||||
*/
|
||||
public void setPostProcessor(MessagePostProcessor postProcessor) {
|
||||
this.postProcessor = postProcessor;
|
||||
}
|
||||
|
||||
public WebServiceConnection createConnection(URI uri) throws IOException {
|
||||
Connection jmsConnection = null;
|
||||
Session jmsSession = null;
|
||||
try {
|
||||
jmsConnection = createConnection();
|
||||
jmsSession = createSession(jmsConnection);
|
||||
Destination requestDestination = resolveRequestDestination(jmsSession, uri);
|
||||
Message requestMessage = createRequestMessage(jmsSession, uri);
|
||||
JmsSenderConnection wsConnection =
|
||||
new JmsSenderConnection(getConnectionFactory(), jmsConnection, jmsSession, requestDestination,
|
||||
requestMessage);
|
||||
wsConnection.setDeliveryMode(JmsTransportUtils.getDeliveryMode(uri));
|
||||
wsConnection.setPriority(JmsTransportUtils.getPriority(uri));
|
||||
wsConnection.setReceiveTimeout(receiveTimeout);
|
||||
wsConnection.setResponseDestination(resolveResponseDestination(jmsSession, uri));
|
||||
wsConnection.setTimeToLive(JmsTransportUtils.getTimeToLive(uri));
|
||||
wsConnection.setTextMessageEncoding(textMessageEncoding);
|
||||
wsConnection.setSessionTransacted(isSessionTransacted());
|
||||
wsConnection.setPostProcessor(postProcessor);
|
||||
return wsConnection;
|
||||
}
|
||||
catch (JMSException ex) {
|
||||
JmsUtils.closeSession(jmsSession);
|
||||
ConnectionFactoryUtils.releaseConnection(jmsConnection, getConnectionFactory(), true);
|
||||
throw new JmsTransportException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean supports(URI uri) {
|
||||
return uri.getScheme().equals(JmsTransportConstants.JMS_URI_SCHEME);
|
||||
}
|
||||
|
||||
private Destination resolveRequestDestination(Session session, URI uri) throws JMSException {
|
||||
return resolveDestinationName(session, JmsTransportUtils.getDestinationName(uri));
|
||||
}
|
||||
|
||||
private Destination resolveResponseDestination(Session session, URI uri) throws JMSException {
|
||||
String destinationName = JmsTransportUtils.getReplyToName(uri);
|
||||
return StringUtils.hasLength(destinationName) ? resolveDestinationName(session, destinationName) : null;
|
||||
}
|
||||
|
||||
private Message createRequestMessage(Session session, URI uri) throws JMSException {
|
||||
int messageType = JmsTransportUtils.getMessageType(uri);
|
||||
if (messageType == JmsTransportConstants.BYTES_MESSAGE_TYPE) {
|
||||
return session.createBytesMessage();
|
||||
}
|
||||
else if (messageType == JmsTransportConstants.TEXT_MESSAGE_TYPE) {
|
||||
return session.createTextMessage();
|
||||
}
|
||||
else {
|
||||
throw new IllegalArgumentException("Invalid message type [" + messageType + "].");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,244 @@
|
||||
/*
|
||||
* Copyright 2005-2010 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.ws.transport.jms;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.util.Iterator;
|
||||
import javax.jms.BytesMessage;
|
||||
import javax.jms.JMSException;
|
||||
import javax.jms.Message;
|
||||
import javax.jms.MessageProducer;
|
||||
import javax.jms.Session;
|
||||
import javax.jms.TextMessage;
|
||||
|
||||
import org.springframework.jms.core.MessagePostProcessor;
|
||||
import org.springframework.jms.support.JmsUtils;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.ws.WebServiceMessage;
|
||||
import org.springframework.ws.transport.AbstractReceiverConnection;
|
||||
import org.springframework.ws.transport.WebServiceConnection;
|
||||
import org.springframework.ws.transport.jms.support.JmsTransportUtils;
|
||||
|
||||
/**
|
||||
* Implementation of {@link WebServiceConnection} that is used for server-side JMS access. Exposes a {@link
|
||||
* BytesMessage} or {@link TextMessage} request and response message.
|
||||
* <p/>
|
||||
* The response message type is equal to the request message type, i.e. if a <code>BytesMessage</code> is received as
|
||||
* request, a <code>BytesMessage</code> is created as response, and if a <code>TextMessage</code> is received, a
|
||||
* <code>TextMessage</code> response is created.
|
||||
*
|
||||
* @author Arjen Poutsma
|
||||
* @since 1.5.0
|
||||
*/
|
||||
public class JmsReceiverConnection extends AbstractReceiverConnection {
|
||||
|
||||
private final Message requestMessage;
|
||||
|
||||
private final Session session;
|
||||
|
||||
private Message responseMessage;
|
||||
|
||||
private String textMessageEncoding;
|
||||
|
||||
private MessagePostProcessor postProcessor;
|
||||
|
||||
private JmsReceiverConnection(Message requestMessage, Session session) {
|
||||
Assert.notNull(requestMessage, "requestMessage must not be null");
|
||||
Assert.notNull(session, "session must not be null");
|
||||
this.requestMessage = requestMessage;
|
||||
this.session = session;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new JMS connection with the given {@link BytesMessage}.
|
||||
*
|
||||
* @param requestMessage the JMS request message
|
||||
* @param session the JMS session
|
||||
*/
|
||||
protected JmsReceiverConnection(BytesMessage requestMessage, Session session) {
|
||||
this((Message) requestMessage, session);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new JMS connection with the given {@link TextMessage}.
|
||||
*
|
||||
* @param requestMessage the JMS request message
|
||||
* @param session the JMS session
|
||||
*/
|
||||
protected JmsReceiverConnection(TextMessage requestMessage, String encoding, Session session) {
|
||||
this(requestMessage, session);
|
||||
this.textMessageEncoding = encoding;
|
||||
}
|
||||
|
||||
void setPostProcessor(MessagePostProcessor postProcessor) {
|
||||
this.postProcessor = postProcessor;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/** Returns the request message for this connection. Returns either a {@link BytesMessage} or a {@link TextMessage}. */
|
||||
public Message getRequestMessage() {
|
||||
return requestMessage;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the response message, if any, for this connection. Returns either a {@link BytesMessage} or a {@link
|
||||
* TextMessage}.
|
||||
*/
|
||||
public Message getResponseMessage() {
|
||||
return responseMessage;
|
||||
}
|
||||
|
||||
/*
|
||||
* URI
|
||||
*/
|
||||
|
||||
public URI getUri() throws URISyntaxException {
|
||||
try {
|
||||
return JmsTransportUtils.toUri(requestMessage.getJMSDestination());
|
||||
}
|
||||
catch (JMSException ex) {
|
||||
throw new URISyntaxException("", ex.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Errors
|
||||
*/
|
||||
|
||||
public String getErrorMessage() throws IOException {
|
||||
return null;
|
||||
}
|
||||
|
||||
public boolean hasError() throws IOException {
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* Receiving
|
||||
*/
|
||||
|
||||
@Override
|
||||
protected Iterator<String> getRequestHeaderNames() throws IOException {
|
||||
try {
|
||||
return JmsTransportUtils.getHeaderNames(requestMessage);
|
||||
}
|
||||
catch (JMSException ex) {
|
||||
throw new JmsTransportException("Could not get property names", ex);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Iterator<String> getRequestHeaders(String name) throws IOException {
|
||||
try {
|
||||
return JmsTransportUtils.getHeaders(requestMessage, name);
|
||||
}
|
||||
catch (JMSException ex) {
|
||||
throw new JmsTransportException("Could not get property value", ex);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected InputStream getRequestInputStream() throws IOException {
|
||||
if (requestMessage instanceof BytesMessage) {
|
||||
return new BytesMessageInputStream((BytesMessage) requestMessage);
|
||||
}
|
||||
else if (requestMessage instanceof TextMessage) {
|
||||
return new TextMessageInputStream((TextMessage) requestMessage, textMessageEncoding);
|
||||
}
|
||||
else {
|
||||
throw new IllegalStateException("Unknown request message type [" + requestMessage + "]");
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Sending
|
||||
*/
|
||||
|
||||
@Override
|
||||
protected void onSendBeforeWrite(WebServiceMessage message) throws IOException {
|
||||
try {
|
||||
if (requestMessage instanceof BytesMessage) {
|
||||
responseMessage = session.createBytesMessage();
|
||||
}
|
||||
else if (requestMessage instanceof TextMessage) {
|
||||
responseMessage = session.createTextMessage();
|
||||
}
|
||||
else {
|
||||
throw new IllegalStateException("Unknown request message type [" + requestMessage + "]");
|
||||
}
|
||||
String correlation = requestMessage.getJMSCorrelationID();
|
||||
if (correlation == null) {
|
||||
correlation = requestMessage.getJMSMessageID();
|
||||
}
|
||||
responseMessage.setJMSCorrelationID(correlation);
|
||||
}
|
||||
catch (JMSException ex) {
|
||||
throw new JmsTransportException("Could not create response message", ex);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void addResponseHeader(String name, String value) throws IOException {
|
||||
try {
|
||||
JmsTransportUtils.addHeader(responseMessage, name, value);
|
||||
}
|
||||
catch (JMSException ex) {
|
||||
throw new JmsTransportException("Could not set property", ex);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected OutputStream getResponseOutputStream() throws IOException {
|
||||
if (responseMessage instanceof BytesMessage) {
|
||||
return new BytesMessageOutputStream((BytesMessage) responseMessage);
|
||||
}
|
||||
else if (responseMessage instanceof TextMessage) {
|
||||
return new TextMessageOutputStream((TextMessage) responseMessage, textMessageEncoding);
|
||||
}
|
||||
else {
|
||||
throw new IllegalStateException("Unknown response message type [" + responseMessage + "]");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onSendAfterWrite(WebServiceMessage message) throws IOException {
|
||||
MessageProducer messageProducer = null;
|
||||
try {
|
||||
if (requestMessage.getJMSReplyTo() != null) {
|
||||
messageProducer = session.createProducer(requestMessage.getJMSReplyTo());
|
||||
messageProducer.setDeliveryMode(requestMessage.getJMSDeliveryMode());
|
||||
messageProducer.setPriority(requestMessage.getJMSPriority());
|
||||
if (postProcessor != null) {
|
||||
responseMessage = postProcessor.postProcessMessage(responseMessage);
|
||||
}
|
||||
messageProducer.send(responseMessage);
|
||||
}
|
||||
}
|
||||
catch (JMSException ex) {
|
||||
throw new JmsTransportException(ex);
|
||||
}
|
||||
finally {
|
||||
JmsUtils.closeMessageProducer(messageProducer);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,327 @@
|
||||
/*
|
||||
* Copyright 2005-2012 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.ws.transport.jms;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.util.Iterator;
|
||||
import javax.jms.BytesMessage;
|
||||
import javax.jms.Connection;
|
||||
import javax.jms.ConnectionFactory;
|
||||
import javax.jms.Destination;
|
||||
import javax.jms.JMSException;
|
||||
import javax.jms.Message;
|
||||
import javax.jms.MessageConsumer;
|
||||
import javax.jms.MessageProducer;
|
||||
import javax.jms.Session;
|
||||
import javax.jms.TemporaryQueue;
|
||||
import javax.jms.TextMessage;
|
||||
|
||||
import org.springframework.jms.connection.ConnectionFactoryUtils;
|
||||
import org.springframework.jms.core.MessagePostProcessor;
|
||||
import org.springframework.jms.support.JmsUtils;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.ws.WebServiceMessage;
|
||||
import org.springframework.ws.transport.AbstractSenderConnection;
|
||||
import org.springframework.ws.transport.WebServiceConnection;
|
||||
import org.springframework.ws.transport.jms.support.JmsTransportUtils;
|
||||
|
||||
/**
|
||||
* Implementation of {@link WebServiceConnection} that is used for client-side JMS access. Exposes a {@link
|
||||
* BytesMessage} request and response message.
|
||||
*
|
||||
* @author Arjen Poutsma
|
||||
* @since 1.5.0
|
||||
*/
|
||||
public class JmsSenderConnection extends AbstractSenderConnection {
|
||||
|
||||
private final ConnectionFactory connectionFactory;
|
||||
|
||||
private final Connection connection;
|
||||
|
||||
private final Session session;
|
||||
|
||||
private final Destination requestDestination;
|
||||
|
||||
private Message requestMessage;
|
||||
|
||||
private Destination responseDestination;
|
||||
|
||||
private Message responseMessage;
|
||||
|
||||
private long receiveTimeout;
|
||||
|
||||
private int deliveryMode;
|
||||
|
||||
private long timeToLive;
|
||||
|
||||
private int priority;
|
||||
|
||||
private String textMessageEncoding;
|
||||
|
||||
private MessagePostProcessor postProcessor;
|
||||
|
||||
private boolean sessionTransacted = false;
|
||||
|
||||
private boolean temporaryResponseQueueCreated = false;
|
||||
|
||||
/** Constructs a new JMS connection with the given parameters. */
|
||||
protected JmsSenderConnection(ConnectionFactory connectionFactory,
|
||||
Connection connection,
|
||||
Session session,
|
||||
Destination requestDestination,
|
||||
Message requestMessage) throws JMSException {
|
||||
Assert.notNull(connectionFactory, "'connectionFactory' must not be null");
|
||||
Assert.notNull(connection, "'connection' must not be null");
|
||||
Assert.notNull(session, "'session' must not be null");
|
||||
Assert.notNull(requestDestination, "'requestDestination' must not be null");
|
||||
Assert.notNull(requestMessage, "'requestMessage' must not be null");
|
||||
this.connectionFactory = connectionFactory;
|
||||
this.connection = connection;
|
||||
this.session = session;
|
||||
this.requestDestination = requestDestination;
|
||||
this.requestMessage = requestMessage;
|
||||
}
|
||||
|
||||
/** Returns the request message for this connection. Returns either a {@link BytesMessage} or a {@link TextMessage}. */
|
||||
public Message getRequestMessage() {
|
||||
return requestMessage;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the response message, if any, for this connection. Returns either a {@link BytesMessage} or a {@link
|
||||
* TextMessage}.
|
||||
*/
|
||||
public Message getResponseMessage() {
|
||||
return responseMessage;
|
||||
}
|
||||
|
||||
/*
|
||||
* Package-friendly setters
|
||||
*/
|
||||
|
||||
void setResponseDestination(Destination responseDestination) {
|
||||
this.responseDestination = responseDestination;
|
||||
}
|
||||
|
||||
void setTimeToLive(long timeToLive) {
|
||||
this.timeToLive = timeToLive;
|
||||
}
|
||||
|
||||
void setDeliveryMode(int deliveryMode) {
|
||||
this.deliveryMode = deliveryMode;
|
||||
}
|
||||
|
||||
void setPriority(int priority) {
|
||||
this.priority = priority;
|
||||
}
|
||||
|
||||
void setReceiveTimeout(long receiveTimeout) {
|
||||
this.receiveTimeout = receiveTimeout;
|
||||
}
|
||||
|
||||
void setTextMessageEncoding(String textMessageEncoding) {
|
||||
this.textMessageEncoding = textMessageEncoding;
|
||||
}
|
||||
|
||||
void setPostProcessor(MessagePostProcessor postProcessor) {
|
||||
this.postProcessor = postProcessor;
|
||||
}
|
||||
|
||||
void setSessionTransacted(boolean sessionTransacted) {
|
||||
this.sessionTransacted = sessionTransacted;
|
||||
}
|
||||
|
||||
/*
|
||||
* URI
|
||||
*/
|
||||
|
||||
public URI getUri() throws URISyntaxException {
|
||||
try {
|
||||
return JmsTransportUtils.toUri(requestDestination);
|
||||
}
|
||||
catch (JMSException ex) {
|
||||
throw new URISyntaxException("", ex.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Errors
|
||||
*/
|
||||
|
||||
public boolean hasError() throws IOException {
|
||||
return false;
|
||||
}
|
||||
|
||||
public String getErrorMessage() throws IOException {
|
||||
return null;
|
||||
}
|
||||
|
||||
/*
|
||||
* Sending
|
||||
*/
|
||||
|
||||
@Override
|
||||
protected void addRequestHeader(String name, String value) throws IOException {
|
||||
try {
|
||||
JmsTransportUtils.addHeader(requestMessage, name, value);
|
||||
}
|
||||
catch (JMSException ex) {
|
||||
throw new JmsTransportException("Could not set property", ex);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected OutputStream getRequestOutputStream() throws IOException {
|
||||
if (requestMessage instanceof BytesMessage) {
|
||||
return new BytesMessageOutputStream((BytesMessage) requestMessage);
|
||||
}
|
||||
else if (requestMessage instanceof TextMessage) {
|
||||
return new TextMessageOutputStream((TextMessage) requestMessage, textMessageEncoding);
|
||||
}
|
||||
else {
|
||||
throw new IllegalStateException("Unknown request message type [" + requestMessage + "]");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onSendAfterWrite(WebServiceMessage message) throws IOException {
|
||||
MessageProducer messageProducer = null;
|
||||
try {
|
||||
messageProducer = session.createProducer(requestDestination);
|
||||
messageProducer.setDeliveryMode(deliveryMode);
|
||||
messageProducer.setTimeToLive(timeToLive);
|
||||
messageProducer.setPriority(priority);
|
||||
if (responseDestination == null) {
|
||||
responseDestination = session.createTemporaryQueue();
|
||||
temporaryResponseQueueCreated = true;
|
||||
}
|
||||
requestMessage.setJMSReplyTo(responseDestination);
|
||||
if (postProcessor != null) {
|
||||
requestMessage = postProcessor.postProcessMessage(requestMessage);
|
||||
}
|
||||
connection.start();
|
||||
messageProducer.send(requestMessage);
|
||||
if (session.getTransacted() && isSessionLocallyTransacted(session)) {
|
||||
JmsUtils.commitIfNecessary(session);
|
||||
}
|
||||
}
|
||||
catch (JMSException ex) {
|
||||
throw new JmsTransportException(ex);
|
||||
}
|
||||
finally {
|
||||
JmsUtils.closeMessageProducer(messageProducer);
|
||||
}
|
||||
}
|
||||
|
||||
/** @see org.springframework.jms.core.JmsTemplate#isSessionLocallyTransacted(Session) */
|
||||
private boolean isSessionLocallyTransacted(Session session) {
|
||||
return sessionTransacted && !ConnectionFactoryUtils.isSessionTransactional(session, connectionFactory);
|
||||
}
|
||||
|
||||
/*
|
||||
* Receiving
|
||||
*/
|
||||
|
||||
@Override
|
||||
protected void onReceiveBeforeRead() throws IOException {
|
||||
MessageConsumer messageConsumer = null;
|
||||
try {
|
||||
if (temporaryResponseQueueCreated) {
|
||||
messageConsumer = session.createConsumer(responseDestination);
|
||||
}
|
||||
else {
|
||||
String messageId = requestMessage.getJMSMessageID().replaceAll("'", "''");
|
||||
String messageSelector = "JMSCorrelationID = '" + messageId + "'";
|
||||
messageConsumer = session.createConsumer(responseDestination, messageSelector);
|
||||
}
|
||||
Message message = receiveTimeout >= 0 ? messageConsumer.receive(receiveTimeout) : messageConsumer.receive();
|
||||
if (message instanceof BytesMessage || message instanceof TextMessage) {
|
||||
responseMessage = message;
|
||||
}
|
||||
else if (message != null) {
|
||||
throw new IllegalArgumentException(
|
||||
"Wrong message type: [" + message.getClass() + "]. " +
|
||||
"Only BytesMessages or TextMessages can be handled.");
|
||||
}
|
||||
}
|
||||
catch (JMSException ex) {
|
||||
throw new JmsTransportException(ex);
|
||||
}
|
||||
finally {
|
||||
JmsUtils.closeMessageConsumer(messageConsumer);
|
||||
if (temporaryResponseQueueCreated) {
|
||||
try {
|
||||
((TemporaryQueue) responseDestination).delete();
|
||||
}
|
||||
catch (JMSException ex) {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean hasResponse() throws IOException {
|
||||
return responseMessage != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Iterator<String> getResponseHeaderNames() throws IOException {
|
||||
try {
|
||||
return JmsTransportUtils.getHeaderNames(responseMessage);
|
||||
}
|
||||
catch (JMSException ex) {
|
||||
throw new JmsTransportException("Could not get property names", ex);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Iterator<String> getResponseHeaders(String name) throws IOException {
|
||||
try {
|
||||
return JmsTransportUtils.getHeaders(responseMessage, name);
|
||||
}
|
||||
catch (JMSException ex) {
|
||||
throw new JmsTransportException("Could not get property value", ex);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected InputStream getResponseInputStream() throws IOException {
|
||||
if (responseMessage instanceof BytesMessage) {
|
||||
return new BytesMessageInputStream((BytesMessage) responseMessage);
|
||||
}
|
||||
else if (responseMessage instanceof TextMessage) {
|
||||
return new TextMessageInputStream((TextMessage) responseMessage, textMessageEncoding);
|
||||
}
|
||||
else {
|
||||
throw new IllegalStateException("Unknown response message type [" + responseMessage + "]");
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onClose() throws IOException {
|
||||
JmsUtils.closeSession(session);
|
||||
ConnectionFactoryUtils.releaseConnection(connection, connectionFactory, true);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* Copyright 2005-2012 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.ws.transport.jms;
|
||||
|
||||
import javax.jms.BytesMessage;
|
||||
import javax.jms.TextMessage;
|
||||
|
||||
import org.springframework.ws.transport.TransportConstants;
|
||||
|
||||
/**
|
||||
* Declares JMS-specific transport constants.
|
||||
*
|
||||
* @author Arjen Poutsma
|
||||
* @since 1.5.0
|
||||
*/
|
||||
public interface JmsTransportConstants extends TransportConstants {
|
||||
|
||||
/** The "jms" URI scheme" */
|
||||
String JMS_URI_SCHEME = "jms";
|
||||
|
||||
/** Indicates a {@link BytesMessage} type. */
|
||||
int BYTES_MESSAGE_TYPE = 1;
|
||||
|
||||
/** Indicates a {@link TextMessage} type. */
|
||||
int TEXT_MESSAGE_TYPE = 2;
|
||||
|
||||
/** Prefix for JMS properties that map to transport headers. */
|
||||
String PROPERTY_PREFIX = "SOAPJMS_";
|
||||
|
||||
/** JMS property used for storing {@link #HEADER_ACCEPT_ENCODING}. */
|
||||
String PROPERTY_ACCEPT_ENCODING = PROPERTY_PREFIX + "acceptEncoding";
|
||||
|
||||
/** JMS property used for storing {@link #HEADER_SOAP_ACTION}. */
|
||||
String PROPERTY_SOAP_ACTION = PROPERTY_PREFIX + "soapAction";
|
||||
|
||||
/** JMS property used for storing {@link #HEADER_CONTENT_LENGTH}. */
|
||||
String PROPERTY_CONTENT_LENGTH = PROPERTY_PREFIX + "contentLength";
|
||||
|
||||
/** JMS property used for storing {@link #HEADER_CONTENT_TYPE}. */
|
||||
String PROPERTY_CONTENT_TYPE = PROPERTY_PREFIX + "contentType";
|
||||
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
* Copyright 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.ws.transport.jms;
|
||||
|
||||
import javax.jms.JMSException;
|
||||
|
||||
import org.springframework.ws.transport.TransportException;
|
||||
|
||||
/**
|
||||
* Exception that is thrown when an error occurs in the JMS transport.
|
||||
*
|
||||
* @author Arjen Poutsma
|
||||
* @since 1.5.0
|
||||
*/
|
||||
public class JmsTransportException extends TransportException {
|
||||
|
||||
private final JMSException jmsException;
|
||||
|
||||
public JmsTransportException(String msg, JMSException ex) {
|
||||
super(msg + ": " + ex.getMessage());
|
||||
initCause(ex);
|
||||
jmsException = ex;
|
||||
}
|
||||
|
||||
public JmsTransportException(JMSException ex) {
|
||||
super(ex.getMessage());
|
||||
initCause(ex);
|
||||
jmsException = ex;
|
||||
}
|
||||
|
||||
public JMSException getJmsException() {
|
||||
return jmsException;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* Copyright 2008 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.ws.transport.jms;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.FilterInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import javax.jms.JMSException;
|
||||
import javax.jms.TextMessage;
|
||||
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Input stream that wraps a {@link javax.jms.TextMessage}.
|
||||
*
|
||||
* @author Arjen Poutsma
|
||||
* @since 1.5.3
|
||||
*/
|
||||
class TextMessageInputStream extends FilterInputStream {
|
||||
|
||||
TextMessageInputStream(TextMessage message, String encoding) throws IOException {
|
||||
super(createInputStream(message, encoding));
|
||||
}
|
||||
|
||||
private static InputStream createInputStream(TextMessage message, String encoding) throws IOException {
|
||||
Assert.notNull(message, "'message' must not be null");
|
||||
Assert.notNull(encoding, "'encoding' must not be null");
|
||||
try {
|
||||
String text = message.getText();
|
||||
byte[] contents = text != null ? text.getBytes(encoding) : new byte[0];
|
||||
return new ByteArrayInputStream(contents);
|
||||
}
|
||||
catch (JMSException ex) {
|
||||
throw new JmsTransportException(ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
* Copyright 2005-2010 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.ws.transport.jms;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.FilterOutputStream;
|
||||
import java.io.IOException;
|
||||
import javax.jms.JMSException;
|
||||
import javax.jms.TextMessage;
|
||||
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Writer that wraps a {@link javax.jms.TextMessage}.
|
||||
*
|
||||
* @author Arjen Poutsma
|
||||
* @since 1.5.3
|
||||
*/
|
||||
class TextMessageOutputStream extends FilterOutputStream {
|
||||
|
||||
private final TextMessage message;
|
||||
|
||||
private final String encoding;
|
||||
|
||||
TextMessageOutputStream(TextMessage message, String encoding) {
|
||||
super(new ByteArrayOutputStream());
|
||||
Assert.notNull(message, "'message' must not be null");
|
||||
Assert.notNull(encoding, "'encoding' must not be null");
|
||||
this.message = message;
|
||||
this.encoding = encoding;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void flush() throws IOException {
|
||||
super.flush();
|
||||
try {
|
||||
ByteArrayOutputStream baos = (ByteArrayOutputStream) out;
|
||||
String text = new String(baos.toByteArray(), encoding);
|
||||
message.setText(text);
|
||||
}
|
||||
catch (JMSException ex) {
|
||||
throw new JmsTransportException(ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,170 @@
|
||||
/*
|
||||
* Copyright 2005-2010 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.ws.transport.jms;
|
||||
|
||||
import javax.ejb.EJBException;
|
||||
import javax.ejb.MessageDrivenBean;
|
||||
import javax.jms.Connection;
|
||||
import javax.jms.ConnectionFactory;
|
||||
import javax.jms.JMSException;
|
||||
import javax.jms.Message;
|
||||
import javax.jms.Session;
|
||||
import javax.naming.NamingException;
|
||||
|
||||
import org.springframework.ejb.support.AbstractJmsMessageDrivenBean;
|
||||
import org.springframework.jms.connection.ConnectionFactoryUtils;
|
||||
import org.springframework.jms.core.MessagePostProcessor;
|
||||
import org.springframework.jms.support.JmsUtils;
|
||||
import org.springframework.jndi.JndiLookupFailureException;
|
||||
import org.springframework.ws.WebServiceMessageFactory;
|
||||
import org.springframework.ws.transport.WebServiceMessageReceiver;
|
||||
|
||||
/**
|
||||
* EJB {@link MessageDrivenBean} that can be used to handleMessage incoming JMS messages.
|
||||
* <p/>
|
||||
* This class needs a JMS {@link ConnectionFactory}, a {@link WebServiceMessageFactory} and {@link
|
||||
* WebServiceMessageReceiver} to operate. By default, these are obtained by doing a bean lookup on the bean factory
|
||||
* provided by {@link #getBeanFactory()} the super class.
|
||||
*
|
||||
* @author Arjen Poutsma
|
||||
* @see #createConnectionFactory()
|
||||
* @see #createMessageFactory()
|
||||
* @see #createMessageReceiver()
|
||||
*/
|
||||
public class WebServiceMessageDrivenBean extends AbstractJmsMessageDrivenBean {
|
||||
|
||||
/** Well-known name for the {@link ConnectionFactory} object in the bean factory for this bean. */
|
||||
public static final String CONNECTION_FACTORY_BEAN_NAME = "connectionFactory";
|
||||
|
||||
/** Well-known name for the {@link WebServiceMessageFactory} bean in the bean factory for this bean. */
|
||||
public static final String MESSAGE_FACTORY_BEAN_NAME = "messageFactory";
|
||||
|
||||
/** Well-known name for the {@link WebServiceMessageReceiver} object in the bean factory for this bean. */
|
||||
public static final String MESSAGE_RECEIVER_BEAN_NAME = "messageReceiver";
|
||||
|
||||
private JmsMessageReceiver delegate;
|
||||
|
||||
private ConnectionFactory connectionFactory;
|
||||
|
||||
/** Delegates to {@link JmsMessageReceiver#handleMessage(Message,Session)}. */
|
||||
public void onMessage(Message message) {
|
||||
Connection connection = null;
|
||||
Session session = null;
|
||||
try {
|
||||
connection = createConnection(connectionFactory);
|
||||
session = createSession(connection);
|
||||
delegate.handleMessage(message, session);
|
||||
}
|
||||
catch (JmsTransportException ex) {
|
||||
throw JmsUtils.convertJmsAccessException(ex.getJmsException());
|
||||
}
|
||||
catch (JMSException ex) {
|
||||
throw JmsUtils.convertJmsAccessException(ex);
|
||||
}
|
||||
catch (Exception ex) {
|
||||
throw new EJBException(ex);
|
||||
}
|
||||
finally {
|
||||
JmsUtils.closeSession(session);
|
||||
ConnectionFactoryUtils.releaseConnection(connection, connectionFactory, true);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new {@link Connection}, {@link WebServiceMessageFactory}, and {@link WebServiceMessageReceiver}.
|
||||
*
|
||||
* @see #createConnectionFactory()
|
||||
* @see #createMessageFactory()
|
||||
* @see #createMessageReceiver()
|
||||
*/
|
||||
@Override
|
||||
protected void onEjbCreate() {
|
||||
try {
|
||||
connectionFactory = createConnectionFactory();
|
||||
delegate = new JmsMessageReceiver();
|
||||
delegate.setMessageFactory(createMessageFactory());
|
||||
delegate.setMessageReceiver(createMessageReceiver());
|
||||
delegate.setPostProcessor(createPostProcessor());
|
||||
}
|
||||
catch (NamingException ex) {
|
||||
throw new JndiLookupFailureException("Could not create connection", ex);
|
||||
}
|
||||
catch (JMSException ex) {
|
||||
throw JmsUtils.convertJmsAccessException(ex);
|
||||
}
|
||||
catch (Exception ex) {
|
||||
throw new EJBException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/** Creates a connection factory. Default implementation does a bean lookup for {@link #CONNECTION_FACTORY_BEAN_NAME}. */
|
||||
protected ConnectionFactory createConnectionFactory() throws Exception {
|
||||
return (ConnectionFactory) getBeanFactory().getBean(CONNECTION_FACTORY_BEAN_NAME, ConnectionFactory.class);
|
||||
}
|
||||
|
||||
/** Creates a message factory. Default implementation does a bean lookup for {@link #MESSAGE_FACTORY_BEAN_NAME}. */
|
||||
protected WebServiceMessageFactory createMessageFactory() {
|
||||
return (WebServiceMessageFactory) getBeanFactory()
|
||||
.getBean(MESSAGE_FACTORY_BEAN_NAME, WebServiceMessageFactory.class);
|
||||
}
|
||||
|
||||
/** Creates a connection factory. Default implementation does a bean lookup for {@link #MESSAGE_RECEIVER_BEAN_NAME}. */
|
||||
protected WebServiceMessageReceiver createMessageReceiver() {
|
||||
return (WebServiceMessageReceiver) getBeanFactory()
|
||||
.getBean(MESSAGE_RECEIVER_BEAN_NAME, WebServiceMessageReceiver.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a JMS {@link Connection} using the given {@link ConnectionFactory}.
|
||||
* <p/>
|
||||
* This implementation uses JMS 1.1 API.
|
||||
*
|
||||
* @param connectionFactory the JMS ConnectionFactory to create a Connection with
|
||||
* @return the new JMS Connection
|
||||
* @throws JMSException if thrown by JMS API methods
|
||||
* @see ConnectionFactory#createConnection()
|
||||
*/
|
||||
protected Connection createConnection(ConnectionFactory connectionFactory) throws JMSException {
|
||||
return connectionFactory.createConnection();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a JMS {@link Session}. Default implementation creates a non-transactional, {@link Session#AUTO_ACKNOWLEDGE
|
||||
* auto acknowledged} session.
|
||||
* <p/>
|
||||
* This implementation uses JMS 1.1 API.
|
||||
*
|
||||
* @param connection the JMS Connection to create a Session for
|
||||
* @return the new JMS Session
|
||||
* @throws JMSException if thrown by JMS API methods
|
||||
* @see Connection#createSession(boolean,int)
|
||||
*/
|
||||
protected Session createSession(Connection connection) throws JMSException {
|
||||
return connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a JMS {@link MessagePostProcessor} to process JMS messages. Default
|
||||
* implementation returns {@code null}, meaning that no post processor is used.
|
||||
*
|
||||
* @return a message post processor
|
||||
*/
|
||||
protected MessagePostProcessor createPostProcessor() {
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
* Copyright 2005-2010 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.ws.transport.jms;
|
||||
|
||||
import javax.jms.BytesMessage;
|
||||
import javax.jms.JMSException;
|
||||
import javax.jms.Message;
|
||||
import javax.jms.Session;
|
||||
|
||||
import org.springframework.jms.listener.SessionAwareMessageListener;
|
||||
import org.springframework.ws.WebServiceMessage;
|
||||
import org.springframework.ws.WebServiceMessageFactory;
|
||||
import org.springframework.ws.transport.WebServiceMessageReceiver;
|
||||
|
||||
/**
|
||||
* Spring {@link SessionAwareMessageListener} that can be used to handle incoming {@link Message} service requests.
|
||||
* <p/>
|
||||
* Requires a {@link WebServiceMessageFactory} which is used to convert the incoming JMS {@link BytesMessage} into a
|
||||
* {@link WebServiceMessage}, and passes that to the {@link WebServiceMessageReceiver} {@link
|
||||
* #setMessageReceiver(WebServiceMessageReceiver) registered}.
|
||||
*
|
||||
* @author Arjen Poutsma
|
||||
* @see #setMessageFactory(org.springframework.ws.WebServiceMessageFactory)
|
||||
* @see #setMessageReceiver(org.springframework.ws.transport.WebServiceMessageReceiver)
|
||||
* @since 1.5.0
|
||||
*/
|
||||
public class WebServiceMessageListener extends JmsMessageReceiver implements SessionAwareMessageListener<Message> {
|
||||
|
||||
public void onMessage(Message message, Session session) throws JMSException {
|
||||
try {
|
||||
handleMessage(message, session);
|
||||
}
|
||||
catch (JmsTransportException ex) {
|
||||
throw ex.getJmsException();
|
||||
}
|
||||
catch (Exception ex) {
|
||||
JMSException jmsException = new JMSException(ex.getMessage());
|
||||
jmsException.setLinkedException(ex);
|
||||
throw jmsException;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
<html>
|
||||
<body>
|
||||
Package providing support for handling messages via JMS.
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,259 @@
|
||||
/*
|
||||
* Copyright 2005-2012 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.ws.transport.jms.support;
|
||||
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Enumeration;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
import javax.jms.DeliveryMode;
|
||||
import javax.jms.Destination;
|
||||
import javax.jms.JMSException;
|
||||
import javax.jms.Message;
|
||||
import javax.jms.Queue;
|
||||
import javax.jms.Topic;
|
||||
|
||||
import org.springframework.ws.transport.jms.JmsTransportConstants;
|
||||
|
||||
/**
|
||||
* Collection of utility methods to work with JMS transports. Includes methods to retrieve JMS properties from an {@link
|
||||
* URI}.
|
||||
*
|
||||
* @author Arjen Poutsma
|
||||
* @since 1.5.0
|
||||
*/
|
||||
public abstract class JmsTransportUtils {
|
||||
|
||||
private static final String[] CONVERSION_TABLE = new String[]{JmsTransportConstants.HEADER_CONTENT_TYPE,
|
||||
JmsTransportConstants.PROPERTY_CONTENT_TYPE, JmsTransportConstants.HEADER_CONTENT_LENGTH,
|
||||
JmsTransportConstants.PROPERTY_CONTENT_LENGTH, JmsTransportConstants.HEADER_SOAP_ACTION,
|
||||
JmsTransportConstants.PROPERTY_SOAP_ACTION, JmsTransportConstants.HEADER_ACCEPT_ENCODING,
|
||||
JmsTransportConstants.PROPERTY_ACCEPT_ENCODING};
|
||||
|
||||
private static final Pattern DESTINATION_NAME_PATTERN = Pattern.compile("^([^\\?]+)");
|
||||
|
||||
private static final Pattern DELIVERY_MODE_PATTERN = Pattern.compile("deliveryMode=(PERSISTENT|NON_PERSISTENT)");
|
||||
|
||||
private static final Pattern MESSAGE_TYPE_PATTERN = Pattern.compile("messageType=(BYTES_MESSAGE|TEXT_MESSAGE)");
|
||||
|
||||
private static final Pattern TIME_TO_LIVE_PATTERN = Pattern.compile("timeToLive=(\\d+)");
|
||||
|
||||
private static final Pattern PRIORITY_PATTERN = Pattern.compile("priority=(\\d)");
|
||||
|
||||
private static final Pattern REPLY_TO_NAME_PATTERN = Pattern.compile("replyToName=([^&]+)");
|
||||
|
||||
private JmsTransportUtils() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts the given transport header to a JMS property name. Returns the given header name if no match is found.
|
||||
*
|
||||
* @param headerName the header name to transform
|
||||
* @return the JMS property name
|
||||
*/
|
||||
public static String headerToJmsProperty(String headerName) {
|
||||
for (int i = 0; i < CONVERSION_TABLE.length; i = i + 2) {
|
||||
if (CONVERSION_TABLE[i].equals(headerName)) {
|
||||
return CONVERSION_TABLE[i + 1];
|
||||
}
|
||||
}
|
||||
return headerName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts the given JMS property name to a transport header name. Returns the given property name if no match is
|
||||
* found.
|
||||
*
|
||||
* @param propertyName the JMS property name to transform
|
||||
* @return the transport header name
|
||||
*/
|
||||
public static String jmsPropertyToHeader(String propertyName) {
|
||||
for (int i = 1; i < CONVERSION_TABLE.length; i = i + 2) {
|
||||
if (CONVERSION_TABLE[i].equals(propertyName)) {
|
||||
return CONVERSION_TABLE[i - 1];
|
||||
}
|
||||
}
|
||||
return propertyName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts the given JMS destination into a <code>jms</code> URI.
|
||||
*
|
||||
* @param destination the destination
|
||||
* @return a jms URI
|
||||
*/
|
||||
public static URI toUri(Destination destination) throws URISyntaxException, JMSException {
|
||||
String destinationName;
|
||||
if (destination instanceof Queue) {
|
||||
destinationName = ((Queue) destination).getQueueName();
|
||||
}
|
||||
else if (destination instanceof Topic) {
|
||||
Topic topic = (Topic) destination;
|
||||
destinationName = topic.getTopicName();
|
||||
}
|
||||
else {
|
||||
throw new IllegalArgumentException("Destination [ " + destination + "] is neither Queue nor Topic");
|
||||
}
|
||||
return new URI(JmsTransportConstants.JMS_URI_SCHEME, destinationName, null);
|
||||
}
|
||||
|
||||
/** Returns the destination name of the given URI. */
|
||||
public static String getDestinationName(URI uri) {
|
||||
return getStringParameter(DESTINATION_NAME_PATTERN, uri);
|
||||
}
|
||||
|
||||
/** Adds the given header to the specified message. */
|
||||
public static void addHeader(Message message, String name, String value) throws JMSException {
|
||||
String propertyName = JmsTransportUtils.headerToJmsProperty(name);
|
||||
message.setStringProperty(propertyName, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an iterator over all header names in the given message. Delegates to {@link
|
||||
* #jmsPropertyToHeader(String)}.
|
||||
*/
|
||||
public static Iterator<String> getHeaderNames(Message message) throws JMSException {
|
||||
Enumeration<?> properties = message.getPropertyNames();
|
||||
List<String> results = new ArrayList<String>();
|
||||
while (properties.hasMoreElements()) {
|
||||
String property = (String) properties.nextElement();
|
||||
if (property.startsWith(JmsTransportConstants.PROPERTY_PREFIX)) {
|
||||
String header = jmsPropertyToHeader(property);
|
||||
results.add(header);
|
||||
}
|
||||
}
|
||||
return results.iterator();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an iterator over all the header values of the given message and header name. Delegates to {@link
|
||||
* #headerToJmsProperty(String)}.
|
||||
*/
|
||||
public static Iterator<String> getHeaders(Message message, String name) throws JMSException {
|
||||
String propertyName = headerToJmsProperty(name);
|
||||
String value = message.getStringProperty(propertyName);
|
||||
if (value != null) {
|
||||
return Collections.singletonList(value).iterator();
|
||||
}
|
||||
else {
|
||||
return Collections.<String>emptyList().iterator();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the delivery mode of the given URI.
|
||||
*
|
||||
* @see DeliveryMode#NON_PERSISTENT
|
||||
* @see DeliveryMode#PERSISTENT
|
||||
* @see Message#DEFAULT_DELIVERY_MODE
|
||||
*/
|
||||
public static int getDeliveryMode(URI uri) {
|
||||
String deliveryMode = getStringParameter(DELIVERY_MODE_PATTERN, uri);
|
||||
if ("NON_PERSISTENT".equals(deliveryMode)) {
|
||||
return DeliveryMode.NON_PERSISTENT;
|
||||
}
|
||||
else if ("PERSISTENT".equals(deliveryMode)) {
|
||||
return DeliveryMode.PERSISTENT;
|
||||
}
|
||||
else {
|
||||
return Message.DEFAULT_DELIVERY_MODE;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the message type of the given URI. Defaults to {@link JmsTransportConstants#BYTES_MESSAGE_TYPE}.
|
||||
*
|
||||
* @see JmsTransportConstants#BYTES_MESSAGE_TYPE
|
||||
* @see JmsTransportConstants#TEXT_MESSAGE_TYPE
|
||||
*/
|
||||
public static int getMessageType(URI uri) {
|
||||
String deliveryMode = getStringParameter(MESSAGE_TYPE_PATTERN, uri);
|
||||
if ("TEXT_MESSAGE".equals(deliveryMode)) {
|
||||
return JmsTransportConstants.TEXT_MESSAGE_TYPE;
|
||||
}
|
||||
else {
|
||||
return JmsTransportConstants.BYTES_MESSAGE_TYPE;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the lifetime, in milliseconds, of the given URI.
|
||||
*
|
||||
* @see Message#DEFAULT_TIME_TO_LIVE
|
||||
*/
|
||||
public static long getTimeToLive(URI uri) {
|
||||
return getLongParameter(TIME_TO_LIVE_PATTERN, uri, Message.DEFAULT_TIME_TO_LIVE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the priority of the given URI.
|
||||
*
|
||||
* @see Message#DEFAULT_PRIORITY
|
||||
*/
|
||||
public static int getPriority(URI uri) {
|
||||
return getIntParameter(PRIORITY_PATTERN, uri, Message.DEFAULT_PRIORITY);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the reply-to name of the given URI.
|
||||
*
|
||||
* @see Message#setJMSReplyTo(Destination)
|
||||
*/
|
||||
public static String getReplyToName(URI uri) {
|
||||
return getStringParameter(REPLY_TO_NAME_PATTERN, uri);
|
||||
}
|
||||
|
||||
private static String getStringParameter(Pattern pattern, URI uri) {
|
||||
Matcher matcher = pattern.matcher(uri.getSchemeSpecificPart());
|
||||
if (matcher.find() && matcher.groupCount() == 1) {
|
||||
return matcher.group(1);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static int getIntParameter(Pattern pattern, URI uri, int defaultValue) {
|
||||
Matcher matcher = pattern.matcher(uri.getSchemeSpecificPart());
|
||||
if (matcher.find() && matcher.groupCount() == 1) {
|
||||
try {
|
||||
return Integer.parseInt(matcher.group(1));
|
||||
}
|
||||
catch (NumberFormatException ex) {
|
||||
// fall through to default value
|
||||
}
|
||||
}
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
private static long getLongParameter(Pattern pattern, URI uri, long defaultValue) {
|
||||
Matcher matcher = pattern.matcher(uri.getSchemeSpecificPart());
|
||||
if (matcher.find() && matcher.groupCount() == 1) {
|
||||
try {
|
||||
return Long.parseLong(matcher.group(1));
|
||||
}
|
||||
catch (NumberFormatException ex) {
|
||||
// fall through to default value
|
||||
}
|
||||
}
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
<html>
|
||||
<body>
|
||||
Classes supporting the org.springframework.ws.transport.jms package.
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,278 @@
|
||||
/*
|
||||
* Copyright 2005-2010 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.ws.transport.mail;
|
||||
|
||||
import java.util.Properties;
|
||||
import javax.mail.Folder;
|
||||
import javax.mail.FolderClosedException;
|
||||
import javax.mail.Message;
|
||||
import javax.mail.MessagingException;
|
||||
import javax.mail.Session;
|
||||
import javax.mail.Store;
|
||||
import javax.mail.URLName;
|
||||
import javax.mail.internet.AddressException;
|
||||
import javax.mail.internet.InternetAddress;
|
||||
|
||||
import org.springframework.scheduling.SchedulingAwareRunnable;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.ws.WebServiceMessageFactory;
|
||||
import org.springframework.ws.transport.WebServiceMessageReceiver;
|
||||
import org.springframework.ws.transport.mail.monitor.MonitoringStrategy;
|
||||
import org.springframework.ws.transport.mail.monitor.PollingMonitoringStrategy;
|
||||
import org.springframework.ws.transport.mail.monitor.Pop3PollingMonitoringStrategy;
|
||||
import org.springframework.ws.transport.mail.support.MailTransportUtils;
|
||||
import org.springframework.ws.transport.support.AbstractAsyncStandaloneMessageReceiver;
|
||||
|
||||
/**
|
||||
* Server-side component for receiving email messages using JavaMail. Requires a {@link #setTransportUri(String)
|
||||
* transport} URI, {@link #setStoreUri(String) store} URI, and {@link #setMonitoringStrategy(MonitoringStrategy)
|
||||
* monitoringStrategy} to be set, in addition to the {@link #setMessageFactory(WebServiceMessageFactory) messageFactory}
|
||||
* and {@link #setMessageReceiver(WebServiceMessageReceiver) messageReceiver} required by the base class.
|
||||
* <p/>
|
||||
* The {@link MonitoringStrategy} is used to detect new incoming email request. If the <code>monitoringStrategy</code>
|
||||
* is not explicitly set, this receiver will use the {@link Pop3PollingMonitoringStrategy} for POP3 servers, and the
|
||||
* {@link PollingMonitoringStrategy} for IMAP servers.
|
||||
*
|
||||
* @author Arjen Poutsma
|
||||
* @since 1.5.0
|
||||
*/
|
||||
public class MailMessageReceiver extends AbstractAsyncStandaloneMessageReceiver {
|
||||
|
||||
private Session session = Session.getInstance(new Properties(), null);
|
||||
|
||||
private URLName storeUri;
|
||||
|
||||
private URLName transportUri;
|
||||
|
||||
private Folder folder;
|
||||
|
||||
private Store store;
|
||||
|
||||
private InternetAddress from;
|
||||
|
||||
private MonitoringStrategy monitoringStrategy;
|
||||
|
||||
/** Sets the from address to use when sending response messages. */
|
||||
public void setFrom(String from) throws AddressException {
|
||||
this.from = new InternetAddress(from);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set JavaMail properties for the {@link Session}.
|
||||
* <p/>
|
||||
* A new {@link Session} will be created with those properties. Use either this method or {@link #setSession}, but
|
||||
* not both.
|
||||
* <p/>
|
||||
* Non-default properties in this instance will override given JavaMail properties.
|
||||
*/
|
||||
public void setJavaMailProperties(Properties javaMailProperties) {
|
||||
session = Session.getInstance(javaMailProperties, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the JavaMail <code>Session</code>, possibly pulled from JNDI.
|
||||
* <p/>
|
||||
* Default is a new <code>Session</code> without defaults, that is completely configured via this instance's
|
||||
* properties.
|
||||
* <p/>
|
||||
* If using a pre-configured <code>Session</code>, non-default properties in this instance will override the
|
||||
* settings in the <code>Session</code>.
|
||||
*
|
||||
* @see #setJavaMailProperties
|
||||
*/
|
||||
public void setSession(Session session) {
|
||||
Assert.notNull(session, "Session must not be null");
|
||||
this.session = session;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the JavaMail Store URI to be used for retrieving request messages. Typically takes the form of
|
||||
* <code>[imap|pop3]://user:password@host:port/INBOX</code>. Setting this property is required.
|
||||
* <p/>
|
||||
* For example, <code>imap://john:secret@imap.example.com/INBOX</code>
|
||||
*
|
||||
* @see Session#getStore(URLName)
|
||||
*/
|
||||
public void setStoreUri(String storeUri) {
|
||||
this.storeUri = new URLName(storeUri);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the JavaMail Transport URI to be used for sending response messages. Typically takes the form of
|
||||
* <code>smtp://user:password@host:port</code>. Setting this property is required.
|
||||
* <p/>
|
||||
* For example, <code>smtp://john:secret@smtp.example.com</code>
|
||||
*
|
||||
* @see Session#getTransport(URLName)
|
||||
*/
|
||||
public void setTransportUri(String transportUri) {
|
||||
this.transportUri = new URLName(transportUri);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the monitoring strategy to use for retrieving new requests. Default is the {@link
|
||||
* PollingMonitoringStrategy}.
|
||||
*/
|
||||
public void setMonitoringStrategy(MonitoringStrategy monitoringStrategy) {
|
||||
this.monitoringStrategy = monitoringStrategy;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
Assert.notNull(storeUri, "Property 'storeUri' is required");
|
||||
Assert.notNull(transportUri, "Property 'transportUri' is required");
|
||||
if (monitoringStrategy == null) {
|
||||
String protocol = storeUri.getProtocol();
|
||||
if ("pop3".equals(protocol)) {
|
||||
monitoringStrategy = new Pop3PollingMonitoringStrategy();
|
||||
}
|
||||
else if ("imap".equals(protocol)) {
|
||||
monitoringStrategy = new PollingMonitoringStrategy();
|
||||
}
|
||||
else {
|
||||
throw new IllegalArgumentException("Cannot determine monitoring strategy for \"" + protocol + "\". " +
|
||||
"Set the 'monitoringStrategy' explicitly.");
|
||||
}
|
||||
}
|
||||
super.afterPropertiesSet();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onActivate() throws MessagingException {
|
||||
openSession();
|
||||
openFolder();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStart() {
|
||||
if (logger.isInfoEnabled()) {
|
||||
logger.info("Starting mail receiver [" + MailTransportUtils.toPasswordProtectedString(storeUri) + "]");
|
||||
}
|
||||
execute(new MonitoringRunnable());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStop() {
|
||||
if (logger.isInfoEnabled()) {
|
||||
logger.info("Stopping mail receiver [" + MailTransportUtils.toPasswordProtectedString(storeUri) + "]");
|
||||
}
|
||||
closeFolder();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onShutdown() {
|
||||
if (logger.isInfoEnabled()) {
|
||||
logger.info("Shutting down mail receiver [" + MailTransportUtils.toPasswordProtectedString(storeUri) + "]");
|
||||
}
|
||||
closeFolder();
|
||||
closeSession();
|
||||
}
|
||||
|
||||
private void openSession() throws MessagingException {
|
||||
store = session.getStore(storeUri);
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Connecting to store [" + MailTransportUtils.toPasswordProtectedString(storeUri) + "]");
|
||||
}
|
||||
store.connect();
|
||||
}
|
||||
|
||||
private void openFolder() throws MessagingException {
|
||||
if (folder != null && folder.isOpen()) {
|
||||
return;
|
||||
}
|
||||
folder = store.getFolder(storeUri);
|
||||
if (folder == null || !folder.exists()) {
|
||||
throw new IllegalStateException("No default folder to receive from");
|
||||
}
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Opening folder [" + MailTransportUtils.toPasswordProtectedString(storeUri) + "]");
|
||||
}
|
||||
folder.open(monitoringStrategy.getFolderOpenMode());
|
||||
}
|
||||
|
||||
private void closeFolder() {
|
||||
MailTransportUtils.closeFolder(folder, true);
|
||||
}
|
||||
|
||||
private void closeSession() {
|
||||
MailTransportUtils.closeService(store);
|
||||
}
|
||||
|
||||
private class MonitoringRunnable implements SchedulingAwareRunnable {
|
||||
|
||||
public void run() {
|
||||
try {
|
||||
openFolder();
|
||||
while (isRunning()) {
|
||||
try {
|
||||
Message[] messages = monitoringStrategy.monitor(folder);
|
||||
for (Message message : messages) {
|
||||
MessageHandler handler = new MessageHandler(message);
|
||||
execute(handler);
|
||||
}
|
||||
}
|
||||
catch (FolderClosedException ex) {
|
||||
logger.debug("Folder closed, reopening");
|
||||
if (isRunning()) {
|
||||
openFolder();
|
||||
}
|
||||
}
|
||||
catch (MessagingException ex) {
|
||||
logger.warn(ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (InterruptedException ex) {
|
||||
// Restore the interrupted status
|
||||
Thread.currentThread().interrupt();
|
||||
}
|
||||
catch (MessagingException ex) {
|
||||
logger.error(ex);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isLongLived() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
private class MessageHandler implements SchedulingAwareRunnable {
|
||||
|
||||
private final Message message;
|
||||
|
||||
public MessageHandler(Message message) {
|
||||
this.message = message;
|
||||
}
|
||||
|
||||
public void run() {
|
||||
MailReceiverConnection connection = new MailReceiverConnection(message, session);
|
||||
connection.setTransportUri(transportUri);
|
||||
connection.setFrom(from);
|
||||
try {
|
||||
handleConnection(connection);
|
||||
}
|
||||
catch (Exception ex) {
|
||||
logger.error("Could not handle incoming mail connection", ex);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isLongLived() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,168 @@
|
||||
/*
|
||||
* Copyright 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.ws.transport.mail;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.URI;
|
||||
import java.util.Properties;
|
||||
import javax.mail.Session;
|
||||
import javax.mail.URLName;
|
||||
import javax.mail.internet.AddressException;
|
||||
import javax.mail.internet.InternetAddress;
|
||||
import javax.mail.internet.MimeMessage;
|
||||
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.ws.WebServiceMessageFactory;
|
||||
import org.springframework.ws.transport.WebServiceConnection;
|
||||
import org.springframework.ws.transport.WebServiceMessageSender;
|
||||
import org.springframework.ws.transport.mail.monitor.PollingMonitoringStrategy;
|
||||
import org.springframework.ws.transport.mail.support.MailTransportUtils;
|
||||
|
||||
/**
|
||||
* {@link WebServiceMessageSender} implementation that uses Mail {@link MimeMessage}s. Requires a {@link
|
||||
* #setTransportUri(String) transport} and {@link #setStoreUri(String) store} URI to be set.
|
||||
* <p/>
|
||||
* Calling {@link WebServiceConnection#receive(WebServiceMessageFactory)} on connections created by this message sender
|
||||
* will result in a blocking call, for the amount of milliseconds specified by the {@link #setReceiveSleepTime(long)
|
||||
* receiveSleepTime} property. This will give the server time to formulate a response message. By default, this propery
|
||||
* is set to 1 minute. For a proper request-response conversation to work, this property value must not be smaller the
|
||||
* {@link PollingMonitoringStrategy#setPollingInterval(long) pollingInterval} property of the server-side message
|
||||
* receiver polling strategy.
|
||||
* <p/>
|
||||
* This message sender supports URI's of the following format: <blockquote> <tt><b>mailto:</b></tt><i>to</i>[<tt><b>?</b></tt><i>param-name</i><tt><b>=</b></tt><i>param-value</i>][<tt><b>&</b></tt><i>param-name</i><tt><b>=</b></tt><i>param-value</i>]*
|
||||
* </blockquote> where the characters <tt><b>:</b></tt>, <tt><b>?</b></tt>, and <tt><b>&</b></tt> stand for
|
||||
* themselves. The <i>to</i> represents a RFC 822 mailbox. Valid <i>param-name</i> include:
|
||||
* <p/>
|
||||
* <blockquote><table> <tr><th><i>param-name</i></th><th><i>Description</i></th></tr>
|
||||
* <tr><td><tt>subject</tt></td><td>The subject of the request message.</td></tr> </table></blockquote>
|
||||
* <p/>
|
||||
* Some examples of email URIs are:
|
||||
* <p/>
|
||||
* <blockquote><tt>mailto:john@example.com</tt><br> <tt>mailto:john@example.com@?subject=SOAP%20Test</tt><br></blockquote>
|
||||
*
|
||||
* @author Arjen Poutsma
|
||||
* @see <a href="http://www.ietf.org/rfc/rfc2368.txt">The mailto URL scheme</a>
|
||||
* @since 1.5.0
|
||||
*/
|
||||
public class MailMessageSender implements WebServiceMessageSender, InitializingBean {
|
||||
|
||||
/**
|
||||
* Default timeout for receive operations. Set to 1000 * 60 milliseconds (i.e. 1 minute).
|
||||
*/
|
||||
public static final long DEFAULT_RECEIVE_TIMEOUT = 1000 * 60;
|
||||
|
||||
private long receiveSleepTime = DEFAULT_RECEIVE_TIMEOUT;
|
||||
|
||||
private Session session = Session.getInstance(new Properties(), null);
|
||||
|
||||
private URLName storeUri;
|
||||
|
||||
private URLName transportUri;
|
||||
|
||||
private InternetAddress from;
|
||||
|
||||
/**
|
||||
* Sets the from address to use when sending request messages.
|
||||
*/
|
||||
public void setFrom(String from) throws AddressException {
|
||||
this.from = new InternetAddress(from);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set JavaMail properties for the {@link Session}.
|
||||
* <p/>
|
||||
* A new {@link Session} will be created with those properties. Use either this method or {@link #setSession}, but
|
||||
* not both.
|
||||
* <p/>
|
||||
* Non-default properties in this instance will override given JavaMail properties.
|
||||
*/
|
||||
public void setJavaMailProperties(Properties javaMailProperties) {
|
||||
session = Session.getInstance(javaMailProperties, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the sleep time to use for receive calls, <strong>in milliseconds</strong>. The default is 1000 * 60 ms, that
|
||||
* is 1 minute.
|
||||
*/
|
||||
public void setReceiveSleepTime(long receiveSleepTime) {
|
||||
this.receiveSleepTime = receiveSleepTime;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the JavaMail <code>Session</code>, possibly pulled from JNDI.
|
||||
* <p/>
|
||||
* Default is a new <code>Session</code> without defaults, that is completely configured via this instance's
|
||||
* properties.
|
||||
* <p/>
|
||||
* If using a pre-configured <code>Session</code>, non-default properties in this instance will override the
|
||||
* settings in the <code>Session</code>.
|
||||
*
|
||||
* @see #setJavaMailProperties
|
||||
*/
|
||||
public void setSession(Session session) {
|
||||
Assert.notNull(session, "Session must not be null");
|
||||
this.session = session;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the JavaMail Store URI to be used for retrieving response messages. Typically takes the form of
|
||||
* <code>[imap|pop3]://user:password@host:port/INBOX</code>. Setting this property is required.
|
||||
* <p/>
|
||||
* For example, <code>imap://john:secret@imap.example.com/INBOX</code>
|
||||
*
|
||||
* @see Session#getStore(URLName)
|
||||
*/
|
||||
public void setStoreUri(String storeUri) {
|
||||
this.storeUri = new URLName(storeUri);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the JavaMail Transport URI to be used for sending response messages. Typically takes the form of
|
||||
* <code>smtp://user:password@host:port</code>. Setting this property is required.
|
||||
* <p/>
|
||||
* For example, <code>smtp://john:secret@smtp.example.com</code>
|
||||
*
|
||||
* @see Session#getTransport(URLName)
|
||||
*/
|
||||
public void setTransportUri(String transportUri) {
|
||||
this.transportUri = new URLName(transportUri);
|
||||
}
|
||||
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
Assert.notNull(transportUri, "'transportUri' is required");
|
||||
Assert.notNull(storeUri, "'storeUri' is required");
|
||||
}
|
||||
|
||||
public WebServiceConnection createConnection(URI uri) throws IOException {
|
||||
InternetAddress to = MailTransportUtils.getTo(uri);
|
||||
MailSenderConnection connection =
|
||||
new MailSenderConnection(session, transportUri, storeUri, to, receiveSleepTime);
|
||||
if (from != null) {
|
||||
connection.setFrom(from);
|
||||
}
|
||||
String subject = MailTransportUtils.getSubject(uri);
|
||||
if (subject != null) {
|
||||
connection.setSubject(subject);
|
||||
}
|
||||
return connection;
|
||||
}
|
||||
|
||||
public boolean supports(URI uri) {
|
||||
return uri.getScheme().equals(MailTransportConstants.MAIL_URI_SCHEME);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,254 @@
|
||||
/*
|
||||
* Copyright 2005-2010 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.ws.transport.mail;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Enumeration;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import javax.activation.DataHandler;
|
||||
import javax.activation.DataSource;
|
||||
import javax.mail.Address;
|
||||
import javax.mail.Header;
|
||||
import javax.mail.Message;
|
||||
import javax.mail.MessagingException;
|
||||
import javax.mail.Session;
|
||||
import javax.mail.Transport;
|
||||
import javax.mail.URLName;
|
||||
import javax.mail.internet.InternetAddress;
|
||||
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
import org.springframework.ws.WebServiceMessage;
|
||||
import org.springframework.ws.transport.AbstractReceiverConnection;
|
||||
import org.springframework.ws.transport.TransportConstants;
|
||||
import org.springframework.ws.transport.WebServiceConnection;
|
||||
import org.springframework.ws.transport.mail.support.MailTransportUtils;
|
||||
|
||||
/**
|
||||
* Implementation of {@link WebServiceConnection} that is used for server-side Mail access. Exposes a {@link Message}
|
||||
* request and response message.
|
||||
*
|
||||
* @author Arjen Poutsma
|
||||
* @since 1.5.0
|
||||
*/
|
||||
public class MailReceiverConnection extends AbstractReceiverConnection {
|
||||
|
||||
private final Message requestMessage;
|
||||
|
||||
private final Session session;
|
||||
|
||||
private Message responseMessage;
|
||||
|
||||
private ByteArrayOutputStream responseBuffer;
|
||||
|
||||
private String responseContentType;
|
||||
|
||||
private URLName transportUri;
|
||||
|
||||
private InternetAddress from;
|
||||
|
||||
/** Constructs a new Mail connection with the given parameters. */
|
||||
protected MailReceiverConnection(Message requestMessage, Session session) {
|
||||
Assert.notNull(requestMessage, "'requestMessage' must not be null");
|
||||
Assert.notNull(session, "'session' must not be null");
|
||||
this.requestMessage = requestMessage;
|
||||
this.session = session;
|
||||
}
|
||||
|
||||
/** Returns the request message for this connection. */
|
||||
public Message getRequestMessage() {
|
||||
return requestMessage;
|
||||
}
|
||||
|
||||
/** Returns the response message, if any, for this connection. */
|
||||
public Message getResponseMessage() {
|
||||
return responseMessage;
|
||||
}
|
||||
|
||||
/*
|
||||
* Package-friendly setters
|
||||
*/
|
||||
void setTransportUri(URLName transportUri) {
|
||||
this.transportUri = transportUri;
|
||||
}
|
||||
|
||||
void setFrom(InternetAddress from) {
|
||||
this.from = from;
|
||||
}
|
||||
|
||||
/*
|
||||
* URI
|
||||
*/
|
||||
|
||||
public URI getUri() throws URISyntaxException {
|
||||
try {
|
||||
Address[] recipients = requestMessage.getRecipients(Message.RecipientType.TO);
|
||||
if (!ObjectUtils.isEmpty(recipients) && recipients[0] instanceof InternetAddress) {
|
||||
return MailTransportUtils.toUri((InternetAddress) recipients[0], requestMessage.getSubject());
|
||||
}
|
||||
else {
|
||||
throw new URISyntaxException("", "Could not determine To header");
|
||||
}
|
||||
}
|
||||
catch (MessagingException ex) {
|
||||
throw new URISyntaxException("", ex.getMessage());
|
||||
}
|
||||
}
|
||||
/*
|
||||
* Errors
|
||||
*/
|
||||
|
||||
public String getErrorMessage() throws IOException {
|
||||
return null;
|
||||
}
|
||||
|
||||
public boolean hasError() throws IOException {
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* Receiving
|
||||
*/
|
||||
|
||||
@Override
|
||||
protected Iterator<String> getRequestHeaderNames() throws IOException {
|
||||
try {
|
||||
List<String> headers = new ArrayList<String>();
|
||||
Enumeration<?> enumeration = requestMessage.getAllHeaders();
|
||||
while (enumeration.hasMoreElements()) {
|
||||
Header header = (Header) enumeration.nextElement();
|
||||
headers.add(header.getName());
|
||||
}
|
||||
return headers.iterator();
|
||||
}
|
||||
catch (MessagingException ex) {
|
||||
throw new IOException(ex.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Iterator<String> getRequestHeaders(String name) throws IOException {
|
||||
try {
|
||||
String[] headers = requestMessage.getHeader(name);
|
||||
return Arrays.asList(headers).iterator();
|
||||
}
|
||||
catch (MessagingException ex) {
|
||||
throw new MailTransportException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected InputStream getRequestInputStream() throws IOException {
|
||||
try {
|
||||
return requestMessage.getInputStream();
|
||||
}
|
||||
catch (MessagingException ex) {
|
||||
throw new MailTransportException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void addResponseHeader(String name, String value) throws IOException {
|
||||
try {
|
||||
responseMessage.addHeader(name, value);
|
||||
if (TransportConstants.HEADER_CONTENT_TYPE.equals(name)) {
|
||||
responseContentType = value;
|
||||
}
|
||||
}
|
||||
catch (MessagingException ex) {
|
||||
throw new MailTransportException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected OutputStream getResponseOutputStream() throws IOException {
|
||||
return responseBuffer;
|
||||
}
|
||||
|
||||
/*
|
||||
* Sending
|
||||
*/
|
||||
|
||||
@Override
|
||||
protected void onSendBeforeWrite(WebServiceMessage message) throws IOException {
|
||||
try {
|
||||
responseMessage = requestMessage.reply(false);
|
||||
responseMessage.setFrom(from);
|
||||
|
||||
responseBuffer = new ByteArrayOutputStream();
|
||||
}
|
||||
catch (MessagingException ex) {
|
||||
throw new MailTransportException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onSendAfterWrite(WebServiceMessage message) throws IOException {
|
||||
Transport transport = null;
|
||||
try {
|
||||
responseMessage.setDataHandler(
|
||||
new DataHandler(new ByteArrayDataSource(responseContentType, responseBuffer.toByteArray())));
|
||||
transport = session.getTransport(transportUri);
|
||||
transport.connect();
|
||||
responseMessage.saveChanges();
|
||||
transport.sendMessage(responseMessage, responseMessage.getAllRecipients());
|
||||
}
|
||||
catch (MessagingException ex) {
|
||||
throw new MailTransportException(ex);
|
||||
}
|
||||
finally {
|
||||
MailTransportUtils.closeService(transport);
|
||||
}
|
||||
}
|
||||
|
||||
private class ByteArrayDataSource implements DataSource {
|
||||
|
||||
private byte[] data;
|
||||
|
||||
private String contentType;
|
||||
|
||||
public ByteArrayDataSource(String contentType, byte[] data) {
|
||||
this.data = data;
|
||||
this.contentType = contentType;
|
||||
}
|
||||
|
||||
public String getContentType() {
|
||||
return contentType;
|
||||
}
|
||||
|
||||
public InputStream getInputStream() throws IOException {
|
||||
return new ByteArrayInputStream(data);
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return "ByteArrayDataSource";
|
||||
}
|
||||
|
||||
public OutputStream getOutputStream() throws IOException {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,337 @@
|
||||
/*
|
||||
* Copyright 2005-2010 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.ws.transport.mail;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Date;
|
||||
import java.util.Enumeration;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import javax.activation.DataHandler;
|
||||
import javax.activation.DataSource;
|
||||
import javax.mail.Flags;
|
||||
import javax.mail.Folder;
|
||||
import javax.mail.Header;
|
||||
import javax.mail.Message;
|
||||
import javax.mail.MessagingException;
|
||||
import javax.mail.Session;
|
||||
import javax.mail.Store;
|
||||
import javax.mail.Transport;
|
||||
import javax.mail.URLName;
|
||||
import javax.mail.internet.InternetAddress;
|
||||
import javax.mail.internet.MimeMessage;
|
||||
import javax.mail.search.HeaderTerm;
|
||||
import javax.mail.search.SearchTerm;
|
||||
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.ws.WebServiceMessage;
|
||||
import org.springframework.ws.transport.AbstractSenderConnection;
|
||||
import org.springframework.ws.transport.TransportConstants;
|
||||
import org.springframework.ws.transport.WebServiceConnection;
|
||||
import org.springframework.ws.transport.mail.support.MailTransportUtils;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
/**
|
||||
* Implementation of {@link WebServiceConnection} that is used for client-side Mail access. Exposes a {@link Message}
|
||||
* request and response message.
|
||||
*
|
||||
* @author Arjen Poutsma
|
||||
* @since 1.5.0
|
||||
*/
|
||||
|
||||
public class MailSenderConnection extends AbstractSenderConnection {
|
||||
|
||||
private static final Log logger = LogFactory.getLog(MailSenderConnection.class);
|
||||
|
||||
private final Session session;
|
||||
|
||||
private MimeMessage requestMessage;
|
||||
|
||||
private Message responseMessage;
|
||||
|
||||
private String requestContentType;
|
||||
|
||||
private boolean deleteAfterReceive = false;
|
||||
|
||||
private final URLName storeUri;
|
||||
|
||||
private final URLName transportUri;
|
||||
|
||||
private ByteArrayOutputStream requestBuffer;
|
||||
|
||||
private InternetAddress from;
|
||||
|
||||
private final InternetAddress to;
|
||||
|
||||
private String subject;
|
||||
|
||||
private final long receiveTimeout;
|
||||
|
||||
private Store store;
|
||||
|
||||
private Folder folder;
|
||||
|
||||
/** Constructs a new Mail connection with the given parameters. */
|
||||
protected MailSenderConnection(Session session,
|
||||
URLName transportUri,
|
||||
URLName storeUri,
|
||||
InternetAddress to,
|
||||
long receiveTimeout) {
|
||||
Assert.notNull(session, "'session' must not be null");
|
||||
Assert.notNull(transportUri, "'transportUri' must not be null");
|
||||
Assert.notNull(storeUri, "'storeUri' must not be null");
|
||||
Assert.notNull(to, "'to' must not be null");
|
||||
this.session = session;
|
||||
this.transportUri = transportUri;
|
||||
this.storeUri = storeUri;
|
||||
this.to = to;
|
||||
this.receiveTimeout = receiveTimeout;
|
||||
}
|
||||
|
||||
/** Returns the request message for this connection. */
|
||||
public Message getRequestMessage() {
|
||||
return requestMessage;
|
||||
}
|
||||
|
||||
/** Returns the response message, if any, for this connection. */
|
||||
public Message getResponseMessage() {
|
||||
return responseMessage;
|
||||
}
|
||||
|
||||
/*
|
||||
* Package-friendly setters
|
||||
*/
|
||||
|
||||
void setFrom(InternetAddress from) {
|
||||
this.from = from;
|
||||
}
|
||||
|
||||
void setSubject(String subject) {
|
||||
this.subject = subject;
|
||||
}
|
||||
|
||||
/*
|
||||
* URI
|
||||
*/
|
||||
public URI getUri() throws URISyntaxException {
|
||||
return MailTransportUtils.toUri(to, subject);
|
||||
}
|
||||
|
||||
/*
|
||||
* Sending
|
||||
*/
|
||||
@Override
|
||||
protected void onSendBeforeWrite(WebServiceMessage message) throws IOException {
|
||||
try {
|
||||
requestMessage = new MimeMessage(session);
|
||||
requestMessage.setRecipient(Message.RecipientType.TO, to);
|
||||
requestMessage.setSentDate(new Date());
|
||||
if (from != null) {
|
||||
requestMessage.setFrom(from);
|
||||
}
|
||||
if (subject != null) {
|
||||
requestMessage.setSubject(subject);
|
||||
}
|
||||
requestBuffer = new ByteArrayOutputStream();
|
||||
}
|
||||
catch (MessagingException ex) {
|
||||
throw new MailTransportException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void addRequestHeader(String name, String value) throws IOException {
|
||||
try {
|
||||
requestMessage.addHeader(name, value);
|
||||
if (TransportConstants.HEADER_CONTENT_TYPE.equals(name)) {
|
||||
requestContentType = value;
|
||||
}
|
||||
}
|
||||
catch (MessagingException ex) {
|
||||
throw new MailTransportException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected OutputStream getRequestOutputStream() throws IOException {
|
||||
return requestBuffer;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onSendAfterWrite(WebServiceMessage message) throws IOException {
|
||||
Transport transport = null;
|
||||
try {
|
||||
requestMessage.setDataHandler(
|
||||
new DataHandler(new ByteArrayDataSource(requestContentType, requestBuffer.toByteArray())));
|
||||
transport = session.getTransport(transportUri);
|
||||
transport.connect();
|
||||
requestMessage.saveChanges();
|
||||
transport.sendMessage(requestMessage, requestMessage.getAllRecipients());
|
||||
}
|
||||
catch (MessagingException ex) {
|
||||
throw new MailTransportException(ex);
|
||||
}
|
||||
finally {
|
||||
MailTransportUtils.closeService(transport);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Receiving
|
||||
*/
|
||||
|
||||
@Override
|
||||
protected void onReceiveBeforeRead() throws IOException {
|
||||
try {
|
||||
String requestMessageId = requestMessage.getMessageID();
|
||||
Assert.hasLength(requestMessageId, "No Message-ID found on request message [" + requestMessage + "]");
|
||||
try {
|
||||
Thread.sleep(receiveTimeout);
|
||||
}
|
||||
catch (InterruptedException e) {
|
||||
// Re-interrupt current thread, to allow other threads to react.
|
||||
Thread.currentThread().interrupt();
|
||||
}
|
||||
openFolder();
|
||||
SearchTerm searchTerm = new HeaderTerm(MailTransportConstants.HEADER_IN_REPLY_TO, requestMessageId);
|
||||
Message[] responses = folder.search(searchTerm);
|
||||
if (responses.length > 0) {
|
||||
if (responses.length > 1) {
|
||||
logger.warn("Received more than one response for request with ID [" + requestMessageId + "]");
|
||||
}
|
||||
responseMessage = responses[0];
|
||||
}
|
||||
if (deleteAfterReceive) {
|
||||
responseMessage.setFlag(Flags.Flag.DELETED, true);
|
||||
}
|
||||
}
|
||||
catch (MessagingException ex) {
|
||||
throw new MailTransportException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
private void openFolder() throws MessagingException {
|
||||
store = session.getStore(storeUri);
|
||||
store.connect();
|
||||
folder = store.getFolder(storeUri);
|
||||
if (folder == null || !folder.exists()) {
|
||||
throw new IllegalStateException("No default folder to receive from");
|
||||
}
|
||||
if (deleteAfterReceive) {
|
||||
folder.open(Folder.READ_WRITE);
|
||||
}
|
||||
else {
|
||||
folder.open(Folder.READ_ONLY);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean hasResponse() throws IOException {
|
||||
return responseMessage != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Iterator<String> getResponseHeaderNames() throws IOException {
|
||||
try {
|
||||
List<String> headers = new ArrayList<String>();
|
||||
Enumeration<?> enumeration = responseMessage.getAllHeaders();
|
||||
while (enumeration.hasMoreElements()) {
|
||||
Header header = (Header) enumeration.nextElement();
|
||||
headers.add(header.getName());
|
||||
}
|
||||
return headers.iterator();
|
||||
}
|
||||
catch (MessagingException ex) {
|
||||
throw new MailTransportException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Iterator<String> getResponseHeaders(String name) throws IOException {
|
||||
try {
|
||||
String[] headers = responseMessage.getHeader(name);
|
||||
return Arrays.asList(headers).iterator();
|
||||
}
|
||||
catch (MessagingException ex) {
|
||||
throw new MailTransportException(ex);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected InputStream getResponseInputStream() throws IOException {
|
||||
try {
|
||||
return responseMessage.getDataHandler().getInputStream();
|
||||
}
|
||||
catch (MessagingException ex) {
|
||||
throw new MailTransportException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean hasError() throws IOException {
|
||||
return false;
|
||||
}
|
||||
|
||||
public String getErrorMessage() throws IOException {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClose() throws IOException {
|
||||
MailTransportUtils.closeFolder(folder, deleteAfterReceive);
|
||||
MailTransportUtils.closeService(store);
|
||||
}
|
||||
|
||||
private class ByteArrayDataSource implements DataSource {
|
||||
|
||||
private byte[] data;
|
||||
|
||||
private String contentType;
|
||||
|
||||
public ByteArrayDataSource(String contentType, byte[] data) {
|
||||
this.data = data;
|
||||
this.contentType = contentType;
|
||||
}
|
||||
|
||||
public InputStream getInputStream() throws IOException {
|
||||
return new ByteArrayInputStream(data);
|
||||
}
|
||||
|
||||
public OutputStream getOutputStream() throws IOException {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
public String getContentType() {
|
||||
return contentType;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return "ByteArrayDataSource";
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* Copyright 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.ws.transport.mail;
|
||||
|
||||
import org.springframework.ws.transport.TransportConstants;
|
||||
|
||||
/**
|
||||
* Declares Mail-specific transport constants.
|
||||
*
|
||||
* @author Arjen Poutsma
|
||||
* @since 1.5.0
|
||||
*/
|
||||
public interface MailTransportConstants extends TransportConstants {
|
||||
|
||||
/**
|
||||
* The "mail" URI scheme.
|
||||
*/
|
||||
String MAIL_URI_SCHEME = "mailto";
|
||||
|
||||
/**
|
||||
* The "In-Reply-To" header.
|
||||
*/
|
||||
String HEADER_IN_REPLY_TO = "In-Reply-To";
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
* Copyright 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.ws.transport.mail;
|
||||
|
||||
import javax.mail.MessagingException;
|
||||
|
||||
import org.springframework.ws.transport.TransportException;
|
||||
|
||||
/**
|
||||
* Exception that is thrown when an error occurs in the Mail transport.
|
||||
*
|
||||
* @author Arjen Poutsma
|
||||
* @since 1.5.0
|
||||
*/
|
||||
public class MailTransportException extends TransportException {
|
||||
|
||||
private final MessagingException messagingException;
|
||||
|
||||
public MailTransportException(String msg, MessagingException ex) {
|
||||
super(msg + ": " + ex.getMessage());
|
||||
initCause(ex);
|
||||
messagingException = ex;
|
||||
}
|
||||
|
||||
public MailTransportException(MessagingException ex) {
|
||||
super(ex.getMessage());
|
||||
initCause(ex);
|
||||
messagingException = ex;
|
||||
}
|
||||
|
||||
public MessagingException getMessagingException() {
|
||||
return messagingException;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,164 @@
|
||||
/*
|
||||
* Copyright 2005-2010 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.ws.transport.mail.monitor;
|
||||
|
||||
import javax.mail.FetchProfile;
|
||||
import javax.mail.Flags;
|
||||
import javax.mail.Folder;
|
||||
import javax.mail.Message;
|
||||
import javax.mail.MessagingException;
|
||||
import javax.mail.search.AndTerm;
|
||||
import javax.mail.search.FlagTerm;
|
||||
import javax.mail.search.SearchTerm;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
/**
|
||||
* Abstract base class for the {@link MonitoringStrategy} interface. Exposes a {@link #setDeleteMessages(boolean)
|
||||
* deleteMessages} property, and includes a basic workflow for message monitoring.
|
||||
*
|
||||
* @author Arjen Poutsma
|
||||
* @since 1.5.0
|
||||
*/
|
||||
public abstract class AbstractMonitoringStrategy implements MonitoringStrategy {
|
||||
|
||||
/** Logger available to subclasses. */
|
||||
protected final Log logger = LogFactory.getLog(getClass());
|
||||
|
||||
private boolean deleteMessages = true;
|
||||
|
||||
/**
|
||||
* Sets whether messages should be marked as {@link javax.mail.Flags.Flag#DELETED DELETED} after they have been
|
||||
* read. Default is <code>true</code>.
|
||||
*/
|
||||
public void setDeleteMessages(boolean deleteMessages) {
|
||||
this.deleteMessages = deleteMessages;
|
||||
}
|
||||
|
||||
public int getFolderOpenMode() {
|
||||
return deleteMessages ? Folder.READ_WRITE : Folder.READ_ONLY;
|
||||
}
|
||||
|
||||
/**
|
||||
* Monitors the given folder, and returns any new messages when they arrive. This implementation calls {@link
|
||||
* #waitForNewMessages(Folder)}, then searches for new messages using {@link #searchForNewMessages(Folder)}, fetches
|
||||
* the messages using {@link #fetchMessages(Folder, Message[])}, and finally {@link #setDeleteMessages(boolean)
|
||||
* deletes} the messages, if {@link #setDeleteMessages(boolean) deleteMessages} is <code>true</code>.
|
||||
*
|
||||
* @param folder the folder to monitor
|
||||
* @return the new messages
|
||||
* @throws MessagingException in case of JavaMail errors
|
||||
* @throws InterruptedException when a thread is interrupted
|
||||
*/
|
||||
public final Message[] monitor(Folder folder) throws MessagingException, InterruptedException {
|
||||
waitForNewMessages(folder);
|
||||
Message[] messages = searchForNewMessages(folder);
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Found " + messages.length + " new messages");
|
||||
}
|
||||
if (messages.length > 0) {
|
||||
fetchMessages(folder, messages);
|
||||
}
|
||||
if (deleteMessages) {
|
||||
deleteMessages(folder, messages);
|
||||
}
|
||||
return messages;
|
||||
}
|
||||
|
||||
/**
|
||||
* Template method that blocks until new messages arrive in the given folder. Typical implementations use {@link
|
||||
* Thread#sleep(long)} or the IMAP IDLE command.
|
||||
*
|
||||
* @param folder the folder to monitor
|
||||
* @throws MessagingException in case of JavaMail errors
|
||||
* @throws InterruptedException when a thread is interrupted
|
||||
*/
|
||||
protected abstract void waitForNewMessages(Folder folder) throws MessagingException, InterruptedException;
|
||||
|
||||
/**
|
||||
* Retrieves new messages from the given folder. This implementation creates a {@link SearchTerm} that searches for
|
||||
* all messages in the folder that are {@link javax.mail.Flags.Flag#RECENT RECENT}, not {@link
|
||||
* javax.mail.Flags.Flag#ANSWERED ANSWERED}, and not {@link javax.mail.Flags.Flag#DELETED DELETED}. The search term
|
||||
* is used to {@link Folder#search(SearchTerm) search} for new messages.
|
||||
*
|
||||
* @param folder the folder to retrieve new messages from
|
||||
* @return the new messages
|
||||
* @throws MessagingException in case of JavaMail errors
|
||||
*/
|
||||
protected Message[] searchForNewMessages(Folder folder) throws MessagingException {
|
||||
if (!folder.isOpen()) {
|
||||
return new Message[0];
|
||||
}
|
||||
Flags supportedFlags = folder.getPermanentFlags();
|
||||
SearchTerm searchTerm = null;
|
||||
if (supportedFlags != null) {
|
||||
if (supportedFlags.contains(Flags.Flag.RECENT)) {
|
||||
searchTerm = new FlagTerm(new Flags(Flags.Flag.RECENT), true);
|
||||
}
|
||||
if (supportedFlags.contains(Flags.Flag.ANSWERED)) {
|
||||
FlagTerm answeredTerm = new FlagTerm(new Flags(Flags.Flag.ANSWERED), false);
|
||||
if (searchTerm == null) {
|
||||
searchTerm = answeredTerm;
|
||||
}
|
||||
else {
|
||||
searchTerm = new AndTerm(searchTerm, answeredTerm);
|
||||
}
|
||||
}
|
||||
if (supportedFlags.contains(Flags.Flag.DELETED)) {
|
||||
FlagTerm deletedTerm = new FlagTerm(new Flags(Flags.Flag.DELETED), false);
|
||||
if (searchTerm == null) {
|
||||
searchTerm = deletedTerm;
|
||||
}
|
||||
else {
|
||||
searchTerm = new AndTerm(searchTerm, deletedTerm);
|
||||
}
|
||||
}
|
||||
}
|
||||
return searchTerm != null ? folder.search(searchTerm) : folder.getMessages();
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetches the specified messages from the specified folder. Default implementation {@link Folder#fetch(Message[],
|
||||
* FetchProfile) fetches} every {@link javax.mail.FetchProfile.Item}.
|
||||
*
|
||||
* @param folder the folder to fetch messages from
|
||||
* @param messages the messages to fetch
|
||||
* @throws MessagingException in case of JavMail errors
|
||||
*/
|
||||
protected void fetchMessages(Folder folder, Message[] messages) throws MessagingException {
|
||||
FetchProfile contentsProfile = new FetchProfile();
|
||||
contentsProfile.add(FetchProfile.Item.ENVELOPE);
|
||||
contentsProfile.add(FetchProfile.Item.CONTENT_INFO);
|
||||
contentsProfile.add(FetchProfile.Item.FLAGS);
|
||||
folder.fetch(messages, contentsProfile);
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes the given messages from the given folder. Only invoked when {@link #setDeleteMessages(boolean)} is
|
||||
* <code>true</code>.
|
||||
*
|
||||
* @param folder the folder to delete messages from
|
||||
* @param messages the messages to delete
|
||||
* @throws MessagingException in case of JavaMail errors
|
||||
*/
|
||||
protected void deleteMessages(Folder folder, Message[] messages) throws MessagingException {
|
||||
for (Message message : messages) {
|
||||
message.setFlag(Flags.Flag.DELETED, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
/*
|
||||
* Copyright 2005-2010 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.ws.transport.mail.monitor;
|
||||
|
||||
import javax.mail.Folder;
|
||||
import javax.mail.Message;
|
||||
import javax.mail.MessagingException;
|
||||
import javax.mail.event.MessageCountAdapter;
|
||||
import javax.mail.event.MessageCountEvent;
|
||||
import javax.mail.event.MessageCountListener;
|
||||
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
import com.sun.mail.imap.IMAPFolder;
|
||||
|
||||
/**
|
||||
* Implementation of the {@link MonitoringStrategy} interface that uses the IMAP IDLE command for asynchronous message
|
||||
* detection.
|
||||
* <p/>
|
||||
* <b>Note</b> that this implementation is only suitable for use with IMAP servers which support the IDLE command.
|
||||
* Additionally, this strategy requires JavaMail version 1.4.1.
|
||||
*
|
||||
* @author Arjen Poutsma
|
||||
* @since 1.5.0
|
||||
*/
|
||||
public class ImapIdleMonitoringStrategy extends AbstractMonitoringStrategy {
|
||||
|
||||
private MessageCountListener messageCountListener;
|
||||
|
||||
@Override
|
||||
protected void waitForNewMessages(Folder folder) throws MessagingException, InterruptedException {
|
||||
Assert.isInstanceOf(IMAPFolder.class, folder);
|
||||
IMAPFolder imapFolder = (IMAPFolder) folder;
|
||||
// retrieve unseen messages before we enter the blocking idle call
|
||||
if (searchForNewMessages(folder).length > 0) {
|
||||
return;
|
||||
}
|
||||
if (messageCountListener == null) {
|
||||
createMessageCountListener();
|
||||
}
|
||||
folder.addMessageCountListener(messageCountListener);
|
||||
try {
|
||||
imapFolder.idle();
|
||||
}
|
||||
finally {
|
||||
folder.removeMessageCountListener(messageCountListener);
|
||||
}
|
||||
}
|
||||
|
||||
private void createMessageCountListener() {
|
||||
messageCountListener = new MessageCountAdapter() {
|
||||
@Override
|
||||
public void messagesAdded(MessageCountEvent e) {
|
||||
Message[] messages = e.getMessages();
|
||||
for (Message message : messages) {
|
||||
try {
|
||||
// this will return the flow to the idle call, above
|
||||
message.getLineCount();
|
||||
}
|
||||
catch (MessagingException ex) {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* Copyright 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.ws.transport.mail.monitor;
|
||||
|
||||
import javax.mail.Folder;
|
||||
import javax.mail.Message;
|
||||
import javax.mail.MessagingException;
|
||||
|
||||
/**
|
||||
* Defines the contract for objects that monitor a given folder for new messages. Allows for multiple implementation
|
||||
* strategies, including polling, or event-driven techniques such as IMAP's <code>IDLE</code> command.
|
||||
*
|
||||
* @author Arjen Poutsma
|
||||
*/
|
||||
public interface MonitoringStrategy {
|
||||
|
||||
/**
|
||||
* Monitors the given folder, and returns any new messages when they arrive.
|
||||
*
|
||||
* @param folder the folder in which to look for new messages
|
||||
* @return the new messages
|
||||
* @throws MessagingException in case of JavaMail errors
|
||||
* @throws InterruptedException if a thread is interrupted
|
||||
*/
|
||||
Message[] monitor(Folder folder) throws MessagingException, InterruptedException;
|
||||
|
||||
/**
|
||||
* Returns the folder open mode to be used by this strategy. Can be either {@link Folder#READ_ONLY} or {@link
|
||||
* Folder#READ_WRITE}.
|
||||
*/
|
||||
int getFolderOpenMode();
|
||||
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
/*
|
||||
* Copyright 2005-2010 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.ws.transport.mail.monitor;
|
||||
|
||||
import javax.mail.Folder;
|
||||
import javax.mail.MessagingException;
|
||||
|
||||
/**
|
||||
* Implementation of the {@link MonitoringStrategy} interface that uses a simple polling mechanism. Defines a {@link
|
||||
* #setPollingInterval(long) polling interval} property which defines the interval in between message polls.
|
||||
* <p/>
|
||||
* <b>Note</b> that this implementation is not suitable for use with POP3 servers. Use the {@link
|
||||
* Pop3PollingMonitoringStrategy} instead.
|
||||
*
|
||||
* @author Arjen Poutsma
|
||||
* @since 1.5.0
|
||||
*/
|
||||
public class PollingMonitoringStrategy extends AbstractMonitoringStrategy {
|
||||
|
||||
/** Defines the default polling frequency. Set to 1000 * 60 milliseconds (i.e. 1 minute). */
|
||||
public static final long DEFAULT_POLLING_FREQUENCY = 1000 * 60;
|
||||
|
||||
private long pollingInterval = DEFAULT_POLLING_FREQUENCY;
|
||||
|
||||
/**
|
||||
* Sets the interval used in between message polls, <strong>in milliseconds</strong>. The default is 1000 * 60 ms,
|
||||
* that is 1 minute.
|
||||
*/
|
||||
public void setPollingInterval(long pollingInterval) {
|
||||
this.pollingInterval = pollingInterval;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void waitForNewMessages(Folder folder) throws MessagingException, InterruptedException {
|
||||
Thread.sleep(pollingInterval);
|
||||
afterSleep(folder);
|
||||
}
|
||||
|
||||
/**
|
||||
* Invoked after the {@link Thread#sleep(long)} method has been invoked. This implementation calls {@link
|
||||
* Folder#getMessageCount()}, to force new messages to be seen.
|
||||
*
|
||||
* @param folder the folder to check for new messages
|
||||
* @throws MessagingException in case of JavaMail errors
|
||||
*/
|
||||
protected void afterSleep(Folder folder) throws MessagingException {
|
||||
folder.getMessageCount();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,82 @@
|
||||
/*
|
||||
* Copyright 2005-2010 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.ws.transport.mail.monitor;
|
||||
|
||||
import javax.mail.Folder;
|
||||
import javax.mail.Message;
|
||||
import javax.mail.MessagingException;
|
||||
import javax.mail.internet.MimeMessage;
|
||||
|
||||
import org.springframework.ws.transport.mail.support.MailTransportUtils;
|
||||
|
||||
/**
|
||||
* Implementation of the {@link MonitoringStrategy} interface that uses a simple polling mechanism suitable for POP3
|
||||
* servers. Since POP3 does not have a native mechanism to determine which messages are "new", this implementation
|
||||
* simply retrieves all messages in the {@link Folder}, and delete them afterwards. All messages in the POP3 mailbox are
|
||||
* therefore, by definition, new.
|
||||
* <p/>
|
||||
* Setting the {@link #setDeleteMessages(boolean) deleteMessages} property is therefore ignored: messages are always
|
||||
* deleted.
|
||||
*
|
||||
* @author Arjen Poutsma
|
||||
* @since 1.5.0
|
||||
*/
|
||||
public class Pop3PollingMonitoringStrategy extends PollingMonitoringStrategy {
|
||||
|
||||
public Pop3PollingMonitoringStrategy() {
|
||||
super.setDeleteMessages(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setDeleteMessages(boolean deleteMessages) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Re-opens the folder, if it closed.
|
||||
*/
|
||||
@Override
|
||||
protected void afterSleep(Folder folder) throws MessagingException {
|
||||
if (!folder.isOpen()) {
|
||||
folder.open(Folder.READ_WRITE);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Simply returns {@link Folder#getMessages()}.
|
||||
*/
|
||||
@Override
|
||||
protected Message[] searchForNewMessages(Folder folder) throws MessagingException {
|
||||
return folder.getMessages();
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes the given messages from the given folder, and closes it to expunge deleted messages.
|
||||
*
|
||||
* @param folder the folder to delete messages from
|
||||
* @param messages the messages to delete
|
||||
* @throws MessagingException in case of JavaMail errors
|
||||
*/
|
||||
@Override
|
||||
protected void deleteMessages(Folder folder, Message[] messages) throws MessagingException {
|
||||
super.deleteMessages(folder, messages);
|
||||
// expunge deleted mails, and make sure we've retrieved them before closing the folder
|
||||
for (Message message : messages) {
|
||||
new MimeMessage((MimeMessage) message);
|
||||
}
|
||||
MailTransportUtils.closeFolder(folder, true);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
<html>
|
||||
<body>
|
||||
Provides the MonitoringStrategy interface and implementations. Used for monitoring a JavaMail Folder for new email
|
||||
messages.
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,5 @@
|
||||
<html>
|
||||
<body>
|
||||
Package providing support for handling messages via email.
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,188 @@
|
||||
/*
|
||||
* Copyright 2005-2010 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.ws.transport.mail.support;
|
||||
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
import javax.mail.Folder;
|
||||
import javax.mail.MessagingException;
|
||||
import javax.mail.Service;
|
||||
import javax.mail.Store;
|
||||
import javax.mail.Transport;
|
||||
import javax.mail.URLName;
|
||||
import javax.mail.internet.AddressException;
|
||||
import javax.mail.internet.InternetAddress;
|
||||
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.ws.transport.mail.MailTransportConstants;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
/**
|
||||
* Collection of utility methods to work with Mail transports.
|
||||
*
|
||||
* @author Arjen Poutsma
|
||||
* @since 1.5.0
|
||||
*/
|
||||
public abstract class MailTransportUtils {
|
||||
|
||||
private static final Pattern TO_PATTERN = Pattern.compile("^([^\\?]+)");
|
||||
|
||||
private static final Pattern SUBJECT_PATTERN = Pattern.compile("subject=([^\\&]+)");
|
||||
|
||||
private static final Log logger = LogFactory.getLog(MailTransportUtils.class);
|
||||
|
||||
private MailTransportUtils() {
|
||||
}
|
||||
|
||||
public static InternetAddress getTo(URI uri) {
|
||||
Matcher matcher = TO_PATTERN.matcher(uri.getSchemeSpecificPart());
|
||||
if (matcher.find()) {
|
||||
for (int i = 1; i <= matcher.groupCount(); i++) {
|
||||
String group = matcher.group(i);
|
||||
if (group != null) {
|
||||
try {
|
||||
return new InternetAddress(group);
|
||||
}
|
||||
catch (AddressException e) {
|
||||
// try next group
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static String getSubject(URI uri) {
|
||||
Matcher matcher = SUBJECT_PATTERN.matcher(uri.getSchemeSpecificPart());
|
||||
if (matcher.find()) {
|
||||
return matcher.group(1);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Close the given JavaMail Service and ignore any thrown exception. This is useful for typical <code>finally</code>
|
||||
* blocks in manual JavaMail code.
|
||||
*
|
||||
* @param service the JavaMail Service to close (may be <code>null</code>)
|
||||
* @see Transport
|
||||
* @see Store
|
||||
*/
|
||||
public static void closeService(Service service) {
|
||||
if (service != null) {
|
||||
try {
|
||||
service.close();
|
||||
}
|
||||
catch (MessagingException ex) {
|
||||
logger.debug("Could not close JavaMail Service", ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Close the given JavaMail Folder and ignore any thrown exception. This is useful for typical <code>finally</code>
|
||||
* blocks in manual JavaMail code.
|
||||
*
|
||||
* @param folder the JavaMail Folder to close (may be <code>null</code>)
|
||||
*/
|
||||
|
||||
public static void closeFolder(Folder folder) {
|
||||
closeFolder(folder, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Close the given JavaMail Folder and ignore any thrown exception. This is useful for typical <code>finally</code>
|
||||
* blocks in manual JavaMail code.
|
||||
*
|
||||
* @param folder the JavaMail Folder to close (may be <code>null</code>)
|
||||
* @param expunge whether all deleted messages should be expunged from the folder
|
||||
*/
|
||||
public static void closeFolder(Folder folder, boolean expunge) {
|
||||
if (folder != null && folder.isOpen()) {
|
||||
try {
|
||||
folder.close(expunge);
|
||||
}
|
||||
catch (MessagingException ex) {
|
||||
logger.debug("Could not close JavaMail Folder", ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Returns a string representation of the given {@link URLName}, where the password has been protected. */
|
||||
public static String toPasswordProtectedString(URLName name) {
|
||||
String protocol = name.getProtocol();
|
||||
String username = name.getUsername();
|
||||
String password = name.getPassword();
|
||||
String host = name.getHost();
|
||||
int port = name.getPort();
|
||||
String file = name.getFile();
|
||||
String ref = name.getRef();
|
||||
StringBuilder tempURL = new StringBuilder();
|
||||
if (protocol != null) {
|
||||
tempURL.append(protocol).append(':');
|
||||
}
|
||||
|
||||
if (StringUtils.hasLength(username) || StringUtils.hasLength(host)) {
|
||||
tempURL.append("//");
|
||||
if (StringUtils.hasLength(username)) {
|
||||
tempURL.append(username);
|
||||
if (StringUtils.hasLength(password)) {
|
||||
tempURL.append(":*****");
|
||||
}
|
||||
tempURL.append("@");
|
||||
}
|
||||
if (StringUtils.hasLength(host)) {
|
||||
tempURL.append(host);
|
||||
}
|
||||
if (port != -1) {
|
||||
tempURL.append(':').append(Integer.toString(port));
|
||||
}
|
||||
if (StringUtils.hasLength(file)) {
|
||||
tempURL.append('/');
|
||||
}
|
||||
}
|
||||
if (StringUtils.hasLength(file)) {
|
||||
tempURL.append(file);
|
||||
}
|
||||
if (StringUtils.hasLength(ref)) {
|
||||
tempURL.append('#').append(ref);
|
||||
}
|
||||
return tempURL.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts the given internet address into a <code>mailto</code> URI.
|
||||
*
|
||||
* @param to the To: address
|
||||
* @param subject the subject, may be <code>null</code>
|
||||
* @return a mailto URI
|
||||
*/
|
||||
public static URI toUri(InternetAddress to, String subject) throws URISyntaxException {
|
||||
if (StringUtils.hasLength(subject)) {
|
||||
return new URI(MailTransportConstants.MAIL_URI_SCHEME, to.getAddress() + "?subject=" + subject, null);
|
||||
}
|
||||
else {
|
||||
return new URI(MailTransportConstants.MAIL_URI_SCHEME, to.getAddress(), null);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
<html>
|
||||
<body>
|
||||
Classes supporting the org.springframework.ws.transport.mail package.
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,84 @@
|
||||
/*
|
||||
* Copyright 2005-2010 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.ws.transport.support;
|
||||
|
||||
import org.springframework.beans.factory.BeanNameAware;
|
||||
import org.springframework.core.task.SimpleAsyncTaskExecutor;
|
||||
import org.springframework.core.task.TaskExecutor;
|
||||
import org.springframework.util.ClassUtils;
|
||||
|
||||
/**
|
||||
* Abstract base class for asynchronous standalone, server-side transport objects. Contains a Spring {@link
|
||||
* TaskExecutor}, and various lifecycle callbacks.
|
||||
*
|
||||
* @author Arjen Poutsma
|
||||
*/
|
||||
public abstract class AbstractAsyncStandaloneMessageReceiver extends AbstractStandaloneMessageReceiver
|
||||
implements BeanNameAware {
|
||||
|
||||
/** Default thread name prefix. */
|
||||
public final String DEFAULT_THREAD_NAME_PREFIX = ClassUtils.getShortName(getClass()) + "-";
|
||||
|
||||
private TaskExecutor taskExecutor;
|
||||
|
||||
private String beanName;
|
||||
|
||||
/**
|
||||
* Set the Spring {@link TaskExecutor} to use for running the listener threads. Default is {@link
|
||||
* SimpleAsyncTaskExecutor}, starting up a number of new threads.
|
||||
* <p/>
|
||||
* Specify an alternative task executor for integration with an existing thread pool, such as the {@link
|
||||
* org.springframework.scheduling.commonj.WorkManagerTaskExecutor} to integrate with WebSphere or WebLogic.
|
||||
*/
|
||||
public void setTaskExecutor(TaskExecutor taskExecutor) {
|
||||
this.taskExecutor = taskExecutor;
|
||||
}
|
||||
|
||||
public void setBeanName(String beanName) {
|
||||
this.beanName = beanName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
if (taskExecutor == null) {
|
||||
taskExecutor = createDefaultTaskExecutor();
|
||||
}
|
||||
super.afterPropertiesSet();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a default TaskExecutor. Called if no explicit TaskExecutor has been specified.
|
||||
* <p/>
|
||||
* The default implementation builds a {@link org.springframework.core.task.SimpleAsyncTaskExecutor} with the
|
||||
* specified bean name (or the class name, if no bean name specified) as thread name prefix.
|
||||
*
|
||||
* @see org.springframework.core.task.SimpleAsyncTaskExecutor#SimpleAsyncTaskExecutor(String)
|
||||
*/
|
||||
protected TaskExecutor createDefaultTaskExecutor() {
|
||||
String threadNamePrefix = beanName != null ? beanName + "-" : DEFAULT_THREAD_NAME_PREFIX;
|
||||
return new SimpleAsyncTaskExecutor(threadNamePrefix);
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes the given {@link Runnable} via this receiver's {@link TaskExecutor}.
|
||||
*
|
||||
* @see #setTaskExecutor(TaskExecutor)
|
||||
*/
|
||||
protected void execute(Runnable runnable) {
|
||||
taskExecutor.execute(runnable);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,128 @@
|
||||
/*
|
||||
* Copyright 2005-2010 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.ws.transport.support;
|
||||
|
||||
import org.springframework.beans.factory.DisposableBean;
|
||||
import org.springframework.context.Lifecycle;
|
||||
|
||||
/**
|
||||
* Abstract base class for standalone, server-side transport objects. Provides a basic, thread-safe implementation of
|
||||
* the {@link Lifecycle} interface, and various template methods to be implemented by concrete sub classes.
|
||||
*
|
||||
* @author Arjen Poutsma
|
||||
* @since 1.5.0
|
||||
*/
|
||||
public abstract class AbstractStandaloneMessageReceiver extends SimpleWebServiceMessageReceiverObjectSupport
|
||||
implements Lifecycle, DisposableBean {
|
||||
|
||||
private volatile boolean active = false;
|
||||
|
||||
private boolean autoStartup = true;
|
||||
|
||||
private boolean running = false;
|
||||
|
||||
private final Object lifecycleMonitor = new Object();
|
||||
|
||||
/** Return whether this server is currently active, that is, whether it has been set up but not shut down yet. */
|
||||
public final boolean isActive() {
|
||||
synchronized (lifecycleMonitor) {
|
||||
return active;
|
||||
}
|
||||
}
|
||||
|
||||
/** Return whether this server is currently running, that is, whether it has been started and not stopped yet. */
|
||||
public final boolean isRunning() {
|
||||
synchronized (lifecycleMonitor) {
|
||||
return running;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set whether to automatically start the receiver after initialization.
|
||||
* <p/>
|
||||
* Default is <code>true</code>; set this to <code>false</code> to allow for manual startup.
|
||||
*/
|
||||
public void setAutoStartup(boolean autoStartup) {
|
||||
this.autoStartup = autoStartup;
|
||||
}
|
||||
|
||||
/** Calls {@link #activate()} when the BeanFactory initializes the receiver instance. */
|
||||
@Override
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
activate();
|
||||
}
|
||||
|
||||
/** Calls {@link #shutdown()} when the BeanFactory destroys the receiver instance. */
|
||||
public void destroy() {
|
||||
shutdown();
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize this server. Starts the server if {@link #setAutoStartup(boolean) autoStartup} hasn't been turned
|
||||
* off.
|
||||
*/
|
||||
public final void activate() throws Exception {
|
||||
synchronized (lifecycleMonitor) {
|
||||
active = true;
|
||||
}
|
||||
onActivate();
|
||||
if (autoStartup) {
|
||||
start();
|
||||
}
|
||||
}
|
||||
|
||||
/** Start this server. */
|
||||
public final void start() {
|
||||
synchronized (lifecycleMonitor) {
|
||||
running = true;
|
||||
}
|
||||
onStart();
|
||||
}
|
||||
|
||||
/** Stop this server. */
|
||||
public final void stop() {
|
||||
synchronized (lifecycleMonitor) {
|
||||
running = false;
|
||||
}
|
||||
onStop();
|
||||
}
|
||||
|
||||
/** Shut down this server. */
|
||||
public final void shutdown() {
|
||||
synchronized (lifecycleMonitor) {
|
||||
running = false;
|
||||
active = false;
|
||||
}
|
||||
onShutdown();
|
||||
}
|
||||
|
||||
/**
|
||||
* Template method invoked when {@link #activate()} is invoked.
|
||||
*
|
||||
* @throws Exception in case of errors
|
||||
*/
|
||||
protected abstract void onActivate() throws Exception;
|
||||
|
||||
/** Template method invoked when {@link #start()} is invoked. */
|
||||
protected abstract void onStart();
|
||||
|
||||
/** Template method invoked when {@link #stop()} is invoked. */
|
||||
protected abstract void onStop();
|
||||
|
||||
/** Template method invoked when {@link #shutdown()} is invoked. */
|
||||
protected abstract void onShutdown();
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
/*
|
||||
* Copyright 2005-2010 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.ws.transport.support;
|
||||
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.ws.transport.WebServiceConnection;
|
||||
import org.springframework.ws.transport.WebServiceMessageReceiver;
|
||||
|
||||
/**
|
||||
* Base class for server-side transport objects which have a predefined {@link WebServiceMessageReceiver}.
|
||||
*
|
||||
* @author Arjen Poutsma
|
||||
* @see #handleConnection(WebServiceConnection)
|
||||
* @since 1.5.0
|
||||
*/
|
||||
public abstract class SimpleWebServiceMessageReceiverObjectSupport extends WebServiceMessageReceiverObjectSupport
|
||||
implements InitializingBean {
|
||||
|
||||
private WebServiceMessageReceiver messageReceiver;
|
||||
|
||||
/**
|
||||
* Returns the <code>WebServiceMessageReceiver</code> used by this listener.
|
||||
*/
|
||||
public WebServiceMessageReceiver getMessageReceiver() {
|
||||
return messageReceiver;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the <code>WebServiceMessageReceiver</code> used by this listener.
|
||||
*/
|
||||
public void setMessageReceiver(WebServiceMessageReceiver messageReceiver) {
|
||||
this.messageReceiver = messageReceiver;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
super.afterPropertiesSet();
|
||||
Assert.notNull(getMessageReceiver(), "messageReceiver must not be null");
|
||||
}
|
||||
|
||||
protected final void handleConnection(WebServiceConnection connection) throws Exception {
|
||||
handleConnection(connection, getMessageReceiver());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* Copyright 2005-2010 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.ws.transport.xmpp;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.FilterInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
import org.jivesoftware.smack.packet.Message;
|
||||
|
||||
/**
|
||||
* Input stream that wraps a {@link Message}.
|
||||
*
|
||||
* @author Gildas Cuisinier
|
||||
* @author Arjen Poutsma
|
||||
* @since 2.0
|
||||
*/
|
||||
class MessageInputStream extends FilterInputStream {
|
||||
|
||||
MessageInputStream(Message message, String encoding) throws IOException {
|
||||
super(createInputStream(message, encoding));
|
||||
}
|
||||
|
||||
private static InputStream createInputStream(Message message, String encoding) throws IOException {
|
||||
Assert.notNull(message, "'message' must not be null");
|
||||
Assert.notNull(encoding, "'encoding' must not be null");
|
||||
String text = message.getBody();
|
||||
byte[] contents = text != null ? text.getBytes(encoding) : new byte[0];
|
||||
return new ByteArrayInputStream(contents);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
* Copyright 2005-2010 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.ws.transport.xmpp;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.FilterOutputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
import org.jivesoftware.smack.packet.Message;
|
||||
|
||||
/**
|
||||
* Output stream that wraps a {@link Message}.
|
||||
*
|
||||
* @author Gildas Cuisinier
|
||||
* @author Arjen Poutsma
|
||||
* @since 2.0
|
||||
*/
|
||||
class MessageOutputStream extends FilterOutputStream {
|
||||
|
||||
private final Message message;
|
||||
|
||||
private final String encoding;
|
||||
|
||||
MessageOutputStream(Message message, String encoding) {
|
||||
super(new ByteArrayOutputStream());
|
||||
Assert.notNull(message, "'message' must not be null");
|
||||
Assert.notNull(encoding, "'encoding' must not be null");
|
||||
this.message = message;
|
||||
this.encoding = encoding;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void flush() throws IOException {
|
||||
super.flush();
|
||||
ByteArrayOutputStream bos = (ByteArrayOutputStream) out;
|
||||
String text = new String(bos.toByteArray(), encoding);
|
||||
message.setBody(text);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,113 @@
|
||||
/*
|
||||
* Copyright 2005-2010 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.ws.transport.xmpp;
|
||||
|
||||
import org.springframework.ws.transport.support.AbstractStandaloneMessageReceiver;
|
||||
|
||||
import org.jivesoftware.smack.PacketListener;
|
||||
import org.jivesoftware.smack.XMPPConnection;
|
||||
import org.jivesoftware.smack.XMPPException;
|
||||
import org.jivesoftware.smack.filter.PacketFilter;
|
||||
import org.jivesoftware.smack.filter.PacketTypeFilter;
|
||||
import org.jivesoftware.smack.packet.Message;
|
||||
import org.jivesoftware.smack.packet.Packet;
|
||||
|
||||
/**
|
||||
* Server-side component for receiving XMPP (Jabber) messages. Requires a {@linkplain #setConnection(XMPPConnection)
|
||||
* connection} to be set, in addition to the {@link #setMessageFactory(org.springframework.ws.WebServiceMessageFactory)
|
||||
* messageFactory} and {@link #setMessageReceiver(org.springframework.ws.transport.WebServiceMessageReceiver)
|
||||
* messageReceiver} required by the base class.
|
||||
*
|
||||
* @author Gildas Cuisinier
|
||||
* @author Arjen Poutsma
|
||||
* @see org.springframework.ws.transport.xmpp.support.XmppConnectionFactoryBean
|
||||
* @since 2.0
|
||||
*/
|
||||
public class XmppMessageReceiver extends AbstractStandaloneMessageReceiver {
|
||||
|
||||
/** Default encoding used to read from and write to {@link org.jivesoftware.smack.packet.Message} messages. */
|
||||
public static final String DEFAULT_MESSAGE_ENCODING = "UTF-8";
|
||||
|
||||
private XMPPConnection connection;
|
||||
|
||||
private WebServicePacketListener packetListener;
|
||||
|
||||
private String messageEncoding = DEFAULT_MESSAGE_ENCODING;
|
||||
|
||||
public XmppMessageReceiver() {
|
||||
}
|
||||
|
||||
/** Sets the {@code XMPPConnection} to use. Setting this property is required. */
|
||||
public void setConnection(XMPPConnection connection) {
|
||||
this.connection = connection;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onActivate() throws XMPPException {
|
||||
if (!connection.isConnected()) {
|
||||
connection.connect();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStart() {
|
||||
if (logger.isInfoEnabled()) {
|
||||
logger.info("Starting XMPP receiver [" + connection.getUser() + "]");
|
||||
}
|
||||
packetListener = new WebServicePacketListener();
|
||||
PacketFilter packetFilter = new PacketTypeFilter(Message.class);
|
||||
connection.addPacketListener(packetListener, packetFilter);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStop() {
|
||||
if (logger.isInfoEnabled()) {
|
||||
logger.info("Stopping XMPP receiver [" + connection.getUser() + "]");
|
||||
}
|
||||
connection.removePacketListener(packetListener);
|
||||
packetListener = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onShutdown() {
|
||||
if (logger.isInfoEnabled()) {
|
||||
logger.info("Shutting down XMPP receiver [" + connection.getUser() + "]");
|
||||
}
|
||||
if (connection.isConnected()) {
|
||||
connection.disconnect();
|
||||
}
|
||||
}
|
||||
|
||||
private class WebServicePacketListener implements PacketListener {
|
||||
|
||||
public void processPacket(Packet packet) {
|
||||
logger.info("Received " + packet);
|
||||
if (packet instanceof Message) {
|
||||
Message message = (Message) packet;
|
||||
try {
|
||||
XmppReceiverConnection wsConnection = new XmppReceiverConnection(connection, message);
|
||||
wsConnection.setMessageEncoding(messageEncoding);
|
||||
handleConnection(wsConnection);
|
||||
}
|
||||
catch (Exception ex) {
|
||||
logger.error(ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,98 @@
|
||||
/*
|
||||
* Copyright 2005-2010 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.ws.transport.xmpp;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.URI;
|
||||
import java.util.UUID;
|
||||
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.ws.transport.WebServiceConnection;
|
||||
import org.springframework.ws.transport.WebServiceMessageSender;
|
||||
import org.springframework.ws.transport.xmpp.support.XmppTransportUtils;
|
||||
|
||||
import org.jivesoftware.smack.XMPPConnection;
|
||||
|
||||
/**
|
||||
* {@link WebServiceMessageSender} implementation that uses XMPP {@link org.jivesoftware.smack.packet.Message}s.
|
||||
* Requires a {@link #setConnection(org.jivesoftware.smack.XMPPConnection) connection}to be set.
|
||||
* <p/>
|
||||
* This message sender supports URI's of the following format: <blockquote> <tt><b>xmpp:</b></tt><i>to</i> </blockquote>
|
||||
* The <i>to</i> represents a Jabber ID.
|
||||
*
|
||||
* @author Gildas Cuisinier
|
||||
* @author Arjen Poutsma
|
||||
* @since 2.0
|
||||
*/
|
||||
public class XmppMessageSender implements WebServiceMessageSender, InitializingBean {
|
||||
|
||||
/** Default timeout for receive operations: -1 indicates a blocking receive without timeout. */
|
||||
public static final long DEFAULT_RECEIVE_TIMEOUT = -1;
|
||||
|
||||
/** Default encoding used to read from and write to {@link org.jivesoftware.smack.packet.Message} messages. */
|
||||
public static final String DEFAULT_MESSAGE_ENCODING = "UTF-8";
|
||||
|
||||
private long receiveTimeout = DEFAULT_RECEIVE_TIMEOUT;
|
||||
|
||||
private String messageEncoding = DEFAULT_MESSAGE_ENCODING;
|
||||
|
||||
private XMPPConnection connection;
|
||||
|
||||
/** Sets the {@code XMPPConnection}. Setting this property is required. */
|
||||
public void setConnection(XMPPConnection connection) {
|
||||
this.connection = connection;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the timeout to use for receive calls. The default is -1, which means no timeout.
|
||||
*
|
||||
* @see org.jivesoftware.smack.PacketCollector#nextResult(long)
|
||||
*/
|
||||
public void setReceiveTimeout(long receiveTimeout) {
|
||||
this.receiveTimeout = receiveTimeout;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the encoding used to read from {@link org.jivesoftware.smack.packet.Message} object. Defaults to
|
||||
* <code>UTF-8</code>.
|
||||
*/
|
||||
public void setMessageEncoding(String messageEncoding) {
|
||||
this.messageEncoding = messageEncoding;
|
||||
}
|
||||
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
Assert.notNull(connection, "'connection' is required");
|
||||
}
|
||||
|
||||
public WebServiceConnection createConnection(URI uri) throws IOException {
|
||||
String to = XmppTransportUtils.getTo(uri);
|
||||
String thread = createThread();
|
||||
XmppSenderConnection connection = new XmppSenderConnection(this.connection, to, thread);
|
||||
connection.setReceiveTimeout(receiveTimeout);
|
||||
connection.setMessageEncoding(messageEncoding);
|
||||
return connection;
|
||||
}
|
||||
|
||||
public boolean supports(URI uri) {
|
||||
return uri.getScheme().equals(XmppTransportConstants.XMPP_URI_SCHEME);
|
||||
}
|
||||
|
||||
protected String createThread() {
|
||||
return UUID.randomUUID().toString();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,141 @@
|
||||
/*
|
||||
* Copyright 2005-2010 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.ws.transport.xmpp;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.util.Iterator;
|
||||
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.ws.WebServiceMessage;
|
||||
import org.springframework.ws.transport.AbstractReceiverConnection;
|
||||
import org.springframework.ws.transport.xmpp.support.XmppTransportUtils;
|
||||
|
||||
import org.jivesoftware.smack.XMPPConnection;
|
||||
import org.jivesoftware.smack.packet.Message;
|
||||
|
||||
/**
|
||||
* Implementation of {@link org.springframework.ws.transport.WebServiceConnection} that is used for server-side XMPP
|
||||
* access. Exposes a {@link Message} request and response message.
|
||||
*
|
||||
* @author Gildas Cuisinier
|
||||
* @author Arjen Poutsma
|
||||
* @since 2.0
|
||||
*/
|
||||
public class XmppReceiverConnection extends AbstractReceiverConnection {
|
||||
|
||||
private final XMPPConnection connection;
|
||||
|
||||
private final Message requestMessage;
|
||||
|
||||
private Message responseMessage;
|
||||
|
||||
private String messageEncoding;
|
||||
|
||||
public XmppReceiverConnection(XMPPConnection connection, Message requestMessage) {
|
||||
Assert.notNull(connection, "'connection' must not be null");
|
||||
Assert.notNull(requestMessage, "'requestMessage' must not be null");
|
||||
this.connection = connection;
|
||||
this.requestMessage = requestMessage;
|
||||
}
|
||||
|
||||
/** Returns the request message for this connection. */
|
||||
public Message getRequestMessage() {
|
||||
return requestMessage;
|
||||
}
|
||||
|
||||
/** Returns the response message, if any, for this connection. */
|
||||
public Message getResponseMessage() {
|
||||
return responseMessage;
|
||||
}
|
||||
|
||||
/*
|
||||
* Package-friendly setters
|
||||
*/
|
||||
|
||||
void setMessageEncoding(String messageEncoding) {
|
||||
this.messageEncoding = messageEncoding;
|
||||
}
|
||||
|
||||
/*
|
||||
* URI
|
||||
*/
|
||||
|
||||
public URI getUri() throws URISyntaxException {
|
||||
return XmppTransportUtils.toUri(requestMessage);
|
||||
}
|
||||
|
||||
/*
|
||||
* Errors
|
||||
*/
|
||||
|
||||
public boolean hasError() {
|
||||
return XmppTransportUtils.hasError(responseMessage);
|
||||
}
|
||||
|
||||
public String getErrorMessage() {
|
||||
return XmppTransportUtils.getErrorMessage(responseMessage);
|
||||
}
|
||||
|
||||
/*
|
||||
* Receiving
|
||||
*/
|
||||
|
||||
@Override
|
||||
protected Iterator<String> getRequestHeaderNames() throws IOException {
|
||||
return XmppTransportUtils.getHeaderNames(requestMessage);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Iterator<String> getRequestHeaders(String name) throws IOException {
|
||||
return XmppTransportUtils.getHeaders(requestMessage, name);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected InputStream getRequestInputStream() throws IOException {
|
||||
return new MessageInputStream(requestMessage, messageEncoding);
|
||||
}
|
||||
|
||||
/*
|
||||
* Sending
|
||||
*/
|
||||
|
||||
@Override
|
||||
protected void onSendBeforeWrite(WebServiceMessage message) throws IOException {
|
||||
responseMessage = new Message(requestMessage.getFrom(), Message.Type.chat);
|
||||
responseMessage.setFrom(connection.getUser());
|
||||
responseMessage.setThread(requestMessage.getThread());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void addResponseHeader(String name, String value) throws IOException {
|
||||
XmppTransportUtils.addHeader(responseMessage, name, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected OutputStream getResponseOutputStream() throws IOException {
|
||||
return new MessageOutputStream(responseMessage, messageEncoding);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onSendAfterWrite(WebServiceMessage message) throws IOException {
|
||||
connection.sendPacket(responseMessage);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,177 @@
|
||||
/*
|
||||
* Copyright 2005-2010 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.ws.transport.xmpp;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.util.Iterator;
|
||||
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.ws.WebServiceMessage;
|
||||
import org.springframework.ws.transport.AbstractSenderConnection;
|
||||
import org.springframework.ws.transport.xmpp.support.XmppTransportUtils;
|
||||
|
||||
import org.jivesoftware.smack.PacketCollector;
|
||||
import org.jivesoftware.smack.XMPPConnection;
|
||||
import org.jivesoftware.smack.filter.AndFilter;
|
||||
import org.jivesoftware.smack.filter.PacketFilter;
|
||||
import org.jivesoftware.smack.filter.PacketTypeFilter;
|
||||
import org.jivesoftware.smack.filter.ThreadFilter;
|
||||
import org.jivesoftware.smack.packet.Message;
|
||||
import org.jivesoftware.smack.packet.Packet;
|
||||
|
||||
/**
|
||||
* Implementation of {@link org.springframework.ws.transport.WebServiceConnection} that is used for client-side XMPP
|
||||
* access. Exposes a {@link Message} request and response message.
|
||||
*
|
||||
* @author Gildas Cuisinier
|
||||
* @author Arjen Poutsma
|
||||
* @since 2.0
|
||||
*/
|
||||
public class XmppSenderConnection extends AbstractSenderConnection {
|
||||
|
||||
private final Message requestMessage;
|
||||
|
||||
private final XMPPConnection connection;
|
||||
|
||||
private Message responseMessage;
|
||||
|
||||
private String messageEncoding;
|
||||
|
||||
private long receiveTimeout;
|
||||
|
||||
protected XmppSenderConnection(XMPPConnection connection, String to, String thread) {
|
||||
Assert.notNull(connection, "'connection' must not be null");
|
||||
Assert.hasLength(to, "'to' must not be empty");
|
||||
Assert.hasLength(thread, "'thread' must not be empty");
|
||||
this.connection = connection;
|
||||
this.requestMessage = new Message(to, Message.Type.chat);
|
||||
this.requestMessage.setThread(thread);
|
||||
}
|
||||
|
||||
/** Returns the request message for this connection. */
|
||||
public Message getRequestMessage() {
|
||||
return requestMessage;
|
||||
}
|
||||
|
||||
/** Returns the response message, if any, for this connection. */
|
||||
public Message getResponseMessage() {
|
||||
return responseMessage;
|
||||
}
|
||||
|
||||
/*
|
||||
* Package-friendly setters
|
||||
*/
|
||||
|
||||
void setMessageEncoding(String messageEncoding) {
|
||||
this.messageEncoding = messageEncoding;
|
||||
}
|
||||
|
||||
void setReceiveTimeout(long receiveTimeout) {
|
||||
this.receiveTimeout = receiveTimeout;
|
||||
}
|
||||
|
||||
/*
|
||||
* URI
|
||||
*/
|
||||
|
||||
public URI getUri() throws URISyntaxException {
|
||||
return XmppTransportUtils.toUri(requestMessage);
|
||||
}
|
||||
|
||||
/*
|
||||
* Errors
|
||||
*/
|
||||
|
||||
public boolean hasError() {
|
||||
return XmppTransportUtils.hasError(responseMessage);
|
||||
}
|
||||
|
||||
public String getErrorMessage() {
|
||||
return XmppTransportUtils.getErrorMessage(responseMessage);
|
||||
}
|
||||
|
||||
/*
|
||||
* Sending
|
||||
*/
|
||||
|
||||
@Override
|
||||
protected void addRequestHeader(String name, String value) {
|
||||
XmppTransportUtils.addHeader(requestMessage, name, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected OutputStream getRequestOutputStream() throws IOException {
|
||||
return new MessageOutputStream(requestMessage, messageEncoding);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onSendAfterWrite(WebServiceMessage message) throws IOException {
|
||||
requestMessage.setFrom(connection.getUser());
|
||||
connection.sendPacket(requestMessage);
|
||||
}
|
||||
|
||||
/*
|
||||
* Receiving
|
||||
*/
|
||||
|
||||
@Override
|
||||
protected void onReceiveBeforeRead() throws IOException {
|
||||
PacketFilter packetFilter = createPacketFilter();
|
||||
|
||||
PacketCollector collector = connection.createPacketCollector(packetFilter);
|
||||
Packet packet = receiveTimeout >= 0 ? collector.nextResult(receiveTimeout) : collector.nextResult();
|
||||
if (packet instanceof Message) {
|
||||
responseMessage = (Message) packet;
|
||||
}
|
||||
else if (packet != null) {
|
||||
throw new IllegalArgumentException(
|
||||
"Wrong packet type: [" + packet.getClass() + "]. Only Messages can be handled.");
|
||||
}
|
||||
}
|
||||
|
||||
private PacketFilter createPacketFilter() {
|
||||
AndFilter andFilter = new AndFilter();
|
||||
andFilter.addFilter(new PacketTypeFilter(Message.class));
|
||||
andFilter.addFilter(new ThreadFilter(requestMessage.getThread()));
|
||||
return andFilter;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean hasResponse() throws IOException {
|
||||
return responseMessage != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Iterator<String> getResponseHeaderNames() {
|
||||
return XmppTransportUtils.getHeaderNames(responseMessage);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Iterator<String> getResponseHeaders(String name) throws IOException {
|
||||
return XmppTransportUtils.getHeaders(responseMessage, name);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected InputStream getResponseInputStream() throws IOException {
|
||||
return new MessageInputStream(responseMessage, messageEncoding);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright 2005-2010 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.ws.transport.xmpp;
|
||||
|
||||
import org.springframework.ws.transport.TransportConstants;
|
||||
|
||||
/**
|
||||
* Declares XMPP-specific transport constants.
|
||||
*
|
||||
* @author Arjen Poutsma
|
||||
* @since 2.0
|
||||
*/
|
||||
public interface XmppTransportConstants extends TransportConstants {
|
||||
|
||||
/**
|
||||
* The "xmpp" URI scheme.
|
||||
*/
|
||||
String XMPP_URI_SCHEME = "xmpp";
|
||||
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
<html>
|
||||
<body>
|
||||
Package providing support for handling messages via xmpp.
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,136 @@
|
||||
/*
|
||||
* Copyright 2005-2010 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.ws.transport.xmpp.support;
|
||||
|
||||
import org.springframework.beans.factory.DisposableBean;
|
||||
import org.springframework.beans.factory.FactoryBean;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import org.jivesoftware.smack.ConnectionConfiguration;
|
||||
import org.jivesoftware.smack.XMPPConnection;
|
||||
import org.jivesoftware.smack.XMPPException;
|
||||
|
||||
/**
|
||||
* Factory to make {@link org.jivesoftware.smack.XMPPConnection} and perform connection and login on the XMPP server
|
||||
*
|
||||
* @author Gildas Cuisinier
|
||||
* @author Arjen Poutsma
|
||||
* @since 2.0
|
||||
*/
|
||||
public class XmppConnectionFactoryBean implements FactoryBean<XMPPConnection>, InitializingBean, DisposableBean {
|
||||
|
||||
private static final int DEFAULT_PORT = 5222;
|
||||
|
||||
private XMPPConnection connection;
|
||||
|
||||
private String host;
|
||||
|
||||
private int port = DEFAULT_PORT;
|
||||
|
||||
private String serviceName;
|
||||
|
||||
private String username;
|
||||
|
||||
private String password;
|
||||
|
||||
private String resource;
|
||||
|
||||
/** Sets the server host to connect to. */
|
||||
public void setHost(String host) {
|
||||
this.host = host;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the the server port to connect to.
|
||||
* <p/>
|
||||
* Defaults to {@code 5222}.
|
||||
*/
|
||||
public void setPort(int port) {
|
||||
Assert.isTrue(port > 0, "'port' must be larger than 0");
|
||||
this.port = port;
|
||||
}
|
||||
|
||||
/** Sets the service name to connect to. */
|
||||
public void setServiceName(String serviceName) {
|
||||
this.serviceName = serviceName;
|
||||
}
|
||||
|
||||
public void setUsername(String username) {
|
||||
this.username = username;
|
||||
}
|
||||
|
||||
public void setPassword(String password) {
|
||||
this.password = password;
|
||||
}
|
||||
|
||||
public void setResource(String resource) {
|
||||
this.resource = resource;
|
||||
}
|
||||
|
||||
public void afterPropertiesSet() throws XMPPException {
|
||||
ConnectionConfiguration configuration = createConnectionConfiguration(host, port, serviceName);
|
||||
Assert.notNull(configuration, "'configuration' must not be null");
|
||||
Assert.hasText(username, "'username' must not be empty");
|
||||
Assert.hasText(password, "'password' must not be empty");
|
||||
|
||||
connection = new XMPPConnection(configuration);
|
||||
connection.connect();
|
||||
if (StringUtils.hasText(resource)) {
|
||||
connection.login(username, password, resource);
|
||||
}
|
||||
else {
|
||||
connection.login(username, password);
|
||||
}
|
||||
}
|
||||
|
||||
public void destroy() {
|
||||
connection.disconnect();
|
||||
}
|
||||
|
||||
public XMPPConnection getObject() {
|
||||
return connection;
|
||||
}
|
||||
|
||||
public Class<XMPPConnection> getObjectType() {
|
||||
return XMPPConnection.class;
|
||||
}
|
||||
|
||||
public boolean isSingleton() {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the {@code ConnectionConfiguration} from the given parameters.
|
||||
*
|
||||
* @param host the host to connect to
|
||||
* @param port the port to connect to
|
||||
* @param serviceName the name of the service to connect to. May be {@code null}
|
||||
*/
|
||||
protected ConnectionConfiguration createConnectionConfiguration(String host, int port, String serviceName) {
|
||||
Assert.hasText(host, "'host' must not be empty");
|
||||
if (StringUtils.hasText(serviceName)) {
|
||||
return new ConnectionConfiguration(host, port, serviceName);
|
||||
}
|
||||
else {
|
||||
return new ConnectionConfiguration(host, port);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,84 @@
|
||||
/*
|
||||
* Copyright 2005-2010 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.ws.transport.xmpp.support;
|
||||
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.util.Collections;
|
||||
import java.util.Iterator;
|
||||
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.ws.transport.xmpp.XmppTransportConstants;
|
||||
|
||||
import org.jivesoftware.smack.packet.Message;
|
||||
|
||||
/**
|
||||
* Collection of utility methods to work with Mail transports.
|
||||
*
|
||||
* @author Arjen Poutsma
|
||||
* @since 2.0
|
||||
*/
|
||||
public abstract class XmppTransportUtils {
|
||||
|
||||
private XmppTransportUtils() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts the given XMPP destination into a <code>xmpp</code> URI.
|
||||
*/
|
||||
public static URI toUri(Message requestMessage) throws URISyntaxException {
|
||||
return new URI(XmppTransportConstants.XMPP_URI_SCHEME, requestMessage.getTo(), null);
|
||||
}
|
||||
|
||||
public static String getTo(URI uri) {
|
||||
return uri.getSchemeSpecificPart();
|
||||
}
|
||||
|
||||
public static boolean hasError(Message message) {
|
||||
return message != null && Message.Type.error.equals(message.getType());
|
||||
}
|
||||
|
||||
public static String getErrorMessage(Message message) {
|
||||
if (message == null || !Message.Type.error.equals(message.getType())) {
|
||||
return null;
|
||||
}
|
||||
else {
|
||||
return message.getBody();
|
||||
}
|
||||
}
|
||||
|
||||
public static void addHeader(Message message, String name, String value) {
|
||||
message.setProperty(name, value);
|
||||
}
|
||||
|
||||
public static Iterator<String> getHeaderNames(Message message) {
|
||||
Assert.notNull(message, "'message' must not be null");
|
||||
return message.getPropertyNames().iterator();
|
||||
}
|
||||
|
||||
public static Iterator<String> getHeaders(Message message, String name) {
|
||||
Assert.notNull(message, "'message' must not be null");
|
||||
String value = message.getProperty(name).toString();
|
||||
if (value != null) {
|
||||
return Collections.singletonList(value).iterator();
|
||||
}
|
||||
else {
|
||||
return Collections.<String>emptyList().iterator();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright 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.ws.transport;
|
||||
|
||||
import javax.xml.transform.Transformer;
|
||||
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.ws.context.MessageContext;
|
||||
import org.springframework.xml.transform.TransformerObjectSupport;
|
||||
|
||||
public class SimpleTestingMessageReceiver extends TransformerObjectSupport implements WebServiceMessageReceiver {
|
||||
|
||||
public void receive(MessageContext messageContext) throws Exception {
|
||||
Assert.notNull(messageContext, "MessageContext is null");
|
||||
logger.info("Received " + messageContext.getRequest());
|
||||
Transformer transformer = createTransformer();
|
||||
transformer.transform(messageContext.getRequest().getPayloadSource(),
|
||||
messageContext.getResponse().getPayloadResult());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* Copyright 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.ws.transport.http;
|
||||
|
||||
import java.util.Locale;
|
||||
|
||||
import org.springframework.ws.context.MessageContext;
|
||||
import org.springframework.ws.server.endpoint.MessageEndpoint;
|
||||
import org.springframework.ws.soap.SoapMessage;
|
||||
|
||||
public class FaultEndpoint implements MessageEndpoint {
|
||||
|
||||
public void invoke(MessageContext messageContext) throws Exception {
|
||||
SoapMessage response = (SoapMessage) messageContext.getResponse();
|
||||
response.getSoapBody().addServerOrReceiverFault("Something went wrong", Locale.ENGLISH);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
* Copyright 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.ws.transport.http;
|
||||
|
||||
import org.springframework.ws.context.MessageContext;
|
||||
import org.springframework.ws.server.endpoint.MessageEndpoint;
|
||||
|
||||
/** @author Arjen Poutsma */
|
||||
public class NoResponseEndpoint implements MessageEndpoint {
|
||||
|
||||
public void invoke(MessageContext messageContext) throws Exception {
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
* Copyright 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.ws.transport.http;
|
||||
|
||||
import org.springframework.ws.context.MessageContext;
|
||||
import org.springframework.ws.server.endpoint.MessageEndpoint;
|
||||
|
||||
/** @author Arjen Poutsma */
|
||||
public class ResponseEndpoint implements MessageEndpoint {
|
||||
|
||||
public void invoke(MessageContext messageContext) throws Exception {
|
||||
messageContext.getResponse();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,118 @@
|
||||
/*
|
||||
* Copyright 2005-2010 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.ws.transport.http;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.core.io.ClassPathResource;
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
import org.springframework.ws.transport.TransportConstants;
|
||||
|
||||
import org.apache.commons.httpclient.HttpClient;
|
||||
import org.apache.commons.httpclient.methods.GetMethod;
|
||||
import org.apache.commons.httpclient.methods.InputStreamRequestEntity;
|
||||
import org.apache.commons.httpclient.methods.PostMethod;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@ContextConfiguration("httpserver-applicationContext.xml")
|
||||
public class WebServiceHttpHandlerIntegrationTest {
|
||||
|
||||
private HttpClient client;
|
||||
|
||||
@Autowired
|
||||
private int port;
|
||||
|
||||
private String url;
|
||||
|
||||
@Before
|
||||
public void createHttpClient() throws Exception {
|
||||
client = new HttpClient();
|
||||
url = "http://localhost:" + port + "/service";
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testInvalidMethod() throws IOException {
|
||||
GetMethod getMethod = new GetMethod(url);
|
||||
client.executeMethod(getMethod);
|
||||
assertEquals("Invalid Response Code", HttpTransportConstants.STATUS_METHOD_NOT_ALLOWED,
|
||||
getMethod.getStatusCode());
|
||||
assertEquals("Response retrieved", 0, getMethod.getResponseContentLength());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNoResponse() throws IOException {
|
||||
PostMethod postMethod = new PostMethod(url);
|
||||
postMethod.addRequestHeader(HttpTransportConstants.HEADER_CONTENT_TYPE, "text/xml");
|
||||
postMethod.addRequestHeader(TransportConstants.HEADER_SOAP_ACTION,
|
||||
"http://springframework.org/spring-ws/NoResponse");
|
||||
Resource soapRequest = new ClassPathResource("soapRequest.xml", WebServiceHttpHandlerIntegrationTest.class);
|
||||
postMethod.setRequestEntity(new InputStreamRequestEntity(soapRequest.getInputStream()));
|
||||
client.executeMethod(postMethod);
|
||||
assertEquals("Invalid Response Code", HttpTransportConstants.STATUS_ACCEPTED, postMethod.getStatusCode());
|
||||
assertEquals("Response retrieved", 0, postMethod.getResponseContentLength());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testResponse() throws IOException {
|
||||
PostMethod postMethod = new PostMethod(url);
|
||||
postMethod.addRequestHeader(HttpTransportConstants.HEADER_CONTENT_TYPE, "text/xml");
|
||||
postMethod.addRequestHeader(TransportConstants.HEADER_SOAP_ACTION,
|
||||
"http://springframework.org/spring-ws/Response");
|
||||
Resource soapRequest = new ClassPathResource("soapRequest.xml", WebServiceHttpHandlerIntegrationTest.class);
|
||||
postMethod.setRequestEntity(new InputStreamRequestEntity(soapRequest.getInputStream()));
|
||||
client.executeMethod(postMethod);
|
||||
assertEquals("Invalid Response Code", HttpTransportConstants.STATUS_OK, postMethod.getStatusCode());
|
||||
assertTrue("No Response retrieved", postMethod.getResponseContentLength() > 0);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNoEndpoint() throws IOException {
|
||||
PostMethod postMethod = new PostMethod(url);
|
||||
postMethod.addRequestHeader(HttpTransportConstants.HEADER_CONTENT_TYPE, "text/xml");
|
||||
postMethod.addRequestHeader(TransportConstants.HEADER_SOAP_ACTION,
|
||||
"http://springframework.org/spring-ws/NoEndpoint");
|
||||
Resource soapRequest = new ClassPathResource("soapRequest.xml", WebServiceHttpHandlerIntegrationTest.class);
|
||||
postMethod.setRequestEntity(new InputStreamRequestEntity(soapRequest.getInputStream()));
|
||||
client.executeMethod(postMethod);
|
||||
assertEquals("Invalid Response Code", HttpTransportConstants.STATUS_NOT_FOUND, postMethod.getStatusCode());
|
||||
assertEquals("Response retrieved", 0, postMethod.getResponseContentLength());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFault() throws IOException {
|
||||
PostMethod postMethod = new PostMethod(url);
|
||||
postMethod.addRequestHeader(HttpTransportConstants.HEADER_CONTENT_TYPE, "text/xml");
|
||||
postMethod
|
||||
.addRequestHeader(TransportConstants.HEADER_SOAP_ACTION, "http://springframework.org/spring-ws/Fault");
|
||||
Resource soapRequest = new ClassPathResource("soapRequest.xml", WebServiceHttpHandlerIntegrationTest.class);
|
||||
postMethod.setRequestEntity(new InputStreamRequestEntity(soapRequest.getInputStream()));
|
||||
client.executeMethod(postMethod);
|
||||
assertEquals("Invalid Response Code", HttpTransportConstants.STATUS_INTERNAL_SERVER_ERROR,
|
||||
postMethod.getStatusCode());
|
||||
assertTrue("No Response retrieved", postMethod.getResponseContentLength() > 0);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
* Copyright 2005-2010 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.ws.transport.jms;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
import org.springframework.ws.client.core.WebServiceTemplate;
|
||||
import org.springframework.xml.transform.StringResult;
|
||||
import org.springframework.xml.transform.StringSource;
|
||||
|
||||
import org.custommonkey.xmlunit.XMLAssert;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@ContextConfiguration("jms-applicationContext.xml")
|
||||
public class JmsIntegrationTest {
|
||||
|
||||
@Autowired
|
||||
private WebServiceTemplate webServiceTemplate;
|
||||
|
||||
|
||||
public void setWebServiceTemplate(WebServiceTemplate webServiceTemplate) {
|
||||
this.webServiceTemplate = webServiceTemplate;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTemporaryQueue() throws Exception {
|
||||
String content = "<root xmlns='http://springframework.org/spring-ws'><child/></root>";
|
||||
StringResult result = new StringResult();
|
||||
webServiceTemplate.sendSourceAndReceiveToResult(new StringSource(content), result);
|
||||
XMLAssert.assertXMLEqual("Invalid content received", content, result.toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPermanentQueue() throws Exception {
|
||||
String url = "jms:RequestQueue?deliveryMode=NON_PERSISTENT;replyToName=ResponseQueue";
|
||||
String content = "<root xmlns='http://springframework.org/spring-ws'><child/></root>";
|
||||
StringResult result = new StringResult();
|
||||
webServiceTemplate.sendSourceAndReceiveToResult(url, new StringSource(content), result);
|
||||
XMLAssert.assertXMLEqual("Invalid content received", content, result.toString());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,237 @@
|
||||
/*
|
||||
* Copyright 2005-2012 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.ws.transport.jms;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.net.URI;
|
||||
import javax.jms.BytesMessage;
|
||||
import javax.jms.JMSException;
|
||||
import javax.jms.Message;
|
||||
import javax.jms.Session;
|
||||
import javax.jms.TextMessage;
|
||||
import javax.xml.soap.MessageFactory;
|
||||
import javax.xml.soap.SOAPConstants;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.jms.core.JmsTemplate;
|
||||
import org.springframework.jms.core.MessageCreator;
|
||||
import org.springframework.jms.core.MessagePostProcessor;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
import org.springframework.ws.soap.SoapMessage;
|
||||
import org.springframework.ws.soap.SoapVersion;
|
||||
import org.springframework.ws.soap.saaj.SaajSoapMessage;
|
||||
import org.springframework.ws.soap.saaj.SaajSoapMessageFactory;
|
||||
import org.springframework.ws.transport.WebServiceConnection;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@ContextConfiguration("jms-sender-applicationContext.xml")
|
||||
public class JmsMessageSenderIntegrationTest {
|
||||
|
||||
@Autowired
|
||||
private JmsMessageSender messageSender;
|
||||
|
||||
@Autowired
|
||||
private JmsTemplate jmsTemplate;
|
||||
|
||||
private MessageFactory messageFactory;
|
||||
|
||||
private static final String SOAP_ACTION = "\"http://springframework.org/DoIt\"";
|
||||
|
||||
@Before
|
||||
public void createMessageFactory() throws Exception {
|
||||
messageFactory = MessageFactory.newInstance(SOAPConstants.SOAP_1_1_PROTOCOL);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSendAndReceiveQueueBytesMessageTemporaryQueue() throws Exception {
|
||||
WebServiceConnection connection = null;
|
||||
try {
|
||||
URI uri = new URI("jms:SenderRequestQueue?deliveryMode=NON_PERSISTENT");
|
||||
connection = messageSender.createConnection(uri);
|
||||
SoapMessage soapRequest = new SaajSoapMessage(messageFactory.createMessage());
|
||||
soapRequest.setSoapAction(SOAP_ACTION);
|
||||
connection.send(soapRequest);
|
||||
|
||||
BytesMessage request = (BytesMessage) jmsTemplate.receive();
|
||||
assertNotNull("No message received", request);
|
||||
assertTrue("No message content received", request.readByte() != -1);
|
||||
ByteArrayOutputStream bos = new ByteArrayOutputStream();
|
||||
messageFactory.createMessage().writeTo(bos);
|
||||
final byte[] buf = bos.toByteArray();
|
||||
jmsTemplate.send(request.getJMSReplyTo(), new MessageCreator() {
|
||||
|
||||
public Message createMessage(Session session) throws JMSException {
|
||||
BytesMessage response = session.createBytesMessage();
|
||||
response.setStringProperty(JmsTransportConstants.PROPERTY_SOAP_ACTION, SOAP_ACTION);
|
||||
response.setStringProperty(JmsTransportConstants.PROPERTY_CONTENT_TYPE,
|
||||
SoapVersion.SOAP_11.getContentType());
|
||||
response.writeBytes(buf);
|
||||
return response;
|
||||
}
|
||||
});
|
||||
SoapMessage response = (SoapMessage) connection.receive(new SaajSoapMessageFactory(messageFactory));
|
||||
assertNotNull("No response received", response);
|
||||
assertEquals("Invalid SOAPAction", SOAP_ACTION, response.getSoapAction());
|
||||
assertFalse("Message is fault", response.hasFault());
|
||||
}
|
||||
finally {
|
||||
if (connection != null) {
|
||||
connection.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSendAndReceiveQueueBytesMessagePermanentQueue() throws Exception {
|
||||
WebServiceConnection connection = null;
|
||||
try {
|
||||
String responseQueueName = "SenderResponseQueue";
|
||||
URI uri = new URI(
|
||||
"jms:SenderRequestQueue?replyToName=" + responseQueueName + "&deliveryMode=NON_PERSISTENT");
|
||||
connection = messageSender.createConnection(uri);
|
||||
SoapMessage soapRequest = new SaajSoapMessage(messageFactory.createMessage());
|
||||
soapRequest.setSoapAction(SOAP_ACTION);
|
||||
connection.send(soapRequest);
|
||||
|
||||
final BytesMessage request = (BytesMessage) jmsTemplate.receive();
|
||||
assertNotNull("No message received", request);
|
||||
assertTrue("No message content received", request.readByte() != -1);
|
||||
ByteArrayOutputStream bos = new ByteArrayOutputStream();
|
||||
messageFactory.createMessage().writeTo(bos);
|
||||
final byte[] buf = bos.toByteArray();
|
||||
jmsTemplate.send(responseQueueName, new MessageCreator() {
|
||||
|
||||
public Message createMessage(Session session) throws JMSException {
|
||||
BytesMessage response = session.createBytesMessage();
|
||||
response.setJMSCorrelationID(request.getJMSMessageID());
|
||||
response.setStringProperty(JmsTransportConstants.PROPERTY_SOAP_ACTION, SOAP_ACTION);
|
||||
response.setStringProperty(JmsTransportConstants.PROPERTY_CONTENT_TYPE,
|
||||
SoapVersion.SOAP_11.getContentType());
|
||||
response.writeBytes(buf);
|
||||
return response;
|
||||
}
|
||||
});
|
||||
SoapMessage response = (SoapMessage) connection.receive(new SaajSoapMessageFactory(messageFactory));
|
||||
assertNotNull("No response received", response);
|
||||
assertEquals("Invalid SOAPAction", SOAP_ACTION, response.getSoapAction());
|
||||
assertFalse("Message is fault", response.hasFault());
|
||||
}
|
||||
finally {
|
||||
if (connection != null) {
|
||||
connection.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSendAndReceiveQueueTextMessage() throws Exception {
|
||||
WebServiceConnection connection = null;
|
||||
try {
|
||||
URI uri = new URI("jms:SenderRequestQueue?deliveryMode=NON_PERSISTENT&messageType=TEXT_MESSAGE");
|
||||
connection = messageSender.createConnection(uri);
|
||||
SoapMessage soapRequest = new SaajSoapMessage(messageFactory.createMessage());
|
||||
soapRequest.setSoapAction(SOAP_ACTION);
|
||||
connection.send(soapRequest);
|
||||
|
||||
TextMessage request = (TextMessage) jmsTemplate.receive();
|
||||
assertNotNull("No message received", request);
|
||||
assertNotNull("No message content received", request.getText());
|
||||
ByteArrayOutputStream bos = new ByteArrayOutputStream();
|
||||
messageFactory.createMessage().writeTo(bos);
|
||||
final String text = new String(bos.toByteArray(), "UTF-8");
|
||||
jmsTemplate.send(request.getJMSReplyTo(), new MessageCreator() {
|
||||
|
||||
public Message createMessage(Session session) throws JMSException {
|
||||
TextMessage response = session.createTextMessage();
|
||||
response.setStringProperty(JmsTransportConstants.PROPERTY_SOAP_ACTION, SOAP_ACTION);
|
||||
response.setStringProperty(JmsTransportConstants.PROPERTY_CONTENT_TYPE,
|
||||
SoapVersion.SOAP_11.getContentType());
|
||||
response.setText(text);
|
||||
return response;
|
||||
}
|
||||
});
|
||||
SoapMessage response = (SoapMessage) connection.receive(new SaajSoapMessageFactory(messageFactory));
|
||||
assertNotNull("No response received", response);
|
||||
assertEquals("Invalid SOAPAction", SOAP_ACTION, response.getSoapAction());
|
||||
assertFalse("Message is fault", response.hasFault());
|
||||
}
|
||||
finally {
|
||||
if (connection != null) {
|
||||
connection.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSendNoResponse() throws Exception {
|
||||
WebServiceConnection connection = null;
|
||||
try {
|
||||
URI uri = new URI("jms:SenderRequestQueue?deliveryMode=NON_PERSISTENT");
|
||||
connection = messageSender.createConnection(uri);
|
||||
SoapMessage soapRequest = new SaajSoapMessage(messageFactory.createMessage());
|
||||
soapRequest.setSoapAction(SOAP_ACTION);
|
||||
connection.send(soapRequest);
|
||||
|
||||
BytesMessage request = (BytesMessage) jmsTemplate.receive();
|
||||
assertNotNull("No message received", request);
|
||||
ByteArrayOutputStream bos = new ByteArrayOutputStream();
|
||||
messageFactory.createMessage().writeTo(bos);
|
||||
SoapMessage response = (SoapMessage) connection.receive(new SaajSoapMessageFactory(messageFactory));
|
||||
assertNull("Response received", response);
|
||||
}
|
||||
finally {
|
||||
if (connection != null) {
|
||||
connection.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPostProcessor() throws Exception {
|
||||
MessagePostProcessor processor = new MessagePostProcessor() {
|
||||
public Message postProcessMessage(Message message) throws JMSException {
|
||||
message.setBooleanProperty("processed", true);
|
||||
return message;
|
||||
}
|
||||
};
|
||||
JmsSenderConnection connection = null;
|
||||
try {
|
||||
URI uri = new URI("jms:SenderRequestQueue?deliveryMode=NON_PERSISTENT");
|
||||
connection = (JmsSenderConnection) messageSender.createConnection(uri);
|
||||
connection.setPostProcessor(processor);
|
||||
SoapMessage soapRequest = new SaajSoapMessage(messageFactory.createMessage());
|
||||
connection.send(soapRequest);
|
||||
|
||||
BytesMessage request = (BytesMessage) jmsTemplate.receive();
|
||||
assertNotNull("No message received", request);
|
||||
assertTrue("Message not processed", request.getBooleanProperty("processed"));
|
||||
}
|
||||
finally {
|
||||
if (connection != null) {
|
||||
connection.close();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,102 @@
|
||||
/*
|
||||
* Copyright 2005-2010 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.ws.transport.jms;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.jms.BytesMessage;
|
||||
import javax.jms.JMSException;
|
||||
import javax.jms.Message;
|
||||
import javax.jms.Queue;
|
||||
import javax.jms.Session;
|
||||
import javax.jms.TextMessage;
|
||||
import javax.jms.Topic;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.jms.core.JmsTemplate;
|
||||
import org.springframework.jms.core.MessageCreator;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@ContextConfiguration("jms-receiver-applicationContext.xml")
|
||||
public class WebServiceMessageListenerIntegrationTest {
|
||||
|
||||
private static final String CONTENT =
|
||||
"<SOAP-ENV:Envelope xmlns:SOAP-ENV='http://schemas.xmlsoap.org/soap/envelope/'>" + "<SOAP-ENV:Body>\n" +
|
||||
"<m:GetLastTradePrice xmlns:m='http://www.springframework.org/spring-ws'>\n" +
|
||||
"<symbol>DIS</symbol>\n" + "</m:GetLastTradePrice>\n" + "</SOAP-ENV:Body></SOAP-ENV:Envelope>";
|
||||
|
||||
@Autowired
|
||||
private JmsTemplate jmsTemplate;
|
||||
|
||||
@Resource
|
||||
private Queue responseQueue;
|
||||
|
||||
@Resource
|
||||
private Queue requestQueue;
|
||||
|
||||
@Autowired
|
||||
private Topic requestTopic;
|
||||
|
||||
|
||||
@Test
|
||||
public void testReceiveQueueBytesMessage() throws Exception {
|
||||
final byte[] b = CONTENT.getBytes("UTF-8");
|
||||
jmsTemplate.send(requestQueue, new MessageCreator() {
|
||||
public Message createMessage(Session session) throws JMSException {
|
||||
BytesMessage request = session.createBytesMessage();
|
||||
request.setJMSReplyTo(responseQueue);
|
||||
request.writeBytes(b);
|
||||
return request;
|
||||
}
|
||||
});
|
||||
BytesMessage response = (BytesMessage) jmsTemplate.receive(responseQueue);
|
||||
assertNotNull("No response received", response);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testReceiveQueueTextMessage() throws Exception {
|
||||
jmsTemplate.send(requestQueue, new MessageCreator() {
|
||||
public Message createMessage(Session session) throws JMSException {
|
||||
TextMessage request = session.createTextMessage(CONTENT);
|
||||
request.setJMSReplyTo(responseQueue);
|
||||
return request;
|
||||
}
|
||||
});
|
||||
TextMessage response = (TextMessage) jmsTemplate.receive(responseQueue);
|
||||
assertNotNull("No response received", response);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testReceiveTopic() throws Exception {
|
||||
final byte[] b = CONTENT.getBytes("UTF-8");
|
||||
jmsTemplate.send(requestTopic, new MessageCreator() {
|
||||
public Message createMessage(Session session) throws JMSException {
|
||||
BytesMessage request = session.createBytesMessage();
|
||||
request.writeBytes(b);
|
||||
return request;
|
||||
}
|
||||
});
|
||||
Thread.sleep(100);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,115 @@
|
||||
/*
|
||||
* Copyright 2005-2012 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.ws.transport.jms.support;
|
||||
|
||||
import java.net.URI;
|
||||
import javax.jms.DeliveryMode;
|
||||
import javax.jms.Message;
|
||||
|
||||
import org.springframework.ws.transport.jms.JmsTransportConstants;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
public class JmsTransportUtilsTest {
|
||||
|
||||
@Test
|
||||
public void getDestinationName() throws Exception {
|
||||
URI uri = new URI("jms:RequestQueue?replyToName=RESP_QUEUE");
|
||||
String destinationName = JmsTransportUtils.getDestinationName(uri);
|
||||
assertEquals("Invalid destination", "RequestQueue", destinationName);
|
||||
|
||||
uri = new URI("jms:RequestQueue");
|
||||
destinationName = JmsTransportUtils.getDestinationName(uri);
|
||||
assertEquals("Invalid destination", "RequestQueue", destinationName);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getDeliveryMode() throws Exception {
|
||||
URI uri = new URI("jms:RequestQueue?deliveryMode=NON_PERSISTENT");
|
||||
int deliveryMode = JmsTransportUtils.getDeliveryMode(uri);
|
||||
assertEquals("Invalid deliveryMode", DeliveryMode.NON_PERSISTENT, deliveryMode);
|
||||
|
||||
uri = new URI("jms:RequestQueue?deliveryMode=PERSISTENT");
|
||||
deliveryMode = JmsTransportUtils.getDeliveryMode(uri);
|
||||
assertEquals("Invalid deliveryMode", DeliveryMode.PERSISTENT, deliveryMode);
|
||||
|
||||
uri = new URI("jms:RequestQueue?replyToName=RESP_QUEUE");
|
||||
deliveryMode = JmsTransportUtils.getDeliveryMode(uri);
|
||||
assertEquals("Invalid deliveryMode", Message.DEFAULT_DELIVERY_MODE, deliveryMode);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getMessageType() throws Exception {
|
||||
URI uri = new URI("jms:RequestQueue?messageType=BYTESMESSAGE");
|
||||
int messageType = JmsTransportUtils.getMessageType(uri);
|
||||
assertEquals("Invalid messageType", JmsTransportConstants.BYTES_MESSAGE_TYPE, messageType);
|
||||
|
||||
uri = new URI("jms:RequestQueue?messageType=TEXT_MESSAGE");
|
||||
messageType = JmsTransportUtils.getMessageType(uri);
|
||||
assertEquals("Invalid messageType", JmsTransportConstants.TEXT_MESSAGE_TYPE, messageType);
|
||||
|
||||
uri = new URI("jms:RequestQueue?replyToName=RESP_QUEUE");
|
||||
messageType = JmsTransportUtils.getMessageType(uri);
|
||||
assertEquals("Invalid messageType", JmsTransportConstants.BYTES_MESSAGE_TYPE, messageType);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getTimeToLive() throws Exception {
|
||||
URI uri = new URI("jms:RequestQueue?timeToLive=100");
|
||||
long timeToLive = JmsTransportUtils.getTimeToLive(uri);
|
||||
assertEquals("Invalid timeToLive", 100, timeToLive);
|
||||
|
||||
uri = new URI("jms:RequestQueue?replyToName=RESP_QUEUE");
|
||||
timeToLive = JmsTransportUtils.getTimeToLive(uri);
|
||||
assertEquals("Invalid timeToLive", Message.DEFAULT_TIME_TO_LIVE, timeToLive);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getPriority() throws Exception {
|
||||
URI uri = new URI("jms:RequestQueue?priority=5");
|
||||
int priority = JmsTransportUtils.getPriority(uri);
|
||||
assertEquals("Invalid priority", 5, priority);
|
||||
|
||||
uri = new URI("jms:RequestQueue?replyToName=RESP_QUEUE");
|
||||
priority = JmsTransportUtils.getPriority(uri);
|
||||
assertEquals("Invalid priority", Message.DEFAULT_PRIORITY, priority);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getReplyToName() throws Exception {
|
||||
URI uri = new URI("jms:RequestQueue?replyToName=RESP_QUEUE");
|
||||
String replyToName = JmsTransportUtils.getReplyToName(uri);
|
||||
assertEquals("Invalid replyToName", "RESP_QUEUE", replyToName);
|
||||
|
||||
uri = new URI("jms:RequestQueue?priority=5");
|
||||
replyToName = JmsTransportUtils.getReplyToName(uri);
|
||||
Assert.assertNull("Invalid replyToName", replyToName);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void jndi() throws Exception {
|
||||
URI uri = new URI("jms:jms/REQUEST_QUEUE?replyToName=jms/REPLY_QUEUE");
|
||||
String destination = JmsTransportUtils.getDestinationName(uri);
|
||||
assertEquals("Invalid destination name", "jms/REQUEST_QUEUE", destination);
|
||||
|
||||
String replyTo = JmsTransportUtils.getReplyToName(uri);
|
||||
assertEquals("Invalid reply to name", "jms/REPLY_QUEUE", replyTo);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
* Copyright 2005-2010 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.ws.transport.mail;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.support.GenericApplicationContext;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
import org.springframework.ws.client.core.WebServiceTemplate;
|
||||
import org.springframework.xml.transform.StringResult;
|
||||
import org.springframework.xml.transform.StringSource;
|
||||
|
||||
import org.custommonkey.xmlunit.XMLAssert;
|
||||
import org.junit.After;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.jvnet.mock_javamail.Mailbox;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@ContextConfiguration("mail-applicationContext.xml")
|
||||
public class MailIntegrationTest {
|
||||
|
||||
@Autowired
|
||||
private WebServiceTemplate webServiceTemplate;
|
||||
|
||||
@Autowired
|
||||
private GenericApplicationContext applicationContext;
|
||||
|
||||
@After
|
||||
public void clearMailbox() throws Exception {
|
||||
Mailbox.clearAll();
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testMailTransport() throws Exception {
|
||||
String content = "<root xmlns='http://springframework.org/spring-ws'><child/></root>";
|
||||
StringResult result = new StringResult();
|
||||
webServiceTemplate.sendSourceAndReceiveToResult(new StringSource(content), result);
|
||||
applicationContext.close();
|
||||
assertEquals("Server mail message not deleted", 0, Mailbox.get("server@example.com").size());
|
||||
assertEquals("No client mail message received", 1, Mailbox.get("client@example.com").size());
|
||||
XMLAssert.assertXMLEqual("Invalid content received", content, result.toString());
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
/*
|
||||
* Copyright 2005-2010 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.ws.transport.mail;
|
||||
|
||||
import java.net.URI;
|
||||
import javax.xml.namespace.QName;
|
||||
import javax.xml.soap.MessageFactory;
|
||||
import javax.xml.soap.SOAPConstants;
|
||||
import javax.xml.soap.SOAPMessage;
|
||||
|
||||
import org.springframework.ws.soap.SoapMessage;
|
||||
import org.springframework.ws.soap.saaj.SaajSoapMessage;
|
||||
import org.springframework.ws.transport.WebServiceConnection;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.jvnet.mock_javamail.Mailbox;
|
||||
|
||||
public class MailMessageSenderIntegrationTest {
|
||||
|
||||
private MailMessageSender messageSender;
|
||||
|
||||
private MessageFactory messageFactory;
|
||||
|
||||
private static final String SOAP_ACTION = "http://springframework.org/DoIt";
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
messageSender = new MailMessageSender();
|
||||
messageSender.setFrom("Spring-WS SOAP Client <client@example.com>");
|
||||
messageSender.setTransportUri("smtp://smtp.example.com");
|
||||
messageSender.setStoreUri("imap://imap.example.com/INBOX");
|
||||
messageFactory = MessageFactory.newInstance(SOAPConstants.SOAP_1_1_PROTOCOL);
|
||||
messageSender.afterPropertiesSet();
|
||||
}
|
||||
|
||||
@After
|
||||
public void tearDown() throws Exception {
|
||||
Mailbox.clearAll();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSendAndReceiveQueueNoResponse() throws Exception {
|
||||
WebServiceConnection connection = null;
|
||||
try {
|
||||
URI mailTo = new URI("mailto:server@example.com?subject=SOAP%20Test");
|
||||
connection = messageSender.createConnection(mailTo);
|
||||
SOAPMessage saajMessage = messageFactory.createMessage();
|
||||
saajMessage.getSOAPBody().addBodyElement(new QName("http://springframework.org", "test"));
|
||||
SoapMessage soapRequest = new SaajSoapMessage(saajMessage);
|
||||
soapRequest.setSoapAction(SOAP_ACTION);
|
||||
connection.send(soapRequest);
|
||||
Assert.assertEquals("No mail message sent", 1, Mailbox.get("server@example.com").size());
|
||||
}
|
||||
finally {
|
||||
if (connection != null) {
|
||||
connection.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* Copyright 2005-2010 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.ws.transport.mail.support;
|
||||
|
||||
import java.net.URI;
|
||||
import javax.mail.URLName;
|
||||
import javax.mail.internet.InternetAddress;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
public class MailTransportUtilsTest {
|
||||
|
||||
@Test
|
||||
public void testToPasswordProtectedString() throws Exception {
|
||||
URLName name = new URLName("imap://john:secret@imap.example.com/INBOX");
|
||||
String result = MailTransportUtils.toPasswordProtectedString(name);
|
||||
Assert.assertEquals("Password found in string", -1, result.indexOf("secret"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetTo() throws Exception {
|
||||
URI uri = new URI("mailto:infobot@example.com?subject=current-issue");
|
||||
InternetAddress to = MailTransportUtils.getTo(uri);
|
||||
Assert.assertEquals("Invalid destination", new InternetAddress("infobot@example.com"), to);
|
||||
|
||||
uri = new URI("mailto:infobot@example.com");
|
||||
to = MailTransportUtils.getTo(uri);
|
||||
Assert.assertEquals("Invalid destination", new InternetAddress("infobot@example.com"), to);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetSubject() throws Exception {
|
||||
URI uri = new URI("mailto:infobot@example.com?subject=current-issue");
|
||||
String subject = MailTransportUtils.getSubject(uri);
|
||||
Assert.assertEquals("Invalid destination", "current-issue", subject);
|
||||
|
||||
uri = new URI("mailto:infobot@example.com");
|
||||
subject = MailTransportUtils.getSubject(uri);
|
||||
Assert.assertNull("Invalid destination", subject);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
* Copyright 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.ws.transport.support;
|
||||
|
||||
import javax.xml.transform.Source;
|
||||
|
||||
import org.springframework.ws.server.endpoint.PayloadEndpoint;
|
||||
|
||||
public class EchoPayloadEndpoint implements PayloadEndpoint {
|
||||
|
||||
public Source invoke(Source request) throws Exception {
|
||||
return request;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,99 @@
|
||||
/*
|
||||
* Copyright 2005-2011 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.ws.transport.support;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.ServerSocket;
|
||||
import java.util.Random;
|
||||
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Utility class that finds free BSD ports for use in testing scenario's.
|
||||
*
|
||||
* @author Ben Hale
|
||||
* @author Arjen Poutsma
|
||||
*/
|
||||
public abstract class FreePortScanner {
|
||||
|
||||
private static final int MIN_SAFE_PORT = 1024;
|
||||
|
||||
private static final int MAX_PORT = 65535;
|
||||
|
||||
private static final Random random = new Random();
|
||||
|
||||
/**
|
||||
* Returns the number of a free port in the default range.
|
||||
*/
|
||||
public static int getFreePort() {
|
||||
return getFreePort(MIN_SAFE_PORT, MAX_PORT);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the number of a free port in the given range.
|
||||
*/
|
||||
public static int getFreePort(int minPort, int maxPort) {
|
||||
Assert.isTrue(minPort > 0, "'minPort' must be larger than 0");
|
||||
Assert.isTrue(maxPort > minPort, "'maxPort' must be larger than minPort");
|
||||
int portRange = maxPort - minPort;
|
||||
int candidatePort;
|
||||
int searchCounter = 0;
|
||||
do {
|
||||
if (++searchCounter > portRange) {
|
||||
throw new IllegalStateException(
|
||||
String.format("There were no ports available in the range %d to %d", minPort, maxPort));
|
||||
}
|
||||
candidatePort = getRandomPort(minPort, portRange);
|
||||
}
|
||||
while (!isPortAvailable(candidatePort));
|
||||
|
||||
return candidatePort;
|
||||
}
|
||||
|
||||
private static int getRandomPort(int minPort, int portRange) {
|
||||
return minPort + random.nextInt(portRange);
|
||||
}
|
||||
|
||||
private static boolean isPortAvailable(int port) {
|
||||
ServerSocket serverSocket;
|
||||
try {
|
||||
serverSocket = new ServerSocket();
|
||||
}
|
||||
catch (IOException ex) {
|
||||
throw new IllegalStateException("Unable to create ServerSocket.", ex);
|
||||
}
|
||||
|
||||
try {
|
||||
InetSocketAddress sa = new InetSocketAddress(port);
|
||||
serverSocket.bind(sa);
|
||||
return true;
|
||||
}
|
||||
catch (IOException ex) {
|
||||
return false;
|
||||
}
|
||||
finally {
|
||||
try {
|
||||
serverSocket.close();
|
||||
}
|
||||
catch (IOException ex) {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
* Copyright 2005-2010 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.ws.transport.xmpp.support;
|
||||
|
||||
import org.jivesoftware.smack.XMPPException;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
/** @author Arjen Poutsma */
|
||||
public class XmppConnectionFactoryBeanTest {
|
||||
|
||||
private XmppConnectionFactoryBean factoryBean;
|
||||
|
||||
@Before
|
||||
public void createFactoryBean() {
|
||||
factoryBean = new XmppConnectionFactoryBean();
|
||||
}
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void noHost() throws XMPPException {
|
||||
factoryBean.afterPropertiesSet();
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void noUsername() throws XMPPException {
|
||||
factoryBean.setHost("jabber.org");
|
||||
factoryBean.afterPropertiesSet();
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void wrongPort() throws XMPPException {
|
||||
factoryBean.setPort(-10);
|
||||
}
|
||||
|
||||
}
|
||||
6
spring-ws-support/src/test/resources/log4j.properties
Normal file
6
spring-ws-support/src/test/resources/log4j.properties
Normal file
@@ -0,0 +1,6 @@
|
||||
log4j.rootCategory=WARN, stdout
|
||||
log4j.logger.org.springframework.ws=DEBUG
|
||||
|
||||
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
|
||||
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
|
||||
log4j.appender.stdout.layout.ConversionPattern=%d %p [%c] - <%m>%n
|
||||
@@ -0,0 +1,51 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd">
|
||||
|
||||
<bean id="port" class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
|
||||
<property name="targetClass" value="org.springframework.ws.transport.support.FreePortScanner"/>
|
||||
<property name="targetMethod" value="getFreePort"/>
|
||||
</bean>
|
||||
|
||||
<bean id="httpServer" class="org.springframework.remoting.support.SimpleHttpServerFactoryBean">
|
||||
<property name="port" ref="port"/>
|
||||
<property name="contexts">
|
||||
<map>
|
||||
<entry key="/service" value-ref="webServiceHandler"/>
|
||||
</map>
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
<bean id="webServiceHandler" class="org.springframework.ws.transport.http.WebServiceMessageReceiverHttpHandler">
|
||||
<property name="chunkedEncoding" value="true"/>
|
||||
<property name="messageFactory" ref="messageFactory"/>
|
||||
<property name="messageReceiver" ref="messageDispatcher"/>
|
||||
</bean>
|
||||
|
||||
<bean id="messageFactory" class="org.springframework.ws.soap.saaj.SaajSoapMessageFactory"/>
|
||||
|
||||
<bean id="messageDispatcher" class="org.springframework.ws.soap.server.SoapMessageDispatcher">
|
||||
<property name="endpointMappings" ref="payloadMapping"/>
|
||||
</bean>
|
||||
|
||||
<bean id="payloadMapping" class="org.springframework.ws.soap.server.endpoint.mapping.SoapActionEndpointMapping">
|
||||
<property name="mappings">
|
||||
<props>
|
||||
<prop key="http://springframework.org/spring-ws/NoResponse">noResponseEndpoint</prop>
|
||||
<prop key="http://springframework.org/spring-ws/Response">responseEndpoint</prop>
|
||||
<prop key="http://springframework.org/spring-ws/Fault">faultEndpoint</prop>
|
||||
</props>
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
<bean id="noResponseEndpoint"
|
||||
class="org.springframework.ws.transport.http.NoResponseEndpoint"/>
|
||||
|
||||
<bean id="responseEndpoint"
|
||||
class="org.springframework.ws.transport.http.ResponseEndpoint"/>
|
||||
|
||||
<bean id="faultEndpoint"
|
||||
class="org.springframework.ws.transport.http.FaultEndpoint"/>
|
||||
|
||||
|
||||
</beans>
|
||||
@@ -0,0 +1,7 @@
|
||||
<SOAP-ENV:Envelope xmlns:SOAP-ENV='http://schemas.xmlsoap.org/soap/envelope/'>
|
||||
<SOAP-ENV:Body>
|
||||
<m:GetLastTradePrice xmlns:m='http://www.springframework.org/spring-ws'>
|
||||
<symbol>DIS</symbol>
|
||||
</m:GetLastTradePrice>
|
||||
</SOAP-ENV:Body>
|
||||
</SOAP-ENV:Envelope>
|
||||
@@ -0,0 +1,42 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd">
|
||||
|
||||
<bean id="connectionFactory" class="org.apache.activemq.ActiveMQConnectionFactory">
|
||||
<property name="brokerURL" value="vm://localhost?broker.persistent=false"/>
|
||||
</bean>
|
||||
|
||||
<bean id="messageFactory" class="org.springframework.ws.soap.saaj.SaajSoapMessageFactory"/>
|
||||
|
||||
<bean class="org.springframework.jms.listener.DefaultMessageListenerContainer">
|
||||
<property name="connectionFactory" ref="connectionFactory"/>
|
||||
<property name="destinationName" value="RequestQueue"/>
|
||||
<property name="messageListener">
|
||||
<bean class="org.springframework.ws.transport.jms.WebServiceMessageListener">
|
||||
<property name="messageFactory" ref="messageFactory"/>
|
||||
<property name="messageReceiver" ref="messageDispatcher"/>
|
||||
</bean>
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
<bean id="webServiceTemplate" class="org.springframework.ws.client.core.WebServiceTemplate">
|
||||
<constructor-arg ref="messageFactory"/>
|
||||
<property name="messageSender">
|
||||
<bean class="org.springframework.ws.transport.jms.JmsMessageSender">
|
||||
<property name="connectionFactory" ref="connectionFactory"/>
|
||||
</bean>
|
||||
</property>
|
||||
<property name="defaultUri" value="jms:RequestQueue?deliveryMode=NON_PERSISTENT"/>
|
||||
</bean>
|
||||
|
||||
<bean id="messageDispatcher" class="org.springframework.ws.soap.server.SoapMessageDispatcher">
|
||||
<property name="endpointMappings">
|
||||
<bean class="org.springframework.ws.server.endpoint.mapping.PayloadRootQNameEndpointMapping">
|
||||
<property name="defaultEndpoint">
|
||||
<bean class="org.springframework.ws.transport.support.EchoPayloadEndpoint"/>
|
||||
</property>
|
||||
</bean>
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
</beans>
|
||||
@@ -0,0 +1,47 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd">
|
||||
|
||||
<bean id="connectionFactory" class="org.apache.activemq.ActiveMQConnectionFactory">
|
||||
<property name="brokerURL" value="vm://localhost?broker.persistent=false"/>
|
||||
</bean>
|
||||
|
||||
<bean id="requestQueue" class="org.apache.activemq.command.ActiveMQQueue">
|
||||
<property name="physicalName" value="RequestQueue"/>
|
||||
</bean>
|
||||
|
||||
<bean id="requestTopic" class="org.apache.activemq.command.ActiveMQTopic">
|
||||
<property name="physicalName" value="RequestTopic"/>
|
||||
</bean>
|
||||
|
||||
<bean id="responseQueue" class="org.apache.activemq.command.ActiveMQQueue">
|
||||
<property name="physicalName" value="ResponseQueue"/>
|
||||
</bean>
|
||||
|
||||
<bean id="jmsTemplate" class="org.springframework.jms.core.JmsTemplate">
|
||||
<property name="connectionFactory" ref="connectionFactory"/>
|
||||
</bean>
|
||||
|
||||
<bean class="org.springframework.jms.listener.DefaultMessageListenerContainer">
|
||||
<property name="connectionFactory" ref="connectionFactory"/>
|
||||
<property name="destination" ref="requestQueue"/>
|
||||
<property name="messageListener" ref="messageListener"/>
|
||||
</bean>
|
||||
|
||||
<bean class="org.springframework.jms.listener.DefaultMessageListenerContainer">
|
||||
<property name="connectionFactory" ref="connectionFactory"/>
|
||||
<property name="destination" ref="requestTopic"/>
|
||||
<property name="messageListener" ref="messageListener"/>
|
||||
</bean>
|
||||
|
||||
<bean id="messageListener" class="org.springframework.ws.transport.jms.WebServiceMessageListener">
|
||||
<property name="messageFactory">
|
||||
<bean class="org.springframework.ws.soap.saaj.SaajSoapMessageFactory"/>
|
||||
</property>
|
||||
<property name="messageReceiver" ref="messageReceiver"/>
|
||||
</bean>
|
||||
|
||||
<bean id="messageReceiver" class="org.springframework.ws.transport.SimpleTestingMessageReceiver"/>
|
||||
|
||||
|
||||
</beans>
|
||||
@@ -0,0 +1,27 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd">
|
||||
|
||||
<bean id="connectionFactory" class="org.apache.activemq.ActiveMQConnectionFactory">
|
||||
<property name="brokerURL" value="vm://localhost?broker.persistent=false"/>
|
||||
</bean>
|
||||
|
||||
<bean id="requestQueue" class="org.apache.activemq.command.ActiveMQQueue">
|
||||
<property name="physicalName" value="SenderRequestQueue"/>
|
||||
</bean>
|
||||
|
||||
<bean id="responseQueue" class="org.apache.activemq.command.ActiveMQQueue">
|
||||
<property name="physicalName" value="SenderResponseQueue"/>
|
||||
</bean>
|
||||
|
||||
<bean id="jmsTemplate" class="org.springframework.jms.core.JmsTemplate">
|
||||
<property name="connectionFactory" ref="connectionFactory"/>
|
||||
<property name="defaultDestination" ref="requestQueue"/>
|
||||
</bean>
|
||||
|
||||
<bean id="messageSender" class="org.springframework.ws.transport.jms.JmsMessageSender">
|
||||
<property name="connectionFactory" ref="connectionFactory"/>
|
||||
<property name="receiveTimeout" value="500"/>
|
||||
</bean>
|
||||
|
||||
</beans>
|
||||
@@ -0,0 +1,52 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd">
|
||||
|
||||
<bean id="session" class="javax.mail.Session" factory-method="getInstance">
|
||||
<constructor-arg>
|
||||
<props/>
|
||||
</constructor-arg>
|
||||
</bean>
|
||||
|
||||
<bean id="messageFactory" class="org.springframework.ws.soap.saaj.SaajSoapMessageFactory"/>
|
||||
|
||||
<bean id="messagingReceiver" class="org.springframework.ws.transport.mail.MailMessageReceiver">
|
||||
<property name="messageFactory" ref="messageFactory"/>
|
||||
<property name="from" value="Spring-WS SOAP Server <server@example.com>"/>
|
||||
<property name="storeUri" value="imap://server@example.com/INBOX"/>
|
||||
<property name="transportUri" value="smtp://smtp.example.com"/>
|
||||
<property name="messageReceiver" ref="messageDispatcher"/>
|
||||
<property name="session" ref="session"/>
|
||||
<property name="monitoringStrategy">
|
||||
<bean class="org.springframework.ws.transport.mail.monitor.Pop3PollingMonitoringStrategy">
|
||||
<property name="pollingInterval" value="500"/>
|
||||
</bean>
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
<bean id="messageDispatcher" class="org.springframework.ws.soap.server.SoapMessageDispatcher">
|
||||
<property name="endpointMappings">
|
||||
<bean class="org.springframework.ws.server.endpoint.mapping.PayloadRootQNameEndpointMapping">
|
||||
<property name="defaultEndpoint">
|
||||
<bean class="org.springframework.ws.transport.support.EchoPayloadEndpoint"/>
|
||||
</property>
|
||||
</bean>
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
<bean id="webServiceTemplate" class="org.springframework.ws.client.core.WebServiceTemplate">
|
||||
<constructor-arg ref="messageFactory"/>
|
||||
<property name="messageSender">
|
||||
<bean class="org.springframework.ws.transport.mail.MailMessageSender">
|
||||
<property name="from" value="Spring-WS SOAP Client <client@example.com>"/>
|
||||
<property name="transportUri" value="smtp://smtp.example.com"/>
|
||||
<property name="storeUri" value="imap://client@example.com/INBOX"/>
|
||||
<property name="receiveSleepTime" value="1000"/>
|
||||
<property name="session" ref="session"/>
|
||||
</bean>
|
||||
</property>
|
||||
<property name="defaultUri" value="mailto:server@example.com?subject=SOAP%20Test"/>
|
||||
</bean>
|
||||
|
||||
|
||||
</beans>
|
||||
Reference in New Issue
Block a user