Review nullability of spring-ws-support

See gh-1562
This commit is contained in:
Stéphane Nicoll
2025-05-16 09:29:52 +02:00
parent e3e9cdb45c
commit 16dd68afa6
24 changed files with 223 additions and 132 deletions

View File

@@ -20,6 +20,7 @@ import jakarta.jms.BytesMessage;
import jakarta.jms.Message;
import jakarta.jms.Session;
import jakarta.jms.TextMessage;
import org.jspecify.annotations.Nullable;
import org.springframework.jms.core.MessagePostProcessor;
import org.springframework.ws.transport.WebServiceMessageReceiver;
@@ -44,7 +45,7 @@ public class JmsMessageReceiver extends SimpleWebServiceMessageReceiverObjectSup
private String textMessageEncoding = DEFAULT_TEXT_MESSAGE_ENCODING;
private MessagePostProcessor postProcessor;
private @Nullable MessagePostProcessor postProcessor;
/**
* Sets the encoding used to read from and write to {@link TextMessage} messages.

View File

@@ -27,11 +27,13 @@ import jakarta.jms.Message;
import jakarta.jms.Queue;
import jakarta.jms.Session;
import jakarta.jms.Topic;
import org.jspecify.annotations.Nullable;
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.Assert;
import org.springframework.util.StringUtils;
import org.springframework.ws.transport.WebServiceConnection;
import org.springframework.ws.transport.WebServiceMessageSender;
@@ -117,7 +119,7 @@ public class JmsMessageSender extends JmsDestinationAccessor implements WebServi
private String textMessageEncoding = DEFAULT_TEXT_MESSAGE_ENCODING;
private MessagePostProcessor postProcessor;
private @Nullable MessagePostProcessor postProcessor;
/**
* Create a new {@code JmsMessageSender}
@@ -165,6 +167,8 @@ public class JmsMessageSender extends JmsDestinationAccessor implements WebServi
@Override
public WebServiceConnection createConnection(URI uri) throws IOException {
ConnectionFactory connectionFactory = getConnectionFactory();
Assert.notNull(connectionFactory, "ConnectionFactory is required");
Connection jmsConnection = null;
Session jmsSession = null;
try {
@@ -172,8 +176,8 @@ public class JmsMessageSender extends JmsDestinationAccessor implements WebServi
jmsSession = createSession(jmsConnection);
Destination requestDestination = resolveRequestDestination(jmsSession, uri);
Message requestMessage = createRequestMessage(jmsSession, uri);
JmsSenderConnection wsConnection = new JmsSenderConnection(getConnectionFactory(), jmsConnection,
jmsSession, requestDestination, requestMessage);
JmsSenderConnection wsConnection = new JmsSenderConnection(connectionFactory, jmsConnection, jmsSession,
requestDestination, requestMessage);
wsConnection.setDeliveryMode(JmsTransportUtils.getDeliveryMode(uri));
wsConnection.setPriority(JmsTransportUtils.getPriority(uri));
wsConnection.setReceiveTimeout(this.receiveTimeout);
@@ -197,10 +201,12 @@ public class JmsMessageSender extends JmsDestinationAccessor implements WebServi
}
private Destination resolveRequestDestination(Session session, URI uri) throws JMSException {
return resolveDestinationName(session, JmsTransportUtils.getDestinationName(uri));
String destinationName = JmsTransportUtils.getDestinationName(uri);
Assert.notNull(destinationName, "No destination name found for URI [" + uri + "]");
return resolveDestinationName(session, destinationName);
}
private Destination resolveResponseDestination(Session session, URI uri) throws JMSException {
private @Nullable Destination resolveResponseDestination(Session session, URI uri) throws JMSException {
String destinationName = JmsTransportUtils.getReplyToName(uri);
return StringUtils.hasLength(destinationName) ? resolveDestinationName(session, destinationName) : null;
}

View File

@@ -29,6 +29,7 @@ import jakarta.jms.Message;
import jakarta.jms.MessageProducer;
import jakarta.jms.Session;
import jakarta.jms.TextMessage;
import org.jspecify.annotations.Nullable;
import org.springframework.jms.core.MessagePostProcessor;
import org.springframework.jms.support.JmsUtils;
@@ -57,11 +58,11 @@ public class JmsReceiverConnection extends AbstractReceiverConnection {
private final Session session;
private Message responseMessage;
private @Nullable Message responseMessage;
private String textMessageEncoding;
private @Nullable String textMessageEncoding;
private MessagePostProcessor postProcessor;
private @Nullable MessagePostProcessor postProcessor;
private JmsReceiverConnection(Message requestMessage, Session session) {
Assert.notNull(requestMessage, "requestMessage must not be null");
@@ -89,7 +90,7 @@ public class JmsReceiverConnection extends AbstractReceiverConnection {
this.textMessageEncoding = encoding;
}
void setPostProcessor(MessagePostProcessor postProcessor) {
void setPostProcessor(@Nullable MessagePostProcessor postProcessor) {
this.postProcessor = postProcessor;
}
@@ -105,7 +106,7 @@ public class JmsReceiverConnection extends AbstractReceiverConnection {
* Returns the response message, if any, for this connection. Returns either a
* {@link BytesMessage} or a {@link TextMessage}.
*/
public Message getResponseMessage() {
public @Nullable Message getResponseMessage() {
return this.responseMessage;
}
@@ -114,7 +115,7 @@ public class JmsReceiverConnection extends AbstractReceiverConnection {
*/
@Override
public URI getUri() throws URISyntaxException {
public @Nullable URI getUri() throws URISyntaxException {
try {
return JmsTransportUtils.toUri(this.requestMessage.getJMSDestination());
}
@@ -128,7 +129,7 @@ public class JmsReceiverConnection extends AbstractReceiverConnection {
*/
@Override
public String getErrorMessage() throws IOException {
public @Nullable String getErrorMessage() throws IOException {
return null;
}
@@ -167,6 +168,7 @@ public class JmsReceiverConnection extends AbstractReceiverConnection {
return new BytesMessageInputStream((BytesMessage) this.requestMessage);
}
else if (this.requestMessage instanceof TextMessage) {
Assert.notNull(this.textMessageEncoding, "MessageEncoding for TextMessage is required");
return new TextMessageInputStream((TextMessage) this.requestMessage, this.textMessageEncoding);
}
else {
@@ -181,15 +183,7 @@ public class JmsReceiverConnection extends AbstractReceiverConnection {
@Override
protected void onSendBeforeWrite(WebServiceMessage message) throws IOException {
try {
if (this.requestMessage instanceof BytesMessage) {
this.responseMessage = this.session.createBytesMessage();
}
else if (this.requestMessage instanceof TextMessage) {
this.responseMessage = this.session.createTextMessage();
}
else {
throw new IllegalStateException("Unknown request message type [" + this.requestMessage + "]");
}
this.responseMessage = createResponseMessage();
String correlation = this.requestMessage.getJMSCorrelationID();
if (correlation == null) {
correlation = this.requestMessage.getJMSMessageID();
@@ -201,8 +195,21 @@ public class JmsReceiverConnection extends AbstractReceiverConnection {
}
}
private Message createResponseMessage() throws JMSException {
if (this.requestMessage instanceof BytesMessage) {
return this.session.createBytesMessage();
}
else if (this.requestMessage instanceof TextMessage) {
return this.session.createTextMessage();
}
else {
throw new IllegalStateException("Unknown request message type [" + this.requestMessage + "]");
}
}
@Override
public void addResponseHeader(String name, String value) throws IOException {
Assert.state(this.responseMessage != null, "Response message is not available");
try {
JmsTransportUtils.addHeader(this.responseMessage, name, value);
}
@@ -217,6 +224,7 @@ public class JmsReceiverConnection extends AbstractReceiverConnection {
return new BytesMessageOutputStream((BytesMessage) this.responseMessage);
}
else if (this.responseMessage instanceof TextMessage) {
Assert.notNull(this.textMessageEncoding, "MessageEncoding for TextMessage is required");
return new TextMessageOutputStream((TextMessage) this.responseMessage, this.textMessageEncoding);
}
else {
@@ -226,6 +234,7 @@ public class JmsReceiverConnection extends AbstractReceiverConnection {
@Override
protected void onSendAfterWrite(WebServiceMessage message) throws IOException {
Assert.state(this.responseMessage != null, "Response message is not available");
MessageProducer messageProducer = null;
try {
if (this.requestMessage.getJMSReplyTo() != null) {

View File

@@ -34,6 +34,7 @@ import jakarta.jms.MessageProducer;
import jakarta.jms.Session;
import jakarta.jms.TemporaryQueue;
import jakarta.jms.TextMessage;
import org.jspecify.annotations.Nullable;
import org.springframework.jms.connection.ConnectionFactoryUtils;
import org.springframework.jms.core.MessagePostProcessor;
@@ -64,9 +65,9 @@ public class JmsSenderConnection extends AbstractSenderConnection {
private Message requestMessage;
private Destination responseDestination;
private @Nullable Destination responseDestination;
private Message responseMessage;
private @Nullable Message responseMessage;
private long receiveTimeout;
@@ -76,9 +77,9 @@ public class JmsSenderConnection extends AbstractSenderConnection {
private int priority;
private String textMessageEncoding;
private @Nullable String textMessageEncoding;
private MessagePostProcessor postProcessor;
private @Nullable MessagePostProcessor postProcessor;
private boolean sessionTransacted = false;
@@ -111,7 +112,7 @@ public class JmsSenderConnection extends AbstractSenderConnection {
* Returns the response message, if any, for this connection. Returns either a
* {@link BytesMessage} or a {@link TextMessage}.
*/
public Message getResponseMessage() {
public @Nullable Message getResponseMessage() {
return this.responseMessage;
}
@@ -119,7 +120,7 @@ public class JmsSenderConnection extends AbstractSenderConnection {
* Package-friendly setters
*/
void setResponseDestination(Destination responseDestination) {
void setResponseDestination(@Nullable Destination responseDestination) {
this.responseDestination = responseDestination;
}
@@ -143,7 +144,7 @@ public class JmsSenderConnection extends AbstractSenderConnection {
this.textMessageEncoding = textMessageEncoding;
}
void setPostProcessor(MessagePostProcessor postProcessor) {
void setPostProcessor(@Nullable MessagePostProcessor postProcessor) {
this.postProcessor = postProcessor;
}
@@ -156,7 +157,7 @@ public class JmsSenderConnection extends AbstractSenderConnection {
*/
@Override
public URI getUri() throws URISyntaxException {
public @Nullable URI getUri() throws URISyntaxException {
try {
return JmsTransportUtils.toUri(this.requestDestination);
}
@@ -175,7 +176,7 @@ public class JmsSenderConnection extends AbstractSenderConnection {
}
@Override
public String getErrorMessage() throws IOException {
public @Nullable String getErrorMessage() throws IOException {
return null;
}
@@ -199,6 +200,7 @@ public class JmsSenderConnection extends AbstractSenderConnection {
return new BytesMessageOutputStream((BytesMessage) this.requestMessage);
}
else if (this.requestMessage instanceof TextMessage) {
Assert.notNull(this.textMessageEncoding, "MessageEncoding for TextMessage is required");
return new TextMessageOutputStream((TextMessage) this.requestMessage, this.textMessageEncoding);
}
else {
@@ -277,9 +279,10 @@ public class JmsSenderConnection extends AbstractSenderConnection {
}
finally {
JmsUtils.closeMessageConsumer(messageConsumer);
if (this.temporaryResponseQueueCreated) {
if (this.temporaryResponseQueueCreated
&& this.responseDestination instanceof TemporaryQueue temporaryQueue) {
try {
((TemporaryQueue) this.responseDestination).delete();
temporaryQueue.delete();
}
catch (JMSException ex) {
// ignore
@@ -296,6 +299,7 @@ public class JmsSenderConnection extends AbstractSenderConnection {
@Override
public Iterator<String> getResponseHeaderNames() throws IOException {
try {
Assert.state(this.responseMessage != null, "ResponseMessage is required");
return JmsTransportUtils.getHeaderNames(this.responseMessage);
}
catch (JMSException ex) {
@@ -306,6 +310,7 @@ public class JmsSenderConnection extends AbstractSenderConnection {
@Override
public Iterator<String> getResponseHeaders(String name) throws IOException {
try {
Assert.state(this.responseMessage != null, "ResponseMessage is required");
return JmsTransportUtils.getHeaders(this.responseMessage, name);
}
catch (JMSException ex) {
@@ -319,6 +324,7 @@ public class JmsSenderConnection extends AbstractSenderConnection {
return new BytesMessageInputStream((BytesMessage) this.responseMessage);
}
else if (this.responseMessage instanceof TextMessage) {
Assert.notNull(this.textMessageEncoding, "MessageEncoding for TextMessage is required");
return new TextMessageInputStream((TextMessage) this.responseMessage, this.textMessageEncoding);
}
else {

View File

@@ -17,4 +17,7 @@
/**
* Package providing support for handling messages via JMS.
*/
@NullMarked
package org.springframework.ws.transport.jms;
import org.jspecify.annotations.NullMarked;

View File

@@ -32,6 +32,7 @@ import jakarta.jms.JMSException;
import jakarta.jms.Message;
import jakarta.jms.Queue;
import jakarta.jms.Topic;
import org.jspecify.annotations.Nullable;
import org.springframework.ws.transport.jms.JmsTransportConstants;
@@ -100,7 +101,7 @@ public abstract class JmsTransportUtils {
* @param destination the destination
* @return a jms URI
*/
public static URI toUri(Destination destination) throws URISyntaxException, JMSException {
public static @Nullable URI toUri(@Nullable Destination destination) throws URISyntaxException, JMSException {
if (destination == null) {
return null;
}
@@ -118,7 +119,7 @@ public abstract class JmsTransportUtils {
}
/** Returns the destination name of the given URI. */
public static String getDestinationName(URI uri) {
public static @Nullable String getDestinationName(URI uri) {
return getStringParameter(DESTINATION_NAME_PATTERN, uri);
}
@@ -215,11 +216,11 @@ public abstract class JmsTransportUtils {
* Returns the reply-to name of the given URI.
* @see Message#setJMSReplyTo(Destination)
*/
public static String getReplyToName(URI uri) {
public static @Nullable String getReplyToName(URI uri) {
return getStringParameter(REPLY_TO_NAME_PATTERN, uri);
}
private static String getStringParameter(Pattern pattern, URI uri) {
private static @Nullable String getStringParameter(Pattern pattern, URI uri) {
Matcher matcher = pattern.matcher(uri.getSchemeSpecificPart());
if (matcher.find() && matcher.groupCount() == 1) {
return matcher.group(1);

View File

@@ -17,4 +17,7 @@
/**
* Classes supporting the org.springframework.ws.transport.jms package.
*/
@NullMarked
package org.springframework.ws.transport.jms.support;
import org.jspecify.annotations.NullMarked;

View File

@@ -16,6 +16,7 @@
package org.springframework.ws.transport.mail;
import java.util.Objects;
import java.util.Properties;
import jakarta.mail.Folder;
@@ -27,6 +28,7 @@ import jakarta.mail.Store;
import jakarta.mail.URLName;
import jakarta.mail.internet.AddressException;
import jakarta.mail.internet.InternetAddress;
import org.jspecify.annotations.Nullable;
import org.springframework.scheduling.SchedulingAwareRunnable;
import org.springframework.util.Assert;
@@ -58,18 +60,21 @@ public class MailMessageReceiver extends AbstractAsyncStandaloneMessageReceiver
private Session session = Session.getInstance(new Properties(), null);
@SuppressWarnings("NullAway.Init")
private URLName storeUri;
@SuppressWarnings("NullAway.Init")
private URLName transportUri;
private Folder folder;
private Store store;
private InternetAddress from;
@SuppressWarnings("NullAway.Init")
private MonitoringStrategy monitoringStrategy;
private @Nullable Folder folder;
private @Nullable Store store;
private @Nullable InternetAddress from;
/** Sets the from address to use when sending response messages. */
public void setFrom(String from) throws AddressException {
this.from = new InternetAddress(from);
@@ -201,7 +206,7 @@ public class MailMessageReceiver extends AbstractAsyncStandaloneMessageReceiver
if (this.folder != null && this.folder.isOpen()) {
return;
}
this.folder = this.store.getFolder(this.storeUri);
this.folder = Objects.requireNonNull(this.store).getFolder(this.storeUri);
if (this.folder == null || !this.folder.exists()) {
throw new IllegalStateException("No default folder to receive from");
}
@@ -228,7 +233,7 @@ public class MailMessageReceiver extends AbstractAsyncStandaloneMessageReceiver
while (isRunning()) {
try {
Message[] messages = MailMessageReceiver.this.monitoringStrategy
.monitor(MailMessageReceiver.this.folder);
.monitor(Objects.requireNonNull(MailMessageReceiver.this.folder));
for (Message message : messages) {
MessageHandler handler = new MessageHandler(message);
execute(handler);
@@ -274,7 +279,7 @@ public class MailMessageReceiver extends AbstractAsyncStandaloneMessageReceiver
MailReceiverConnection connection = new MailReceiverConnection(this.message,
MailMessageReceiver.this.session);
connection.setTransportUri(MailMessageReceiver.this.transportUri);
connection.setFrom(MailMessageReceiver.this.from);
connection.setFrom(Objects.requireNonNull(MailMessageReceiver.this.from));
try {
handleConnection(connection);
}

View File

@@ -25,6 +25,7 @@ import jakarta.mail.URLName;
import jakarta.mail.internet.AddressException;
import jakarta.mail.internet.InternetAddress;
import jakarta.mail.internet.MimeMessage;
import org.jspecify.annotations.Nullable;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.util.Assert;
@@ -83,11 +84,11 @@ public class MailMessageSender implements WebServiceMessageSender, InitializingB
private Session session = Session.getInstance(new Properties(), null);
private URLName storeUri;
private @Nullable URLName storeUri;
private URLName transportUri;
private @Nullable URLName transportUri;
private InternetAddress from;
private @Nullable InternetAddress from;
/**
* Sets the from address to use when sending request messages.
@@ -163,7 +164,10 @@ public class MailMessageSender implements WebServiceMessageSender, InitializingB
@Override
public WebServiceConnection createConnection(URI uri) throws IOException {
Assert.notNull(this.transportUri, "'transportUri' is required");
Assert.notNull(this.storeUri, "'storeUri' is required");
InternetAddress to = MailTransportUtils.getTo(uri);
Assert.notNull(to, "No TO address found for '" + uri + "'");
MailSenderConnection connection = new MailSenderConnection(this.session, this.transportUri, this.storeUri, to,
this.receiveSleepTime);
if (this.from != null) {

View File

@@ -39,6 +39,7 @@ import jakarta.mail.Session;
import jakarta.mail.Transport;
import jakarta.mail.URLName;
import jakarta.mail.internet.InternetAddress;
import org.jspecify.annotations.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.ObjectUtils;
@@ -62,15 +63,15 @@ public class MailReceiverConnection extends AbstractReceiverConnection {
private final Session session;
private Message responseMessage;
private @Nullable Message responseMessage;
private ByteArrayOutputStream responseBuffer;
private @Nullable ByteArrayOutputStream responseBuffer;
private String responseContentType;
private @Nullable String responseContentType;
private URLName transportUri;
private @Nullable URLName transportUri;
private InternetAddress from;
private @Nullable InternetAddress from;
/** Constructs a new Mail connection with the given parameters. */
protected MailReceiverConnection(Message requestMessage, Session session) {
@@ -87,6 +88,7 @@ public class MailReceiverConnection extends AbstractReceiverConnection {
/** Returns the response message, if any, for this connection. */
public Message getResponseMessage() {
Assert.notNull(this.responseMessage, "ResponseMessage is not available");
return this.responseMessage;
}
@@ -125,7 +127,7 @@ public class MailReceiverConnection extends AbstractReceiverConnection {
*/
@Override
public String getErrorMessage() throws IOException {
public @Nullable String getErrorMessage() throws IOException {
return null;
}
@@ -178,7 +180,7 @@ public class MailReceiverConnection extends AbstractReceiverConnection {
@Override
public void addResponseHeader(String name, String value) throws IOException {
try {
this.responseMessage.addHeader(name, value);
getResponseMessage().addHeader(name, value);
if (TransportConstants.HEADER_CONTENT_TYPE.equals(name)) {
this.responseContentType = value;
}
@@ -190,6 +192,7 @@ public class MailReceiverConnection extends AbstractReceiverConnection {
@Override
protected OutputStream getResponseOutputStream() throws IOException {
Assert.state(this.responseBuffer != null, "onSendBeforeWrite has not been called");
return this.responseBuffer;
}
@@ -213,9 +216,12 @@ public class MailReceiverConnection extends AbstractReceiverConnection {
@Override
protected void onSendAfterWrite(WebServiceMessage message) throws IOException {
Transport transport = null;
Assert.state(this.responseMessage != null, "onSendAfterWrite has not been called");
Assert.state(this.responseBuffer != null, "onSendAfterWrite has not been called");
Assert.notNull(this.transportUri, "'transportUri' must not be null");
try {
this.responseMessage.setDataHandler(new DataHandler(
new ByteArrayDataSource(this.responseContentType, this.responseBuffer.toByteArray())));
new ByteArrayDataSource(this.responseBuffer.toByteArray(), this.responseContentType)));
transport = this.session.getTransport(this.transportUri);
transport.connect();
this.responseMessage.saveChanges();
@@ -235,9 +241,9 @@ public class MailReceiverConnection extends AbstractReceiverConnection {
private final byte[] data;
ByteArrayDataSource(String contentType, byte[] data) {
ByteArrayDataSource(byte[] data, @Nullable String contentType) {
this.data = data;
this.contentType = contentType;
this.contentType = (contentType != null) ? contentType : "application/octet-stream";
}
@Override

View File

@@ -47,6 +47,7 @@ import jakarta.mail.search.HeaderTerm;
import jakarta.mail.search.SearchTerm;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.jspecify.annotations.Nullable;
import org.springframework.util.Assert;
import org.springframework.ws.WebServiceMessage;
@@ -70,11 +71,11 @@ public class MailSenderConnection extends AbstractSenderConnection {
private final Session session;
private MimeMessage requestMessage;
private @Nullable MimeMessage requestMessage;
private Message responseMessage;
private @Nullable Message responseMessage;
private String requestContentType;
private @Nullable String requestContentType;
private boolean deleteAfterReceive = false;
@@ -82,19 +83,19 @@ public class MailSenderConnection extends AbstractSenderConnection {
private final URLName transportUri;
private ByteArrayOutputStream requestBuffer;
private @Nullable ByteArrayOutputStream requestBuffer;
private InternetAddress from;
private @Nullable InternetAddress from;
private final InternetAddress to;
private String subject;
private @Nullable String subject;
private final long receiveTimeout;
private Store store;
private @Nullable Store store;
private Folder folder;
private @Nullable Folder folder;
/** Constructs a new Mail connection with the given parameters. */
protected MailSenderConnection(Session session, URLName transportUri, URLName storeUri, InternetAddress to,
@@ -111,12 +112,14 @@ public class MailSenderConnection extends AbstractSenderConnection {
}
/** Returns the request message for this connection. */
public Message getRequestMessage() {
public MimeMessage getRequestMessage() {
Assert.notNull(this.requestMessage, "RequestMessage is not available");
return this.requestMessage;
}
/** Returns the response message, if any, for this connection. */
public Message getResponseMessage() {
Assert.notNull(this.responseMessage, "ResponseMessage is not available");
return this.responseMessage;
}
@@ -165,7 +168,7 @@ public class MailSenderConnection extends AbstractSenderConnection {
@Override
public void addRequestHeader(String name, String value) throws IOException {
try {
this.requestMessage.addHeader(name, value);
getRequestMessage().addHeader(name, value);
if (TransportConstants.HEADER_CONTENT_TYPE.equals(name)) {
this.requestContentType = value;
}
@@ -177,15 +180,18 @@ public class MailSenderConnection extends AbstractSenderConnection {
@Override
protected OutputStream getRequestOutputStream() throws IOException {
Assert.notNull(this.requestBuffer, "Request OutputStream is not available");
return this.requestBuffer;
}
@Override
protected void onSendAfterWrite(WebServiceMessage message) throws IOException {
Assert.state(this.requestMessage != null, "onSendBeforeWrite has not been called");
Assert.state(this.requestBuffer != null, "onSendBeforeWrite has not been called");
Transport transport = null;
try {
this.requestMessage.setDataHandler(new DataHandler(
new ByteArrayDataSource(this.requestContentType, this.requestBuffer.toByteArray())));
new ByteArrayDataSource(this.requestBuffer.toByteArray(), this.requestContentType)));
transport = this.session.getTransport(this.transportUri);
transport.connect();
this.requestMessage.saveChanges();
@@ -195,7 +201,9 @@ public class MailSenderConnection extends AbstractSenderConnection {
throw new MailTransportException(ex);
}
finally {
MailTransportUtils.closeService(transport);
if (transport != null) {
MailTransportUtils.closeService(transport);
}
}
}
@@ -205,6 +213,7 @@ public class MailSenderConnection extends AbstractSenderConnection {
@Override
protected void onReceiveBeforeRead() throws IOException {
Assert.state(this.requestMessage != null, "onSendBeforeWrite has not been called");
try {
String requestMessageId = this.requestMessage.getMessageID();
Assert.hasLength(requestMessageId, "No Message-ID found on request message [" + this.requestMessage + "]");
@@ -215,7 +224,7 @@ public class MailSenderConnection extends AbstractSenderConnection {
// Re-interrupt current thread, to allow other threads to react.
Thread.currentThread().interrupt();
}
openFolder();
this.folder = openFolder();
SearchTerm searchTerm = new HeaderTerm(MailTransportConstants.HEADER_IN_REPLY_TO, requestMessageId);
Message[] responses = this.folder.search(searchTerm);
if (responses.length > 0) {
@@ -224,7 +233,7 @@ public class MailSenderConnection extends AbstractSenderConnection {
}
this.responseMessage = responses[0];
}
if (this.deleteAfterReceive) {
if (this.deleteAfterReceive && this.responseMessage != null) {
this.responseMessage.setFlag(Flags.Flag.DELETED, true);
}
}
@@ -233,19 +242,20 @@ public class MailSenderConnection extends AbstractSenderConnection {
}
}
private void openFolder() throws MessagingException {
private Folder openFolder() throws MessagingException {
this.store = this.session.getStore(this.storeUri);
this.store.connect();
this.folder = this.store.getFolder(this.storeUri);
if (this.folder == null || !this.folder.exists()) {
Folder folder = this.store.getFolder(this.storeUri);
if (folder == null || !folder.exists()) {
throw new IllegalStateException("No default folder to receive from");
}
if (this.deleteAfterReceive) {
this.folder.open(Folder.READ_WRITE);
folder.open(Folder.READ_WRITE);
}
else {
this.folder.open(Folder.READ_ONLY);
folder.open(Folder.READ_ONLY);
}
return folder;
}
@Override
@@ -257,7 +267,7 @@ public class MailSenderConnection extends AbstractSenderConnection {
public Iterator<String> getResponseHeaderNames() throws IOException {
try {
List<String> headers = new ArrayList<>();
Enumeration<?> enumeration = this.responseMessage.getAllHeaders();
Enumeration<?> enumeration = getResponseMessage().getAllHeaders();
while (enumeration.hasMoreElements()) {
Header header = (Header) enumeration.nextElement();
headers.add(header.getName());
@@ -272,7 +282,7 @@ public class MailSenderConnection extends AbstractSenderConnection {
@Override
public Iterator<String> getResponseHeaders(String name) throws IOException {
try {
String[] headers = this.responseMessage.getHeader(name);
String[] headers = getResponseMessage().getHeader(name);
return Arrays.asList(headers).iterator();
}
catch (MessagingException ex) {
@@ -284,7 +294,7 @@ public class MailSenderConnection extends AbstractSenderConnection {
@Override
protected InputStream getResponseInputStream() throws IOException {
try {
return this.responseMessage.getDataHandler().getInputStream();
return getResponseMessage().getDataHandler().getInputStream();
}
catch (MessagingException ex) {
throw new MailTransportException(ex);
@@ -297,14 +307,18 @@ public class MailSenderConnection extends AbstractSenderConnection {
}
@Override
public String getErrorMessage() throws IOException {
public @Nullable String getErrorMessage() throws IOException {
return null;
}
@Override
public void onClose() throws IOException {
MailTransportUtils.closeFolder(this.folder, this.deleteAfterReceive);
MailTransportUtils.closeService(this.store);
if (this.folder != null) {
MailTransportUtils.closeFolder(this.folder, this.deleteAfterReceive);
}
if (this.store != null) {
MailTransportUtils.closeService(this.store);
}
}
private static final class ByteArrayDataSource implements DataSource {
@@ -313,9 +327,9 @@ public class MailSenderConnection extends AbstractSenderConnection {
private final byte[] data;
ByteArrayDataSource(String contentType, byte[] data) {
ByteArrayDataSource(byte[] data, @Nullable String contentType) {
this.data = data;
this.contentType = contentType;
this.contentType = (contentType != null) ? contentType : "application/octet-stream";
}
@Override

View File

@@ -23,6 +23,7 @@ import jakarta.mail.event.MessageCountAdapter;
import jakarta.mail.event.MessageCountEvent;
import jakarta.mail.event.MessageCountListener;
import org.eclipse.angus.mail.imap.IMAPFolder;
import org.jspecify.annotations.Nullable;
import org.springframework.util.Assert;
@@ -38,7 +39,7 @@ import org.springframework.util.Assert;
*/
public class ImapIdleMonitoringStrategy extends AbstractMonitoringStrategy {
private MessageCountListener messageCountListener;
private @Nullable MessageCountListener messageCountListener;
@Override
protected void waitForNewMessages(Folder folder) throws MessagingException, InterruptedException {

View File

@@ -18,4 +18,7 @@
* Provides the MonitoringStrategy interface and implementations. Used for monitoring a
* JavaMail Folder for new email messages.
*/
@NullMarked
package org.springframework.ws.transport.mail.monitor;
import org.jspecify.annotations.NullMarked;

View File

@@ -17,4 +17,7 @@
/**
* Package providing support for handling messages via email.
*/
@NullMarked
package org.springframework.ws.transport.mail;
import org.jspecify.annotations.NullMarked;

View File

@@ -29,6 +29,7 @@ import jakarta.mail.internet.AddressException;
import jakarta.mail.internet.InternetAddress;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.jspecify.annotations.Nullable;
import org.springframework.util.StringUtils;
import org.springframework.ws.transport.mail.MailTransportConstants;
@@ -50,7 +51,7 @@ public abstract class MailTransportUtils {
private MailTransportUtils() {
}
public static InternetAddress getTo(URI uri) {
public static @Nullable InternetAddress getTo(URI uri) {
Matcher matcher = TO_PATTERN.matcher(uri.getSchemeSpecificPart());
if (matcher.find()) {
for (int i = 1; i <= matcher.groupCount(); i++) {
@@ -68,7 +69,7 @@ public abstract class MailTransportUtils {
return null;
}
public static String getSubject(URI uri) {
public static @Nullable String getSubject(URI uri) {
Matcher matcher = SUBJECT_PATTERN.matcher(uri.getSchemeSpecificPart());
if (matcher.find()) {
return matcher.group(1);
@@ -83,7 +84,7 @@ public abstract class MailTransportUtils {
* @see jakarta.mail.Transport
* @see jakarta.mail.Store
*/
public static void closeService(Service service) {
public static void closeService(@Nullable Service service) {
if (service != null) {
try {
service.close();
@@ -110,7 +111,7 @@ public abstract class MailTransportUtils {
* @param folder the JavaMail Folder to close (may be {@code null})
* @param expunge whether all deleted messages should be expunged from the folder
*/
public static void closeFolder(Folder folder, boolean expunge) {
public static void closeFolder(@Nullable Folder folder, boolean expunge) {
if (folder != null && folder.isOpen()) {
try {
folder.close(expunge);
@@ -172,7 +173,7 @@ public abstract class MailTransportUtils {
* @param subject the subject, may be {@code null}
* @return a mailto URI
*/
public static URI toUri(InternetAddress to, String subject) throws URISyntaxException {
public static URI toUri(InternetAddress to, @Nullable String subject) throws URISyntaxException {
if (StringUtils.hasLength(subject)) {
return new URI(MailTransportConstants.MAIL_URI_SCHEME, to.getAddress() + "?subject=" + subject, null);
}

View File

@@ -17,4 +17,7 @@
/**
* Classes supporting the org.springframework.ws.transport.mail package.
*/
@NullMarked
package org.springframework.ws.transport.mail.support;
import org.jspecify.annotations.NullMarked;

View File

@@ -26,7 +26,9 @@ import org.jivesoftware.smack.filter.StanzaTypeFilter;
import org.jivesoftware.smack.packet.Message;
import org.jivesoftware.smack.packet.Stanza;
import org.jivesoftware.smack.tcp.XMPPTCPConnection;
import org.jspecify.annotations.Nullable;
import org.springframework.util.Assert;
import org.springframework.ws.transport.support.AbstractStandaloneMessageReceiver;
/**
@@ -51,9 +53,9 @@ public class XmppMessageReceiver extends AbstractStandaloneMessageReceiver {
*/
public static final String DEFAULT_MESSAGE_ENCODING = "UTF-8";
private XMPPTCPConnection connection;
private @Nullable XMPPTCPConnection connection;
private WebServicePacketListener packetListener;
private @Nullable WebServicePacketListener packetListener;
private final String messageEncoding = DEFAULT_MESSAGE_ENCODING;
@@ -65,11 +67,16 @@ public class XmppMessageReceiver extends AbstractStandaloneMessageReceiver {
this.connection = connection;
}
private XMPPTCPConnection getConnection() {
Assert.state(this.connection != null, "Connection is required");
return this.connection;
}
@Override
protected void onActivate() throws XMPPException, IOException, SmackException {
if (!this.connection.isConnected()) {
if (!getConnection().isConnected()) {
try {
this.connection.connect();
getConnection().connect();
}
catch (InterruptedException ex) {
throw new IOException(ex);
@@ -80,29 +87,29 @@ public class XmppMessageReceiver extends AbstractStandaloneMessageReceiver {
@Override
protected void onStart() {
if (this.logger.isInfoEnabled()) {
this.logger.info("Starting XMPP receiver [" + this.connection.getUser() + "]");
this.logger.info("Starting XMPP receiver [" + getConnection().getUser() + "]");
}
this.packetListener = new WebServicePacketListener();
StanzaFilter packetFilter = new StanzaTypeFilter(Message.class);
this.connection.addAsyncStanzaListener(this.packetListener, packetFilter);
getConnection().addAsyncStanzaListener(this.packetListener, packetFilter);
}
@Override
protected void onStop() {
if (this.logger.isInfoEnabled()) {
this.logger.info("Stopping XMPP receiver [" + this.connection.getUser() + "]");
this.logger.info("Stopping XMPP receiver [" + getConnection().getUser() + "]");
}
this.connection.removeAsyncStanzaListener(this.packetListener);
getConnection().removeAsyncStanzaListener(this.packetListener);
this.packetListener = null;
}
@Override
protected void onShutdown() {
if (this.logger.isInfoEnabled()) {
this.logger.info("Shutting down XMPP receiver [" + this.connection.getUser() + "]");
this.logger.info("Shutting down XMPP receiver [" + getConnection().getUser() + "]");
}
if (this.connection.isConnected()) {
this.connection.disconnect();
if (getConnection().isConnected()) {
getConnection().disconnect();
}
}
@@ -113,8 +120,7 @@ public class XmppMessageReceiver extends AbstractStandaloneMessageReceiver {
XmppMessageReceiver.this.logger.info("Received " + packet);
if (packet instanceof Message message) {
try {
XmppReceiverConnection wsConnection = new XmppReceiverConnection(
XmppMessageReceiver.this.connection, message);
XmppReceiverConnection wsConnection = new XmppReceiverConnection(getConnection(), message);
wsConnection.setMessageEncoding(XmppMessageReceiver.this.messageEncoding);
handleConnection(wsConnection);
}

View File

@@ -18,9 +18,11 @@ package org.springframework.ws.transport.xmpp;
import java.io.IOException;
import java.net.URI;
import java.util.Objects;
import java.util.UUID;
import org.jivesoftware.smack.XMPPConnection;
import org.jspecify.annotations.Nullable;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.util.Assert;
@@ -58,7 +60,7 @@ public class XmppMessageSender implements WebServiceMessageSender, InitializingB
private String messageEncoding = DEFAULT_MESSAGE_ENCODING;
private XMPPConnection connection;
private @Nullable XMPPConnection connection;
/**
* Sets the {@code XMPPConnection}. Setting this property is required.
@@ -93,7 +95,7 @@ public class XmppMessageSender implements WebServiceMessageSender, InitializingB
public WebServiceConnection createConnection(URI uri) throws IOException {
String to = XmppTransportUtils.getTo(uri);
String thread = createThread();
XmppSenderConnection connection = new XmppSenderConnection(this.connection, to, thread);
XmppSenderConnection connection = new XmppSenderConnection(Objects.requireNonNull(this.connection), to, thread);
connection.setReceiveTimeout(this.receiveTimeout);
connection.setMessageEncoding(this.messageEncoding);
return connection;

View File

@@ -22,10 +22,12 @@ import java.io.OutputStream;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.Iterator;
import java.util.Objects;
import org.jivesoftware.smack.SmackException;
import org.jivesoftware.smack.XMPPConnection;
import org.jivesoftware.smack.packet.Message;
import org.jspecify.annotations.Nullable;
import org.springframework.util.Assert;
import org.springframework.ws.WebServiceMessage;
@@ -48,9 +50,9 @@ public class XmppReceiverConnection extends AbstractReceiverConnection {
private final Message requestMessage;
private Message responseMessage;
private @Nullable Message responseMessage;
private String messageEncoding;
private String messageEncoding = XmppMessageReceiver.DEFAULT_MESSAGE_ENCODING;
public XmppReceiverConnection(XMPPConnection connection, Message requestMessage) {
Assert.notNull(connection, "'connection' must not be null");
@@ -65,7 +67,7 @@ public class XmppReceiverConnection extends AbstractReceiverConnection {
}
/** Returns the response message, if any, for this connection. */
public Message getResponseMessage() {
public @Nullable Message getResponseMessage() {
return this.responseMessage;
}
@@ -96,7 +98,7 @@ public class XmppReceiverConnection extends AbstractReceiverConnection {
}
@Override
public String getErrorMessage() {
public @Nullable String getErrorMessage() {
return XmppTransportUtils.getErrorMessage(this.responseMessage);
}
@@ -132,12 +134,12 @@ public class XmppReceiverConnection extends AbstractReceiverConnection {
@Override
public void addResponseHeader(String name, String value) throws IOException {
XmppTransportUtils.addHeader(this.responseMessage, name, value);
XmppTransportUtils.addHeader(Objects.requireNonNull(this.responseMessage), name, value);
}
@Override
protected OutputStream getResponseOutputStream() throws IOException {
return new MessageOutputStream(this.responseMessage, this.messageEncoding);
return new MessageOutputStream(Objects.requireNonNull(this.responseMessage), this.messageEncoding);
}
@Override

View File

@@ -22,6 +22,7 @@ import java.io.OutputStream;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.Iterator;
import java.util.Objects;
import org.jivesoftware.smack.SmackException;
import org.jivesoftware.smack.StanzaCollector;
@@ -32,6 +33,7 @@ import org.jivesoftware.smack.filter.StanzaTypeFilter;
import org.jivesoftware.smack.filter.ThreadFilter;
import org.jivesoftware.smack.packet.Message;
import org.jivesoftware.smack.packet.Stanza;
import org.jspecify.annotations.Nullable;
import org.jxmpp.jid.impl.JidCreate;
import org.jxmpp.stringprep.XmppStringprepException;
@@ -56,9 +58,9 @@ public class XmppSenderConnection extends AbstractSenderConnection {
private final XMPPConnection connection;
private Message responseMessage;
private @Nullable Message responseMessage;
private String messageEncoding;
private String messageEncoding = XmppMessageReceiver.DEFAULT_MESSAGE_ENCODING;
private long receiveTimeout;
@@ -82,7 +84,7 @@ public class XmppSenderConnection extends AbstractSenderConnection {
}
/** Returns the response message, if any, for this connection. */
public Message getResponseMessage() {
public @Nullable Message getResponseMessage() {
return this.responseMessage;
}
@@ -117,7 +119,7 @@ public class XmppSenderConnection extends AbstractSenderConnection {
}
@Override
public String getErrorMessage() {
public @Nullable String getErrorMessage() {
return XmppTransportUtils.getErrorMessage(this.responseMessage);
}
@@ -185,17 +187,17 @@ public class XmppSenderConnection extends AbstractSenderConnection {
@Override
public Iterator<String> getResponseHeaderNames() {
return XmppTransportUtils.getHeaderNames(this.responseMessage);
return XmppTransportUtils.getHeaderNames(Objects.requireNonNull(this.responseMessage));
}
@Override
public Iterator<String> getResponseHeaders(String name) throws IOException {
return XmppTransportUtils.getHeaders(this.responseMessage, name);
return XmppTransportUtils.getHeaders(Objects.requireNonNull(this.responseMessage), name);
}
@Override
protected InputStream getResponseInputStream() throws IOException {
return new MessageInputStream(this.responseMessage, this.messageEncoding);
return new MessageInputStream(Objects.requireNonNull(this.responseMessage), this.messageEncoding);
}
}

View File

@@ -17,4 +17,7 @@
/**
* Package providing support for handling messages via XMPP.
*/
@NullMarked
package org.springframework.ws.transport.xmpp;
import org.jspecify.annotations.NullMarked;

View File

@@ -17,11 +17,13 @@
package org.springframework.ws.transport.xmpp.support;
import java.io.IOException;
import java.util.Objects;
import org.jivesoftware.smack.SmackException;
import org.jivesoftware.smack.XMPPException;
import org.jivesoftware.smack.tcp.XMPPTCPConnection;
import org.jivesoftware.smack.tcp.XMPPTCPConnectionConfiguration;
import org.jspecify.annotations.Nullable;
import org.jxmpp.jid.parts.Resourcepart;
import org.jxmpp.stringprep.XmppStringprepException;
@@ -43,19 +45,19 @@ public class XmppConnectionFactoryBean implements FactoryBean<XMPPTCPConnection>
private static final int DEFAULT_PORT = 5222;
private XMPPTCPConnection connection;
private @Nullable XMPPTCPConnection connection;
private String host;
private @Nullable String host;
private int port = DEFAULT_PORT;
private String serviceName;
private @Nullable String serviceName;
private String username;
private @Nullable String username;
private String password;
private @Nullable String password;
private String resource;
private @Nullable String resource;
/** Sets the server host to connect to. */
public void setHost(String host) {
@@ -91,6 +93,7 @@ public class XmppConnectionFactoryBean implements FactoryBean<XMPPTCPConnection>
@Override
public void afterPropertiesSet() throws XMPPException, IOException, SmackException {
Assert.hasText(this.host, "'host' must not be empty");
XMPPTCPConnectionConfiguration configuration = createConnectionConfiguration(this.host, this.port,
this.serviceName);
Assert.notNull(configuration, "'configuration' must not be null");
@@ -114,12 +117,12 @@ public class XmppConnectionFactoryBean implements FactoryBean<XMPPTCPConnection>
@Override
public void destroy() {
this.connection.disconnect();
Objects.requireNonNull(this.connection).disconnect();
}
@Override
public XMPPTCPConnection getObject() {
return this.connection;
return Objects.requireNonNull(this.connection);
}
@Override
@@ -138,8 +141,8 @@ public class XmppConnectionFactoryBean implements FactoryBean<XMPPTCPConnection>
* @param port the port to connect to
* @param serviceName the name of the service to connect to. May be {@code null}
*/
protected XMPPTCPConnectionConfiguration createConnectionConfiguration(String host, int port, String serviceName)
throws XmppStringprepException {
protected XMPPTCPConnectionConfiguration createConnectionConfiguration(String host, int port,
@Nullable String serviceName) throws XmppStringprepException {
Assert.hasText(host, "'host' must not be empty");
if (StringUtils.hasText(serviceName)) {
return XMPPTCPConnectionConfiguration.builder()

View File

@@ -23,6 +23,7 @@ import java.util.Iterator;
import org.jivesoftware.smack.packet.Message;
import org.jivesoftware.smackx.jiveproperties.JivePropertiesManager;
import org.jspecify.annotations.Nullable;
import org.springframework.util.Assert;
import org.springframework.ws.transport.xmpp.XmppTransportConstants;
@@ -49,11 +50,11 @@ public abstract class XmppTransportUtils {
return uri.getSchemeSpecificPart();
}
public static boolean hasError(Message message) {
public static boolean hasError(@Nullable Message message) {
return message != null && Message.Type.error.equals(message.getType());
}
public static String getErrorMessage(Message message) {
public static @Nullable String getErrorMessage(@Nullable Message message) {
if (message == null || !Message.Type.error.equals(message.getType())) {
return null;
}

View File

@@ -17,4 +17,7 @@
/**
* Support classes for handling messages via XMPP.
*/
@NullMarked
package org.springframework.ws.transport.xmpp.support;
import org.jspecify.annotations.NullMarked;