/* * Copyright 2014-2016 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.integration.mail.dsl; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.LinkedList; import java.util.List; import java.util.Properties; import java.util.concurrent.Executor; import java.util.function.Consumer; import java.util.function.Function; import javax.mail.Authenticator; import javax.mail.Message; import javax.mail.Part; import javax.mail.Session; import javax.mail.internet.MimeMessage; import org.aopalliance.aop.Advice; import org.springframework.expression.Expression; import org.springframework.integration.dsl.ComponentsRegistration; import org.springframework.integration.dsl.MessageProducerSpec; import org.springframework.integration.expression.FunctionExpression; import org.springframework.integration.mail.ImapIdleChannelAdapter; import org.springframework.integration.mail.ImapMailReceiver; import org.springframework.integration.mail.SearchTermStrategy; import org.springframework.integration.mapping.HeaderMapper; import org.springframework.integration.support.PropertiesBuilder; import org.springframework.integration.transaction.TransactionInterceptorBuilder; import org.springframework.integration.transaction.TransactionSynchronizationFactory; import org.springframework.transaction.PlatformTransactionManager; import org.springframework.transaction.interceptor.DefaultTransactionAttribute; import org.springframework.transaction.interceptor.TransactionInterceptor; import org.springframework.util.Assert; /** * A {@link MessageProducerSpec} for a {@link ImapIdleChannelAdapter}. * * @author Gary Russell * @author Artem Bilan * * @since 5.0 */ public class ImapIdleChannelAdapterSpec extends MessageProducerSpec<ImapIdleChannelAdapterSpec, ImapIdleChannelAdapter> implements ComponentsRegistration { private final ImapMailReceiver receiver; private final Collection<Object> componentsToRegister = new ArrayList<Object>(); private final List<Advice> adviceChain = new LinkedList<>(); protected final boolean externalReceiver; private boolean sessionProvided; ImapIdleChannelAdapterSpec(ImapMailReceiver receiver) { this(receiver, false); } ImapIdleChannelAdapterSpec(ImapMailReceiver receiver, boolean externalReceiver) { super(new ImapIdleChannelAdapter(receiver)); this.target.setAdviceChain(this.adviceChain); this.receiver = receiver; this.componentsToRegister.add(receiver); this.externalReceiver = externalReceiver; } /** * Configure a SpEL expression to select messages. The root object for the expression * evaluation is a {@link javax.mail.internet.MimeMessage} which should return a boolean * result (true means select the message). * @param selectorExpression the selectorExpression. * @return the spec. */ public ImapIdleChannelAdapterSpec selectorExpression(String selectorExpression) { return selectorExpression(PARSER.parseExpression(selectorExpression)); } /** * Configure an {@link Expression} to select messages. The root object for the expression * evaluation is a {@link javax.mail.internet.MimeMessage} which should return a boolean * result (true means select the message). * @param selectorExpression the selectorExpression. * @return the spec. */ public ImapIdleChannelAdapterSpec selectorExpression(Expression selectorExpression) { assertReceiver(); this.receiver.setSelectorExpression(selectorExpression); return this; } private void assertReceiver() { Assert.state(!this.externalReceiver, "An external 'receiver' [" + this.receiver + "] can't be modified."); } /** * Configure a {@link Function} to select messages. The argument for the function * is a {@link javax.mail.internet.MimeMessage}; {@code apply} returns a boolean * result (true means select the message). * @param selectorFunction the selectorFunction. * @return the spec. * @see FunctionExpression */ public ImapIdleChannelAdapterSpec selector(Function<MimeMessage, Boolean> selectorFunction) { return selectorExpression(new FunctionExpression<MimeMessage>(selectorFunction)); } /** * A Java Mail {@link Session} to use. * @param session the session. * @return the spec. * @see ImapMailReceiver#setSession(Session) */ public ImapIdleChannelAdapterSpec session(Session session) { assertReceiver(); this.receiver.setSession(session); this.sessionProvided = true; return this; } /** * @param javaMailProperties the javaMailProperties. * @return the spec. * @see ImapMailReceiver#setJavaMailProperties(Properties) */ public ImapIdleChannelAdapterSpec javaMailProperties(Properties javaMailProperties) { assertReceiver(); assertSession(); this.receiver.setJavaMailProperties(javaMailProperties); return this; } private void assertSession() { Assert.state(!this.sessionProvided, "Neither 'javaMailProperties' nor 'javaMailAuthenticator' " + "references are allowed when a 'session' reference has been provided."); } /** * Configure the {@code javaMailProperties} by invoking a {@link Consumer} callback which * is invoked with a {@link PropertiesBuilder}. * @param configurer the configurer. * @return the spec. * @see ImapMailReceiver#setJavaMailProperties(Properties) */ public ImapIdleChannelAdapterSpec javaMailProperties(Consumer<PropertiesBuilder> configurer) { PropertiesBuilder properties = new PropertiesBuilder(); configurer.accept(properties); return javaMailProperties(properties.get()); } /** * @param javaMailAuthenticator the javaMailAuthenticator. * @return the spec. * @see ImapMailReceiver#setJavaMailAuthenticator(Authenticator) */ public ImapIdleChannelAdapterSpec javaMailAuthenticator(Authenticator javaMailAuthenticator) { assertReceiver(); assertSession(); this.receiver.setJavaMailAuthenticator(javaMailAuthenticator); return this; } /** * @param maxFetchSize the maxFetchSize. * @return the spec. * @see ImapMailReceiver#setMaxFetchSize(int) */ public ImapIdleChannelAdapterSpec maxFetchSize(int maxFetchSize) { assertReceiver(); this.receiver.setMaxFetchSize(maxFetchSize); return this; } /** * @param shouldDeleteMessages the shouldDeleteMessages. * @return the spec. * @see ImapMailReceiver#setShouldDeleteMessages(boolean) */ public ImapIdleChannelAdapterSpec shouldDeleteMessages(boolean shouldDeleteMessages) { assertReceiver(); this.receiver.setShouldDeleteMessages(shouldDeleteMessages); return this; } /** * @param searchTermStrategy the searchTermStrategy. * @return the spec. * @see ImapMailReceiver#setSearchTermStrategy(SearchTermStrategy) */ public ImapIdleChannelAdapterSpec searchTermStrategy(SearchTermStrategy searchTermStrategy) { assertReceiver(); this.receiver.setSearchTermStrategy(searchTermStrategy); return this; } /** * @param shouldMarkMessagesAsRead the shouldMarkMessagesAsRead. * @return the spec. * @see ImapMailReceiver#setShouldMarkMessagesAsRead(Boolean) */ public ImapIdleChannelAdapterSpec shouldMarkMessagesAsRead(boolean shouldMarkMessagesAsRead) { assertReceiver(); this.receiver.setShouldMarkMessagesAsRead(shouldMarkMessagesAsRead); return this; } /** * Set the name of the flag to use to flag messages when the server does * not support \Recent but supports user flags; * default {@value ImapMailReceiver#DEFAULT_SI_USER_FLAG}. * @param userFlag the flag. * @return the spec. * @see ImapMailReceiver#setUserFlag(String) */ public ImapIdleChannelAdapterSpec userFlag(String userFlag) { assertReceiver(); this.receiver.setUserFlag(userFlag); return _this(); } /** * Set the header mapper; if a header mapper is not provided, the message payload is * a {@link MimeMessage}, when provided, the headers are mapped and the payload is * the {@link MimeMessage} content. * @param headerMapper the header mapper. * @return the spec. * @see ImapMailReceiver#setUserFlag(String) * @see #embeddedPartsAsBytes(boolean) */ public ImapIdleChannelAdapterSpec headerMapper(HeaderMapper<MimeMessage> headerMapper) { assertReceiver(); this.receiver.setHeaderMapper(headerMapper); return _this(); } /** * When a header mapper is provided determine whether an embedded {@link Part} (e.g * {@link Message} or {@link javax.mail.Multipart} content is rendered as a byte[] in * the payload. Otherwise, leave as a {@link Part}. These objects are not suitable for * downstream serialization. Default: true. * <p> * This has no effect if there is no header mapper, in that case the payload is the * {@link MimeMessage}. * @param embeddedPartsAsBytes the embeddedPartsAsBytes to set. * @return the spec. * @see #headerMapper(HeaderMapper) */ public ImapIdleChannelAdapterSpec embeddedPartsAsBytes(boolean embeddedPartsAsBytes) { assertReceiver(); this.receiver.setEmbeddedPartsAsBytes(embeddedPartsAsBytes); return _this(); } /** * Configure a {@link TransactionSynchronizationFactory}. Usually used to synchronize * message deletion with some external transaction manager. * @param transactionSynchronizationFactory the transactionSynchronizationFactory. * @return the spec. */ public ImapIdleChannelAdapterSpec transactionSynchronizationFactory( TransactionSynchronizationFactory transactionSynchronizationFactory) { this.target.setTransactionSynchronizationFactory(transactionSynchronizationFactory); return this; } /** * Configure a chain of {@link Advice} objects for message delivery, applied to * the downstream flow. * @param adviceChain the advice chain. * @return the spec. */ public ImapIdleChannelAdapterSpec adviceChain(Advice... adviceChain) { this.adviceChain.addAll(Arrays.asList(adviceChain)); return this; } /** * Specify a {@link TransactionInterceptor} {@link Advice} with the provided * {@code PlatformTransactionManager} and default {@link DefaultTransactionAttribute} * for the downstream flow. * @param transactionManager the {@link PlatformTransactionManager} to use. * @return the spec. */ public ImapIdleChannelAdapterSpec transactional(PlatformTransactionManager transactionManager) { return transactional(new TransactionInterceptorBuilder(false) .transactionManager(transactionManager) .build()); } /** * Specify a {@link TransactionInterceptor} {@link Advice} for the * downstream flow. * @param transactionInterceptor the {@link TransactionInterceptor} to use. * @return the spec. * @see TransactionInterceptorBuilder */ public ImapIdleChannelAdapterSpec transactional(TransactionInterceptor transactionInterceptor) { return adviceChain(transactionInterceptor); } /** * Specify a {@link TransactionInterceptor} {@link Advice} with default * {@code PlatformTransactionManager} and {@link DefaultTransactionAttribute} for the * downstream flow. * @return the spec. */ public ImapIdleChannelAdapterSpec transactional() { TransactionInterceptor transactionInterceptor = new TransactionInterceptorBuilder(false).build(); this.componentsToRegister.add(transactionInterceptor); return transactional(transactionInterceptor); } /** * Specify a task executor to be used to send messages to the downstream flow. * @param sendingTaskExecutor the sendingTaskExecutor. * @return the spec. * @see ImapIdleChannelAdapter#setSendingTaskExecutor(Executor) */ public ImapIdleChannelAdapterSpec sendingTaskExecutor(Executor sendingTaskExecutor) { this.target.setSendingTaskExecutor(sendingTaskExecutor); return this; } /** * @param shouldReconnectAutomatically the shouldReconnectAutomatically. * @return the spec. * @see ImapIdleChannelAdapter#setShouldReconnectAutomatically(boolean) */ public ImapIdleChannelAdapterSpec shouldReconnectAutomatically(boolean shouldReconnectAutomatically) { this.target.setShouldReconnectAutomatically(shouldReconnectAutomatically); return this; } @Override public Collection<Object> getComponentsToRegister() { return this.componentsToRegister; } }