/** *
 * OLAT - Online Learning and Training
 * http://www.olat.org
 * 
 * This software is protected by the OLAT software license. 
 * Use is subject to license terms.
 * See LICENSE.TXT in this distribution for details.
 * 
 * Copyright (c) 2003 OLAT Zentrum, University of Zurich, Switzerland.
 * All rights reserved.
 * 
* Description:
* TODO: Class Description for JabberClientSmack * *

* @version $Revision: 1.8 $ * Initial Date: 14.10.2004 * Last modified: $Date: 2004/10/22 20:35:51 $ * * @author guido */ package org.olat.instantMessaging; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import java.util.regex.Matcher; import java.util.regex.Pattern; import org.jivesoftware.smack.PacketCollector; import org.jivesoftware.smack.PacketListener; import org.jivesoftware.smack.Roster; import org.jivesoftware.smack.RosterEntry; import org.jivesoftware.smack.RosterGroup; 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.IQ; import org.jivesoftware.smack.packet.Message; import org.jivesoftware.smack.packet.Packet; import org.jivesoftware.smack.packet.Presence; import org.jivesoftware.smack.packet.RosterPacket; /** * @author guido * * TODO To change the template for this generated type comment go to * Window - Preferences - Java - Code Style - Code Templates */ public class InstantMessagingClient { // username is olat global unique username private String username; //password is auto generated and only used for instant messaging private String password; private XMPPConnection connection = null; private Roster roster = null; // null means 'not connected' private Presence.Mode presenceMode = null; private Message message = null; // the jabber id like username@olat.ch private String jid; private String jabberServer; private List subscribedUsers = new ArrayList(); protected static final String OLATBUDDIES = "OLAT-Buddies"; private boolean collaborationDisabled = false; private boolean isConnected; private boolean flashClientIsRunning = false; /** * * @param username * @param password */ public InstantMessagingClient(String username, String password) { this.username = username; this.password = password; jabberServer = InstantMessagingModule.getServername(); connect(); } /** * connect to the JabberServer * */ public void connect() { try { //Debug enables a java window with all traffic between client //and server. XMPPConnection.DEBUG_ENABLED = true; connection = new XMPPConnection(jabberServer); connection.login(username, password); isConnected = connection.isConnected(); if(isConnected){ roster = connection.getRoster(); //subscription accept all = 0 roster.setSubscriptionMode(0); setStatus(Presence.Mode.AVAILABLE); addMessageListener(); addSubscriptionListener(); } } catch (XMPPException e) { isConnected = false; e.printStackTrace(); } } /** * change jabber status. * Example: sendPresencePacket(Presence.Type.AVAILABLE, req.getParameter("status"), 1, Presence.Mode.AWAY); * @param type * @param status * @param priority * @param mode * */ public void sendPresence(Presence.Type type, String status, int priority, Presence.Mode mode){ setStatus(mode); Presence presence = new Presence(type); if (status == null){ status = "TODO, default statusmeldug fuer jeden mode"; presence.setStatus(status); }else{ presence.setStatus(status); } presence.setPriority(priority); if (mode != null) presence.setMode(mode); connection.sendPacket(presence); } /** * Each client listens to it's own messages * */ private void addMessageListener(){ PacketFilter filter = new PacketTypeFilter(Message.class); connection.createPacketCollector(filter); PacketListener myListener = new PacketListener() { public void processPacket(Packet packet) { Message jabbmessage = (Message)packet; if(jabbmessage.getType() == Message.Type.CHAT || jabbmessage.getType() == Message.Type.NORMAL) if(!collaborationDisabled){ message = jabbmessage; }else message = null; } }; connection.addPacketListener(myListener, filter); } /** * By adding this methode (right now added to the contructor) we do * have auto subscription. All subscribe packets get automatically * answered by a subscribed packet. */ private void addSubscriptionListener(){ PacketFilter filter = new PacketTypeFilter(Presence.class); connection.createPacketCollector(filter); PacketListener myListener = new PacketListener() { public void processPacket(Packet packet) { Presence presence = (Presence)packet; if(presence.getType() == Presence.Type.SUBSCRIBE){ Presence response = new Presence(Presence.Type.SUBSCRIBED); response.setTo(presence.getFrom()); System.out.println("subscribed to: "+presence.getFrom()); connection.sendPacket(response); //ask also for subscription if(!subscribedUsers.contains(presence.getFrom())){ response = null; response = new Presence(Presence.Type.SUBSCRIBE); response.setTo(presence.getFrom()); connection.sendPacket(response); //update the roster with the new user RosterPacket rosterPacket = new RosterPacket(); rosterPacket.setType(IQ.Type.SET); RosterPacket.Item item = new RosterPacket.Item(presence.getFrom(),parseName(presence.getFrom())); item.addGroupName(OLATBUDDIES); item.setItemType(RosterPacket.ItemType.BOTH); //item.setItemStatus(RosterPacket.ItemStatus.fromString()); rosterPacket.addRosterItem(item); connection.sendPacket(rosterPacket); } } if(presence.getType() == Presence.Type.SUBSCRIBED){ subscribedUsers.add(presence.getFrom()); } } }; connection.addPacketListener(myListener, filter); } /** * For unsubscription we have to create a packet like: * * * * * * @param String a valid jid like guido@jabber.org */ public void removeSubscription(String username){ RosterPacket rosterPacket = new RosterPacket(); rosterPacket.setType(IQ.Type.SET); RosterPacket.Item item = new RosterPacket.Item(username+"@"+jabberServer,parseName(jid)); item.setItemType(RosterPacket.ItemType.REMOVE); rosterPacket.addRosterItem(item); connection.sendPacket(rosterPacket); } /** * * @return message */ public Message getMessage(){ return this.message; } /** * reset the message object * users do this after reading a message in olat */ public void resetMessage(){ this.message = null; } /** * @return Returns the jid. */ public String getJid() { String jid = this.username+"@"+jabberServer; return jid; } /** * @return Returns the status. */ public String getStatus() { if(presenceMode != null){ return presenceMode.toString(); }else{ return Presence.Type.UNAVAILABLE.toString(); } } /** * @param status The status to set. */ public void setStatus(Presence.Mode status) { this.presenceMode = status; } /** * Used for communication with the flash jabber client. * May gets replaced with javascript to flash communication * @param chatpartner * @param message */ public void sendChatParamsToFlashClient(String chatpartner, String message){ StringBuffer out = new StringBuffer(); out.append("chatpartner:"); out.append(chatpartner); out.append(","); out.append("message:"+message); sendCustomMessagePacket(out.toString()); } public void sendConferenceParamsToFlashClient(String roomName){ String roomname = "chatroom:"+roomName; sendCustomMessagePacket(roomname); } /** * On OpenIm on the windows plattform, der type headline wird automatisch nach * chat gewcheselt durch den server, grrrr. Wie sieht es unter jabberd aus? * @param body of the custom message */ private void sendCustomMessagePacket(String msgBody){ //Chat chat = connection.createChat(olatUsername+"@"+JABBERHOST+"/xiff"); //Message customMsg = chat.createMessage(); Message customMsg = new Message(); //custom messages are sent only to our flash client with ressource /xiff customMsg.setTo(username+"@"+jabberServer+"/xiff"); customMsg.setType(Message.Type.HEADLINE); customMsg.setBody(msgBody); System.out.println("Custom message: "+customMsg.toXML()); connection.sendPacket(customMsg); } /** * @return Returns the roster. */ public Roster getRoster() { return roster; } /** * Close the connection to the server * */ public void closeConnection(){ connection.close(); } /** * Ask an other online user to subscribe to their roster * @param username */ public void subscribeToUser(String username){ Presence presence = new Presence(Presence.Type.SUBSCRIBE); presence.setTo(username+"@"+jabberServer); connection.sendPacket(presence); } /** * @param string * @param string2 */ public void subscribeToUser(String username, String groupname) { Presence presence = new Presence(Presence.Type.SUBSCRIBE); presence.setTo(username+"@"+jabberServer); connection.sendPacket(presence); RosterPacket rosterPacket = new RosterPacket(); rosterPacket.setType(IQ.Type.SET); RosterPacket.Item item = new RosterPacket.Item(username+"@"+jabberServer,username); item.addGroupName(groupname); item.setItemType(RosterPacket.ItemType.BOTH); rosterPacket.addRosterItem(item); connection.sendPacket(rosterPacket); } /** * @param an jabber jid like guido@swissjabber.org * @return returns just the name "guido" without the rest */ private String parseName(String XMPPAddress) { if (XMPPAddress == null) { return null; } int atIndex = XMPPAddress.indexOf("@"); if (atIndex <= 0) { return ""; } else { return XMPPAddress.substring(0, atIndex); } } /** * * @param reason The reason why this user is not allowd to chat e.g. doing test * By setting the third param to 10 all messages should be send to * this client even if other clients are up. So we have full control over them. */ public void disableCollaboration(String reason){ sendPresence(Presence.Type.AVAILABLE, reason, 10, Presence.Mode.DO_NOT_DISTURB); collaborationDisabled = true; } public void enableCollaboration(){ collaborationDisabled = false; } /** * indicates wheater the user has a new Message or not * @return */ public boolean hasMessage(){ if(getMessage()!= null){ return true; }else return false; } /** * * @return a String representing the online buddies out of the * number of total buddies */ public String buddyCountOnline() { int onlineBuddyEntries = connection.getRoster().getEntryCount(); int allBuddies = onlineBuddyEntries; for (Iterator l = connection.getRoster().getEntries(); l.hasNext();) { RosterEntry entry = (RosterEntry) l.next(); Presence presence = connection.getRoster().getPresence(entry.getUser()); if (presence == null) onlineBuddyEntries--; } return "(" + onlineBuddyEntries + "/" + allBuddies + ")"; } /** * * @param groupname * @return a String representing the online buddies out of the * number of total buddies for a single group */ public String buddyCountOnlineForGroup(String groupname){ RosterGroup rosterGroup = connection.getRoster().getGroup(groupname); int buddyEntries = rosterGroup.getEntryCount(); int allBuddies = buddyEntries; for(Iterator I = rosterGroup.getEntries();I.hasNext();){ RosterEntry entry = (RosterEntry) I.next(); Presence presence = connection.getRoster().getPresence(entry.getUser()); if (presence == null) buddyEntries--; } return "(" + buddyEntries + "/" + allBuddies + ")"; } public String getUserPresence(String jid){ Presence presence = connection.getRoster().getPresence(jid); String imageName = "offline"; if (presence != null) imageName = presence.getMode().toString(); return imageName; } /** * * @return the message body without newline and quotes */ public String getMessageFormatted(){ String message = this.message.getBody(); String patternNewline = "\n"; String patternCrNewline = "\r\n"; String patternQuote = "'"; String patternDQuote = "\""; String clean = null; Pattern r = Pattern.compile(patternNewline); Matcher m = r.matcher(message); clean = m.replaceAll("
"); r = Pattern.compile(patternCrNewline); m = r.matcher(clean); clean = m.replaceAll("
"); r = Pattern.compile(patternQuote); m = r.matcher(clean); clean = m.replaceAll(" "); r = Pattern.compile(patternDQuote); m = r.matcher(clean); clean = m.replaceAll(""); return clean; } /** * @return Returns the password. */ public String getPassword() { return this.password; } /** * @return Returns the username. */ public String getUsername() { return this.username; } /** * @return Returns true when user is connected to server */ public boolean isConnected() { return isConnected; } public boolean getFlashClientIsRunning(){ return this.flashClientIsRunning; } public void setFlashClientIsRunning(boolean isRunning){ this.flashClientIsRunning = isRunning; } }