/* * Copyright 2013-2015 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.xd.dirt.plugins.job; import java.util.HashMap; import java.util.Map; import org.springframework.messaging.MessageChannel; import org.springframework.messaging.SubscribableChannel; import org.springframework.util.Assert; import org.springframework.xd.dirt.integration.bus.BusUtils; import org.springframework.xd.dirt.integration.bus.MessageBus; import org.springframework.xd.dirt.plugins.AbstractJobPlugin; import org.springframework.xd.dirt.plugins.job.support.listener.XDJobListenerConstants; import org.springframework.xd.module.core.Module; /** * Plugin to enable the registration of out of the box job listeners. * * @author Ilayaperumal Gopinathan * @author Gary Russell * @since 1.0 */ public class JobEventsListenerPlugin extends AbstractJobPlugin implements XDJobListenerConstants { private static final String JOB_TAP_CHANNEL_PREFIX = BusUtils.TAP_CHANNEL_PREFIX + JOB_CHANNEL_PREFIX; public JobEventsListenerPlugin(MessageBus messageBus) { super(messageBus); } @Override public void postProcessModule(Module module) { boolean disableListeners = true; Map<String, String> eventChannels = getEventListenerChannels(module.getDescriptor().getGroup()); for (Map.Entry<String, String> entry : eventChannels.entrySet()) { MessageChannel eventChannel = module.getComponent(entry.getKey(), SubscribableChannel.class); if (eventChannel != null) { messageBus.bindPubSubProducer(entry.getValue(), eventChannel, null); disableListeners = false; } } // Bind aggregatedEvents channel if at least one of the event listeners channels is already bound. if (!disableListeners) { bindAggregatedEventsChannel(module); } } /** * @param jobName the job name. * @return the map containing the entries for the channels used by the job listeners with bean name of the channel * as the key and channel name as the value. */ public static Map<String, String> getEventListenerChannels(String jobName) { Map<String, String> eventListenerChannels = new HashMap<String, String>(); Assert.notNull(jobName, "Job name should not be null"); eventListenerChannels.put(XD_JOB_EXECUTION_EVENTS_CHANNEL, getEventListenerChannelName(jobName, JOB_EXECUTION_EVENTS_SUFFIX)); eventListenerChannels.put(XD_STEP_EXECUTION_EVENTS_CHANNEL, getEventListenerChannelName(jobName, STEP_EXECUTION_EVENTS_SUFFIX)); eventListenerChannels.put(XD_CHUNK_EVENTS_CHANNEL, getEventListenerChannelName(jobName, CHUNK_EVENTS_SUFFIX)); eventListenerChannels.put(XD_ITEM_EVENTS_CHANNEL, getEventListenerChannelName(jobName, ITEM_EVENTS_SUFFIX)); eventListenerChannels.put(XD_SKIP_EVENTS_CHANNEL, getEventListenerChannelName(jobName, SKIP_EVENTS_SUFFIX)); return eventListenerChannels; } private static String getEventListenerChannelName(String jobName, String channelNameSuffix) { return String.format("%s%s.%s", JOB_TAP_CHANNEL_PREFIX, jobName, channelNameSuffix); } /** * @param jobName the job name. * @return the aggregated event channel name. */ public static String getEventListenerChannelName(String jobName) { return String.format("%s%s", JOB_TAP_CHANNEL_PREFIX, jobName); } private void bindAggregatedEventsChannel(Module module) { String jobName = module.getDescriptor().getGroup(); MessageChannel aggEventsChannel = module.getComponent(XD_AGGREGATED_EVENTS_CHANNEL, SubscribableChannel.class); Assert.notNull(aggEventsChannel, "The pub/sub aggregatedEvents channel should be available in the module context."); messageBus.bindPubSubProducer(getEventListenerChannelName(jobName), aggEventsChannel, null); } @Override public void removeModule(Module module) { Map<String, String> eventListenerChannels = getEventListenerChannels(module.getDescriptor().getGroup()); for (Map.Entry<String, String> channelEntry : eventListenerChannels.entrySet()) { messageBus.unbindProducers(channelEntry.getValue()); } // unbind aggregatedEvents channel messageBus.unbindProducers(getEventListenerChannelName(module.getDescriptor().getGroup())); } }