Java tutorial
/* * Copyright 2002-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.integration.xmpp.presence; import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.builder.ToStringBuilder; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.jivesoftware.smack.RosterListener; import org.jivesoftware.smack.XMPPConnection; import org.jivesoftware.smack.packet.Presence; import org.springframework.context.Lifecycle; import org.springframework.integration.Message; import org.springframework.integration.MessageChannel; import org.springframework.integration.core.MessagingTemplate; import org.springframework.integration.endpoint.AbstractEndpoint; import org.springframework.integration.mapping.InboundMessageMapper; import java.util.Collection; /** * Describes an endpoint that is able to login as usual with a {@link org.springframework.integration.xmpp.XmppConnectionFactory} and then emit {@link org.springframework.integration.Message}s when a particular event happens to the logged in users {@link org.jivesoftware.smack.Roster}. We try * and generically propagate these events. In practical terms, there are a few events worth being notified of: <ul> <li>the {@link org.jivesoftware.smack.packet.Presence} of a user in the {@link org.jivesoftware.smack.Roster} has changed.</li> <li>the actual makeup of the logged-in user's {@link * org.jivesoftware.smack.Roster} has changed: entries added, deleted, etc.</li> </ul> * * @author Josh Long * @since 2.0 */ public class XmppRosterEventMessageDrivenEndpoint extends AbstractEndpoint implements Lifecycle { private static final Log logger = LogFactory.getLog(XmppRosterEventMessageDrivenEndpoint.class); private volatile MessageChannel requestChannel; private volatile XMPPConnection xmppConnection; private InboundMessageMapper<Presence> messageMapper; private final MessagingTemplate messagingTemplate = new MessagingTemplate(); /** * This will be injected or configured via a <em>xmpp-connection-factory</em> element. * * @param xmppConnection the connection */ public void setXmppConnection(final XMPPConnection xmppConnection) { this.xmppConnection = xmppConnection; } /** * @param requestChannel the channel on which the inbound message should be sent */ public void setRequestChannel(final MessageChannel requestChannel) { this.messagingTemplate.setDefaultChannel(requestChannel); this.requestChannel = requestChannel; } @Override protected void doStart() { logger.debug("start: " + xmppConnection.isConnected() + ":" + xmppConnection.isAuthenticated()); } @Override protected void doStop() { if (this.xmppConnection.isConnected()) { logger.debug("shutting down " + XmppRosterEventMessageDrivenEndpoint.class.getName() + "."); this.xmppConnection.disconnect(); } } @Override protected void onInit() throws Exception { if (null == this.messageMapper) { this.messageMapper = new XmppPresenceMessageMapper(); } this.messagingTemplate.afterPropertiesSet(); this.xmppConnection.getRoster().addRosterListener(new EventForwardingRosterListener()); } /** * Called whenever an event happesn related to the {@link org.jivesoftware.smack.Roster} * * @param presence the {@link org.jivesoftware.smack.packet.Presence} object representing the new state (optional) */ protected void forwardRosterEventMessage(Presence presence) { try { Message<?> msg = this.messageMapper.toMessage(presence); messagingTemplate.send(requestChannel, msg); } catch (Exception e) { logger.error("Failed to map packet to message ", e); } } public void setMessageMapper(InboundMessageMapper<Presence> messageMapper) { this.messageMapper = messageMapper; } /** * Subscribes to a given {@link org.jivesoftware.smack.Roster}s events and forwards them to components on the bus. */ class EventForwardingRosterListener implements RosterListener { public void entriesAdded(final Collection<String> entries) { logger.debug("entries added: " + StringUtils.join(entries.iterator(), ",")); } public void entriesUpdated(final Collection<String> entries) { logger.debug("entries updated: " + StringUtils.join(entries.iterator(), ",")); } public void entriesDeleted(final Collection<String> entries) { logger.debug("entries deleted: " + StringUtils.join(entries.iterator(), ",")); } public void presenceChanged(final Presence presence) { logger.debug("presence changed: " + ToStringBuilder.reflectionToString(presence)); forwardRosterEventMessage(presence); } } }