Phase 1 of large refactoring. Removing dead code, bug fixes, updates to JDK 1.5.

git-svn-id: http://svn.igniterealtime.org/svn/repos/smack/trunk@4511 b35dd754-fafc-0310-a699-88a17e54d16e
This commit is contained in:
Matt Tucker 2006-07-17 08:39:08 +00:00 committed by matt
parent 1a08715f67
commit bbbfe09c31
62 changed files with 291 additions and 3524 deletions

View File

@ -1,42 +0,0 @@
#! /bin/sh
# //--------------------------------------------------------------------------//
# // $RCSfile$
# // $Revision$
# // $Date$
# //
# // Standard Jive Software ant file. Do not change this file. If you do,
# // you will have seven years of bad luck and bad builds.
# //--------------------------------------------------------------------------//
# //--------------------------------------------------------------------------//
# // Uncomment the following lines if you wish to set JAVA_HOME in this script
# //--------------------------------------------------------------------------//
# JAVA_HOME=
# EXPORT JAVA_HOME
# //--------------------------------------------------------------------------//
# // Check for the JAVA_HOME environment variable //
# //--------------------------------------------------------------------------//
if [ "$JAVA_HOME" != "" ] ; then
# //----------------------------------------------------------------------//
# // Create Ant's classpath //
# //----------------------------------------------------------------------//
CP=$JAVA_HOME/lib/tools.jar:../../../build/ant.jar
# //----------------------------------------------------------------------//
# // Run ant //
# //----------------------------------------------------------------------//
$JAVA_HOME/bin/java -classpath $CP -Dant.home=. org.apache.tools.ant.Main $@
else
# //----------------------------------------------------------------------//
# // No JAVA_HOME error message //
# //----------------------------------------------------------------------//
echo "Jive Forums Build Error:"
echo ""
echo "The JAVA_HOME environment variable is not set. JAVA_HOME should point"
echo "to your java directory, ie: /usr/local/bin/jdk1.3. You can set"
echo "this via the command line like so:"
echo " export JAVA_HOME=/usr/local/bin/jdk1.3"
fi

View File

@ -1,52 +0,0 @@
@echo off
rem //------------------------------------------------------------------------//
rem // $RCSfile$
rem // $Revision$
rem // $Date$
rem //
rem // Standard Jive Software ant.bat file. Do not change this file. If you do,
rem // you will have seven years of bad luck and bad builds.
rem //------------------------------------------------------------------------//
rem //------------------------------------------------------------------------//
rem // Uncomment the following if you wish to set JAVA_HOME in this bat file:
rem //------------------------------------------------------------------------//
rem SET JAVA_HOME=
rem //------------------------------------------------------------------------//
rem // Check for the JAVA_HOME environment variable
rem //------------------------------------------------------------------------//
if "%JAVA_HOME%" == "" goto noJavaHome
rem //------------------------------------------------------------------------//
rem // Make the correct classpath (should include the java jars and the
rem // Ant jars)
rem //------------------------------------------------------------------------//
SET CP=%JAVA_HOME%\lib\tools.jar;..\..\..\build\ant.jar
rem //------------------------------------------------------------------------//
rem // Run Ant
rem // Note for Win 98/95 users: You need to change "%*" in the following
rem // line to be "%1 %2 %3 %4 %5 %6 %7 %8 %9"
rem //------------------------------------------------------------------------//
%JAVA_HOME%\bin\java -Xms32m -Xmx128m -classpath %CP% -Dant.home=. org.apache.tools.ant.Main %*
goto end
rem //------------------------------------------------------------------------//
rem // Error message for missing JAVA_HOME
rem //------------------------------------------------------------------------//
:noJavaHome
echo.
echo Jive Forums Build Error:
echo.
echo The JAVA_HOME environment variable is not set. JAVA_HOME should point to
echo your java directory, ie: c:\jdk1.3.1. You can set this via the command
echo line like so:
echo SET JAVA_HOME=c:\jdk1.3
echo.
goto end
:end

View File

@ -1,91 +0,0 @@
<?xml version="1.0"?>
<!--
$RCSfile$
$Revision$
$Date$
-->
<project name="WebChat" default="all" basedir="..">
<property file="${basedir}/build/webchat-build.properties" />
<property name="smack.home" value="${basedir}/../../../smack" />
<property name="compile.dir" value="${basedir}/build/temp" />
<property name="jar.dest.dir" value="${basedir}/build/WEB-INF/lib" />
<property name="jar.name" value="webchat" />
<property name="war.dest.dir" value="${basedir}" />
<property name="war.name" value="webchat" />
<path id="dependencies">
<!-- build jars -->
<fileset dir="${smack.home}" includes="smack.jar" />
<fileset dir="${basedir}/build/lib" includes="*.jar" />
</path>
<patternset id="web.filetypes">
<include name="**/*.jsp" />
<include name="**/*.js" />
<include name="**/*.html" />
<include name="**/*.gif" />
<include name="**/*.css" />
</patternset>
<target name="init">
<mkdir dir="${compile.dir}" />
<mkdir dir="${jar.dest.dir}" />
<!-- call smack jar process -->
<ant antfile="build/build.xml" dir="${smack.home}" target="jar" inheritAll="false" />
</target>
<target name="clean">
<delete dir="${compile.dir}" />
<delete dir="${jar.dest.dir}" />
<!-- call smack jar process -->
<ant antfile="build/build.xml" dir="${smack.home}" target="clean" inheritAll="false" />
</target>
<target name="compile" depends="init">
<javac
destdir="${compile.dir}"
includeAntRuntime="no"
debug="on"
classpathref="dependencies"
>
<src path="${basedir}/source/java" />
</javac>
</target>
<target name="jar" depends="compile">
<jar destfile="${jar.dest.dir}/${jar.name}.jar"
basedir="${compile.dir}"
includes="**/*.class"
/>
</target>
<target name="war" depends="jar">
<war warfile="${war.dest.dir}/${war.name}.war"
webxml="${basedir}/source/config/WEB-INF/web.xml"
>
<lib dir="${jar.dest.dir}" includes="*.jar" />
<lib dir="${smack.home}" includes="smack.jar" />
<zipfileset dir="${basedir}/source/web">
<patternset refid="web.filetypes" />
</zipfileset>
</war>
</target>
<target name="deploywar" depends="war">
<copy todir="${deploy.war.dir}" overwrite="${overwrite}">
<fileset dir="${war.dest.dir}" includes="${war.name}.war" />
</copy>
</target>
</project>

Binary file not shown.

View File

@ -1,167 +0,0 @@
<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd">
<web-app>
<display-name>WebChat</display-name>
<description>Smack-powered WebChat Application</description>
<context-param>
<param-name>host</param-name>
<param-value>jivesoftware.com</param-value>
</context-param>
<!--
*******************
ALL OF THE FOLLOWING context-params are optional, and are listed with their
default values. Since they are optional, they needn't be included in this
file if you're satisfied with the default values; they're listed here
for informational purposes.
*******************
-->
<!-- allow users to logon anonymously? -->
<context-param>
<param-name>allowAnonymous</param-name>
<param-value>true</param-value>
</context-param>
<!-- allow users to create new accounts? -->
<context-param>
<param-name>allowAccountCreation</param-name>
<param-value>true</param-value>
</context-param>
<!-- allow users to login using their username/password? -->
<context-param>
<param-name>allowLogin</param-name>
<param-value>true</param-value>
</context-param>
<!-- the url for the logo image in the chat window (path relative to the .jsp files) -->
<context-param>
<param-name>logoFilename</param-name>
<param-value>images/logo.gif</param-value>
</context-param>
<!-- the color of the text for chat window room announcements -->
<context-param>
<param-name>chat.announcement-color</param-name>
<param-value>#009d00</param-value>
</context-param>
<!-- the color of the text for the dialog label associated with the user of the web client -->
<context-param>
<param-name>chat.owner-label-color</param-name>
<param-value>#aa0000</param-value>
</context-param>
<!-- the color of the text for the dialog label associated with other chat participants -->
<context-param>
<param-name>chat.participant-label-color</param-name>
<param-value>#0000aa</param-value>
</context-param>
<!-- the color of the text for the dialog in the chat window -->
<context-param>
<param-name>chat.text-color</param-name>
<param-value>#434343</param-value>
</context-param>
<!-- the color of error message text -->
<context-param>
<param-name>error.text-color</param-name>
<param-value>#ff0000</param-value>
</context-param>
<!-- the color of the text for unvisited links -->
<context-param>
<param-name>link.color</param-name>
<param-value>#045d30</param-value>
</context-param>
<!-- the color of the text for links with the pointer hovering over them -->
<context-param>
<param-name>link.hover-color</param-name>
<param-value>#350000</param-value>
</context-param>
<!-- the color of the text for already visited links -->
<context-param>
<param-name>link.visited-color</param-name>
<param-value>#3b3757</param-value>
</context-param>
<!-- the color of the background of all pages -->
<context-param>
<param-name>body.background-color</param-name>
<param-value>#ffffff</param-value>
</context-param>
<!-- the default color of the text on all pages -->
<context-param>
<param-name>body.text-color</param-name>
<param-value>#362f2d</param-value>
</context-param>
<!-- the color of the chat window divider between the participant listing and the chat -->
<context-param>
<param-name>frame.divider-color</param-name>
<param-value>#83272b</param-value>
</context-param>
<!-- the color of the form element buttons -->
<context-param>
<param-name>button.color</param-name>
<param-value>#d6dfdf</param-value>
</context-param>
<!-- the color of the text in the form element buttons -->
<context-param>
<param-name>button.text-color</param-name>
<param-value>#333333</param-value>
</context-param>
<!-- the color of the background in the form element text fields -->
<context-param>
<param-name>textfield.color</param-name>
<param-value>#f7f7fb</param-value>
</context-param>
<!-- the color of the text in the form element text fields and textareas -->
<context-param>
<param-name>textfield.text-color</param-name>
<param-value>#333333</param-value>
</context-param>
<!-- Session listener -->
<listener>
<listener-class>org.jivesoftware.webchat.JiveChatServlet</listener-class>
</listener>
<!-- Servlets -->
<servlet>
<servlet-name>ChatServlet</servlet-name>
<servlet-class>org.jivesoftware.webchat.JiveChatServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<!-- Servlet mappings -->
<servlet-mapping>
<servlet-name>ChatServlet</servlet-name>
<url-pattern>/ChatServlet/*</url-pattern>
</servlet-mapping>
<session-config>
<session-timeout>3</session-timeout>
</session-config>
<!-- Welcome file list -->
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
</web-app>

View File

@ -1,292 +0,0 @@
/**
* $RCSfile$
* $Revision$
* $Date$
*
* Copyright (C) 2003 Jive Software. All rights reserved.
*
* This software is the proprietary information of Jive Software. Use is subject to license terms.
*/
package org.jivesoftware.webchat;
/**
* A Filter that converts ASCII emoticons into image equivalents.
* This filter should only be run after any HTML stripping filters.<p>
*
* The filter must be configured with information about where the image files
* are located. A table containing all the supported emoticons with their
* ASCII representations and image file names is as follows:<p>
*
* <table border=1>
* <tr><td><b>Emotion</b></td><td><b>ASCII</b></td><td><b>Image</b></td></tr>
*
* <tr><td>Happy</td><td>:) or :-)</td><td>happy.gif</td></tr>
* <tr><td>Sad</td><td>:( or :-(</td><td>sad.gif</td></tr>
* <tr><td>Grin</td><td>:D</td><td>grin.gif</td></tr>
* <tr><td>Love</td><td>:x</td><td>love.gif</td></tr>
* <tr><td>Mischief</td><td>;\</td><td>mischief.gif</td></tr>
* <tr><td>Cool</td><td>B-)</td><td>cool.gif</td></tr>
* <tr><td>Devil</td><td>]:)</td><td>devil.gif</td></tr>
* <tr><td>Silly</td><td>:p</td><td>silly.gif</td></tr>
* <tr><td>Angry</td><td>X-(</td><td>angry.gif</td></tr>
* <tr><td>Laugh</td><td>:^O</td><td>laugh.gif</td></tr>
* <tr><td>Wink</td><td>;) or ;-)</td><td>wink.gif</td></tr>
* <tr><td>Blush</td><td>:8}</td><td>blush.gif</td></tr>
* <tr><td>Cry</td><td>:_|</td><td>cry.gif</td></tr>
* <tr><td>Confused</td><td>?:|</td><td>confused.gif</td></tr>
* <tr><td>Shocked</td><td>:O</td><td>shocked.gif</td></tr>
* <tr><td>Plain</td><td>:|</td><td>plain.gif</td></tr>
* </table>
*
* Note: special thanks to August Harrison for implementing an earlier version of this filter.
*/
public class EmoticonFilter {
private static String imageHappy = "happy.gif";
private static String imageSad = "sad.gif";
private static String imageGrin = "grin.gif";
private static String imageLove = "love.gif";
private static String imageMischief = "mischief.gif";
private static String imageCool = "cool.gif";
private static String imageDevil = "devil.gif";
private static String imageSilly = "silly.gif";
private static String imageAngry = "angry.gif";
private static String imageLaugh = "laugh.gif";
private static String imageWink = "wink.gif";
private static String imageBlush = "blush.gif";
private static String imageCry = "cry.gif";
private static String imageConfused = "confused.gif";
private static String imageShocked = "shocked.gif";
private static String imagePlain = "plain.gif";
private static String imageURL = "images/emoticons";
// Placeholders for the built image tags
private static String imgHappy;
private static String imgSad;
private static String imgGrin;
private static String imgLove;
private static String imgMischief;
private static String imgCool;
private static String imgDevil;
private static String imgSilly;
private static String imgAngry;
private static String imgLaugh;
private static String imgWink;
private static String imgBlush;
private static String imgCry;
private static String imgConfused;
private static String imgShocked;
private static String imgPlain;
public EmoticonFilter() {
buildImageTags();
}
public String applyFilter(String string) {
if (string == null || string.length() < 1) {
return string;
}
int length = string.length();
StringBuffer filtered = new StringBuffer(string.length() + 100);
char[] chars = string.toCharArray();
int length1 = length - 1;
int length2 = length - 2;
int index = -1, i = 0, oldend = 0;
String imgTag;
// Replace each of the emoticons, expanded search for performance
while (++index < length1) {
// no tag found yet...
imgTag = null;
switch (chars[i = index]) {
case ']':
// "]:)"
if (i < length2 && chars[++i] == ':' && chars[++i] == ')') {
imgTag = imgDevil;
}
break;
case ':':
switch (chars[++i]) {
case ')':
// ":)"
imgTag = imgHappy;
break;
case '-':
// ":-)"
if (i < length1 && chars[++i] == ')') {
imgTag = imgHappy;
}
// ":-("
else if (chars[i] == '(') {
imgTag = imgSad;
}
break;
case '(':
// ":("
imgTag = imgSad;
break;
case 'D':
// ":D"
imgTag = imgGrin;
break;
case 'x':
// ":x"
imgTag = imgLove;
break;
case 'p':
// ":p"
imgTag = imgSilly;
break;
case '^':
// ":^O"
if (i < length1 && chars[++i] == 'O') {
imgTag = imgLaugh;
}
break;
case '8':
// ":8}"
if (i < length1 && chars[++i] == '}') {
imgTag = imgBlush;
}
break;
case '_':
// ":_|"
if (i < length1 && chars[++i] == '|') {
imgTag = imgCry;
}
break;
case 'O':
// ":O"
imgTag = imgShocked;
break;
case '|':
// ":|"
imgTag = imgPlain;
break;
default:
break;
}
break;
case ';':
switch (chars[++i]) {
case ')':
// ";)"
imgTag = imgWink;
break;
case '-':
// ";-)"
if (i < length1 && chars[++i] == ')') {
imgTag = imgWink;
}
break;
case '\\':
// ";\\"
imgTag = imgMischief;
break;
default:
break;
}
break;
case 'B':
// "B-)"
if (i < length2 && chars[++i] == '-' && chars[++i] == ')') {
imgTag = imgCool;
}
break;
case 'X':
// "X-("
if (i < length2 && chars[++i] == '-' && chars[++i] == '(') {
imgTag = imgAngry;
}
break;
case '?':
// "?:|"
if (i < length2 && chars[++i] == ':' && chars[++i] == '|') {
imgTag = imgConfused;
}
break;
default:
break;
}
// if we found one, replace
if (imgTag != null) {
filtered.append(chars, oldend, index-oldend);
filtered.append(imgTag);
oldend = i + 1;
index = i;
}
}
if (oldend < length) {
filtered.append(chars, oldend, length-oldend);
}
return filtered.toString();
}
/**
* Returns the base URL for emoticon images. This can be specified as
* an absolute or relative path.
*
* @return the base URL for smiley images.
*/
public String getImageURL() {
return imageURL;
}
/**
* Sets the base URL for emoticon images. This can be specified as
* an absolute or relative path.
*
* @param imageURL the base URL for emoticon images.
*/
public void setImageURL(String imageURL) {
if (imageURL != null && imageURL.length() > 0) {
if (imageURL.charAt(imageURL.length()-1) == '/') {
imageURL = imageURL.substring(0, imageURL.length()-1);
}
}
this.imageURL = imageURL;
// rebuild the image tags
buildImageTags();
}
/**
* Build image tags
*/
private void buildImageTags() {
imgHappy = buildURL(imageHappy);
imgSad = buildURL(imageSad);
imgGrin = buildURL(imageGrin);
imgLove = buildURL(imageLove);
imgMischief = buildURL(imageMischief);
imgCool = buildURL(imageCool);
imgDevil = buildURL(imageDevil);
imgSilly = buildURL(imageSilly);
imgAngry = buildURL(imageAngry);
imgLaugh = buildURL(imageLaugh);
imgWink = buildURL(imageWink);
imgBlush = buildURL(imageBlush);
imgCry = buildURL(imageCry);
imgConfused = buildURL(imageConfused);
imgShocked = buildURL(imageShocked);
imgPlain = buildURL(imagePlain);
}
/**
* Returns an HTML image tag using the base image URL and image name.
*/
private String buildURL(String imageName) {
String tag = "<img border='0' src='" + imageURL + "/" + imageName + "'>";
return tag;
}
}

View File

@ -1,729 +0,0 @@
/**
* $RCSfile$
* $Revision$
* $Date$
*
* Copyright (C) 2003 Jive Software. All rights reserved.
*
* This software is the proprietary information of Jive Software. Use is subject to license terms.
*/
package org.jivesoftware.webchat;
import java.io.*;
import java.util.*;
import javax.servlet.*;
import javax.servlet.http.*;
import org.jivesoftware.smack.*;
import org.jivesoftware.smack.filter.*;
import org.jivesoftware.smack.packet.*;
import org.jivesoftware.smack.util.StringUtils;
/**
* An extension of HttpServlet customized to handle transactions between N webclients
* and M chats located on a given XMPP server. While N >= M in the case of group chats,
* the code will currently, never the less, hold onto N connections to the XMPP server.<br>
*
* It is assumed that all JSP pages are in the context root. The init params should be:
* <ul>
* <li> host</li>
* <li> port (optional)</li>
* <li> SSLEnabled (optional)</li>
* </ul>
*
* @author Bill Lynch
* @author loki der quaeler
*/
public class JiveChatServlet
extends HttpServlet
implements HttpSessionListener, PacketListener {
static public final String JIVE_WEB_CHAT_RESOURCE_NAME = "WebChat";
static protected long PACKET_RESPONSE_TIMEOUT_MS = 5000;
static protected String CHAT_LAUNCHER_URI_SUFFIX = "/chat-launcher.jsp";
static protected String CREATE_ACCOUNT_URI = "/account_creation.jsp";
static protected String LOGIN_URI = "/index.jsp";
static protected String ERRORS_ATTRIBUTE_STRING = "messenger.servlet.errors";
static protected String NICKNAME_ATTRIBUTE_STRING = "messenger.servlet.nickname";
static protected String ROOM_ATTRIBUTE_STRING = "messenger.servlet.room";
static protected String HOST_PARAM_STRING = "host";
static protected String PORT_PARAM_STRING = "port";
static protected String SSL_PARAM_STRING = "SSLEnabled";
static protected String COMMAND_PARAM_STRING = "command";
static protected String NICKNAME_PARAM_STRING = "nickname";
static protected String PASSWORD_PARAM_STRING = "password";
static protected String RETYPED_PASSWORD_PARAM_STRING = "password_zwei";
static protected String ROOM_PARAM_STRING = "room";
static protected String USERNAME_PARAM_STRING = "username";
static protected String ANON_LOGIN_COMMAND_STRING = "anon_login";
static protected String CREATE_ACCOUNT_COMMAND_STRING = "create_account";
static protected String LOGIN_COMMAND_STRING = "login";
static protected String LOGOUT_COMMAND_STRING = "logout";
static protected String READ_COMMAND_STRING = "read";
static protected String SILENCE_COMMAND_STRING = "silence";
static protected String WRITE_COMMAND_STRING = "write";
static protected String MESSAGE_REQUEST_STRING = "message";
// is this value used elsewhere? (if not, why a string?) PENDING
static protected String ERROR_RETURN_CODE_STRING = "error";
static protected String SUCCESS_RETURN_CODE_STRING = "success";
// k/v :: S(session id) / ChatData
static protected Map SESSION_CHATDATA_MAP = new HashMap();
// k/v :: S(unique root of packet ids) / ChatData
static protected Map PACKET_ROOT_CHATDATA_MAP = new HashMap();
static protected EmoticonFilter EMOTICONFILTER = new EmoticonFilter();
static protected URLTranscoder URLTRANSCODER = new URLTranscoder();
protected String host;
protected int port;
protected boolean sslEnabled;
public void init (ServletConfig config)
throws ServletException {
ServletContext context = null;
String portParameter = null;
super.init(config);
// XMPPConnection.DEBUG_ENABLED = true;
context = config.getServletContext();
this.host = context.getInitParameter(HOST_PARAM_STRING);
if (this.host == null) {
throw new ServletException("Init parameter \"" + HOST_PARAM_STRING + "\" must be set.");
}
this.port = -1;
portParameter = context.getInitParameter(PORT_PARAM_STRING);
if (portParameter != null) {
try {
this.port = Integer.parseInt(portParameter);
} catch (NumberFormatException nfe) {
throw new ServletException("Init parameter \"" + PORT_PARAM_STRING
+ "\" must be a valid number.", nfe);
}
}
this.sslEnabled
= Boolean.valueOf(context.getInitParameter(SSL_PARAM_STRING)).booleanValue();
}
/**
* Take care of closing down everything we're holding on to, then bubble up the destroy
* to our superclass.
*/
public void destroy () {
synchronized (SESSION_CHATDATA_MAP) {
for (Iterator i = SESSION_CHATDATA_MAP.values().iterator(); i.hasNext(); ) {
ChatData chatData = (ChatData)i.next();
if (chatData.groupChat != null) {
chatData.groupChat.leave();
}
chatData.connection.close();
}
}
super.destroy();
}
protected void service (HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
HttpSession session = request.getSession();
String sessionID = session.getId();
String path = request.getContextPath();
String command = request.getParameter(COMMAND_PARAM_STRING);
if (READ_COMMAND_STRING.equals(command)) {
ChatData chatData = (ChatData)SESSION_CHATDATA_MAP.get(sessionID);
StringBuffer reply = null;
boolean foundData = false;
Message message = null;
int i = 0;
if (chatData == null) {
this.writeData("Must login first.", response);
return;
}
reply = new StringBuffer();
reply.append("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0 Transitional//EN\">\n");
reply.append("<html><head><title>Chat Read Page</title>\n");
reply.append("<meta http-equiv=\"refresh\" content=\"2\">\n");
reply.append("<script language=\"Javascript\" src=\"common.js\"></script>");
reply.append("<script language=\"JavaScript\" type=\"text/javascript\">\n");
reply.append(" var nickname = \"");
reply.append(request.getSession().getAttribute(NICKNAME_ATTRIBUTE_STRING));
reply.append("\";\n");
message = chatData.groupChat.pollMessage();
while (message != null) {
String from = message.getFrom();
String body = message.getBody();
// Get the the user's nickname
from = StringUtils.parseResource(from);
// PENDING - stop using the replace method
// encode the HTML special characters
body = this.replace(body, "&", "&amp;");
body = this.replace(body, "<", "&lt;");
body = this.replace(body, ">", "&gt;");
// replace newlines in the body:
body = this.replace(body, "\r", "");
body = this.replace(body, "\n", "<br>");
// encode the quotes
body = this.replace(body, "\"", "&quot;");
// encode the embedded urls
body = URLTRANSCODER.encodeURLsInText(body);
// Apply emoticons
body = EMOTICONFILTER.applyFilter(body);
if (from.length() == 0) {
reply.append(" var body").append(i).append(" = \"").append(body);
reply.append("\";\n addChatText(body").append(i).append(", true);\n");
} else {
reply.append(" var from").append(i).append(" = \"").append(from);
reply.append("\";\n var body").append(i).append(" = \"").append(body);
reply.append("\";\n addUserName(from").append(i);
reply.append(");\n addChatText(body").append(i).append(", false);\n");
}
message = chatData.groupChat.pollMessage();
foundData = true;
i++;
}
synchronized (chatData.newJoins) {
synchronized (chatData.newDepartures) {
Iterator it = chatData.newJoins.iterator();
i = 0;
while (it.hasNext()) {
reply.append(" var joined").append(i).append(" = \"").append(it.next());
reply.append("\";\n userJoined(joined").append(i).append(");\n");
i++;
}
i = 0;
it = chatData.newDepartures.iterator();
while (it.hasNext()) {
reply.append(" var departed").append(i).append(" = \"").append(it.next());
reply.append("\";\n userDeparted(departed").append(i).append(");\n");
i++;
}
chatData.newJoins.clear();
chatData.newDepartures.clear();
}
}
reply.append("</script>\n</head><body></body></html>");
this.writeData(reply.toString(), response);
} else if (WRITE_COMMAND_STRING.equals(command)) {
String message = request.getParameter(MESSAGE_REQUEST_STRING);
ChatData chatData = (ChatData)SESSION_CHATDATA_MAP.get(sessionID);
if (message == null) {
this.writeData("Parameter \"" + MESSAGE_REQUEST_STRING + "\" is required.",
response);
return;
} else if (chatData == null) {
this.writeData("Must login first.", response);
return;
}
try {
StringBuffer reply = new StringBuffer();
chatData.groupChat.sendMessage(message.trim());
reply.append("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0 Transitional//EN\">\n");
reply.append("<html><head>\n");
reply.append(
"<meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">\n");
reply.append("<title>Chat Form</title>");
reply.append("</head><body>\n");
reply.append("<form name=\"chatform\" action=\"").append(path);
reply.append("/ChatServlet\" method=\"post\">\n");
reply.append("<input type=\"hidden\" name=\"command\" value=\"write\">\n");
reply.append("<input type=\"hidden\" name=\"message\" value=\"\">\n");
reply.append("</form></body></html>");
this.writeData(reply.toString(), response);
} catch (XMPPException e) {
// PENDING - better handling
e.printStackTrace();
}
} else if (LOGOUT_COMMAND_STRING.equals(command)) {
ChatData chatData = null;
synchronized (SESSION_CHATDATA_MAP) {
chatData = (ChatData)SESSION_CHATDATA_MAP.remove(sessionID);
}
if (chatData != null) {
if (chatData.groupChat != null) {
chatData.groupChat.leave();
}
synchronized (PACKET_ROOT_CHATDATA_MAP) {
Packet p = new IQ();
String root = this.getPacketIDRoot(p);
PACKET_ROOT_CHATDATA_MAP.remove(root);
}
chatData.connection.close();
}
} else if (ANON_LOGIN_COMMAND_STRING.equals(command)) {
String returnCode = this.handleLogin(request, true);
if (SUCCESS_RETURN_CODE_STRING.equals(returnCode)) {
response.sendRedirect(path + CHAT_LAUNCHER_URI_SUFFIX);
} else {
// error, return to the original page to display errors and allow re-attempts
RequestDispatcher rd = request.getRequestDispatcher(LOGIN_URI);
rd.forward(request, response);
}
} else if (LOGIN_COMMAND_STRING.equals(command)) {
String returnCode = this.handleLogin(request, false);
if (SUCCESS_RETURN_CODE_STRING.equals(returnCode)) {
response.sendRedirect(path + CHAT_LAUNCHER_URI_SUFFIX);
} else {
// error, return to the original page to display errors and allow re-attempts
RequestDispatcher rd = request.getRequestDispatcher(LOGIN_URI);
rd.forward(request, response);
}
} else if (CREATE_ACCOUNT_COMMAND_STRING.equals(command)) {
String returnCode = this.createAccount(request);
if (SUCCESS_RETURN_CODE_STRING.equals(returnCode)) {
response.sendRedirect(path + LOGIN_URI);
} else {
// error, return to the original page to display errors and allow re-attempts
RequestDispatcher rd = request.getRequestDispatcher(CREATE_ACCOUNT_URI);
rd.forward(request, response);
}
} else if (SILENCE_COMMAND_STRING.equals(command)) {
// do nothing
} else if (command != null) {
this.writeData(("Invalid command: " + command), response);
} else {
this.writeData("Jive Messenger Chat Servlet", response);
}
}
protected String getPacketIDRoot (Packet p) {
if (p == null) {
return null;
}
return p.getPacketID().substring(0, 5);
}
/**
* Creates an account for the user data specified.
*/
private String createAccount (HttpServletRequest request) {
String sessionID = request.getSession().getId();
String username = request.getParameter(USERNAME_PARAM_STRING);
String password = request.getParameter(PASSWORD_PARAM_STRING);
String retypedPassword = request.getParameter(RETYPED_PASSWORD_PARAM_STRING);
Map errors = new HashMap();
// PENDING: validate already taken username
if ((username == null) || (username.trim().length() == 0)) {
errors.put("empty_username", "");
}
if ((password == null) || (password.trim().length() == 0)) {
errors.put("empty_password", "");
}
if ((retypedPassword == null) || (retypedPassword.trim().length() == 0)) {
errors.put("empty_password_two", "");
}
if ((retypedPassword != null) && (password != null)
&& (! retypedPassword.equals(password))) {
errors.put("mismatch_password", "");
}
// If there were no errors, continue
if (errors.size() == 0) {
ChatData chatData = (ChatData)SESSION_CHATDATA_MAP.get(sessionID);
// If a connection already exists for this session, close it before creating
// another.
if (chatData != null) {
if (chatData.groupChat != null) {
chatData.groupChat.leave();
}
chatData.connection.close();
}
chatData = new ChatData();
try {
AccountManager am = null;
// Create connection.
if (! this.sslEnabled) {
if (port != -1) {
chatData.connection = new XMPPConnection(this.host, this.port);
} else {
chatData.connection = new XMPPConnection(this.host);
}
} else {
if (port != -1) {
chatData.connection = new SSLXMPPConnection(this.host, this.port);
}
else {
chatData.connection = new SSLXMPPConnection(this.host);
}
}
am = chatData.connection.getAccountManager();
// PENDING check whether the server even supports account creation
am.createAccount(username, password);
} catch (XMPPException e) {
errors.put("general", "The server reported an error in account creation: "
+ e.getXMPPError().getMessage());
}
}
if (errors.size() > 0) {
request.setAttribute(ERRORS_ATTRIBUTE_STRING, errors);
return ERROR_RETURN_CODE_STRING;
}
return SUCCESS_RETURN_CODE_STRING;
}
/**
* Handles login logic.
*/
private String handleLogin (HttpServletRequest request, boolean anonymous) {
String sessionID = request.getSession().getId();
String username = request.getParameter(USERNAME_PARAM_STRING);
String password = request.getParameter(PASSWORD_PARAM_STRING);
String room = request.getParameter(ROOM_PARAM_STRING);
String nickname = request.getParameter(NICKNAME_PARAM_STRING);
Map errors = new HashMap();
// Validate parameters
if ((! anonymous) && ((username == null) || (username.trim().length() == 0))) {
errors.put(USERNAME_PARAM_STRING, "");
}
if ((! anonymous) && ((password == null) || (password.trim().length() == 0))) {
errors.put(PASSWORD_PARAM_STRING, "");
}
if ((room == null) || (room.trim().length() == 0)) {
errors.put(ROOM_PARAM_STRING, "");
}
if ((nickname == null) || (nickname.trim().length() == 0)) {
errors.put(NICKNAME_PARAM_STRING, "");
}
// If there were no errors, continue
if (errors.size() == 0) {
ChatData chatData = (ChatData)SESSION_CHATDATA_MAP.get(sessionID);
// If a connection already exists for this session, close it before creating
// another.
if (chatData != null) {
if (chatData.groupChat != null) {
chatData.groupChat.leave();
}
chatData.connection.close();
}
chatData = new ChatData();
try {
// Create connection.
if (! this.sslEnabled) {
if (port != -1) {
chatData.connection = new XMPPConnection(this.host, this.port);
} else {
chatData.connection = new XMPPConnection(this.host);
}
} else {
if (port != -1) {
chatData.connection = new SSLXMPPConnection(this.host, this.port);
}
else {
chatData.connection = new SSLXMPPConnection(this.host);
}
}
if (anonymous) {
Authentication a = new Authentication();
PacketCollector pc = chatData.connection.createPacketCollector(
new PacketIDFilter(a.getPacketID()));
Authentication responsePacket = null;
a.setType(IQ.Type.SET);
chatData.connection.sendPacket(a);
responsePacket = (Authentication)pc.nextResult(PACKET_RESPONSE_TIMEOUT_MS);
if (responsePacket == null) {
// throw new XMPPException("No response from the server.");
}
// check for error response
pc.cancel();
// since GroupChat isn't setting the 'from' in it's message sends,
// i can't see a problem in not doing anything with the unique resource
// we've just been given by the server. if GroupChat starts setting the
// from, it would probably grab the information from the XMPPConnection
// instance it holds, and as such we would then need to introduce the
// concept of anonymous logins to XMPPConnection, or tell GroupChat what
// to do what username is null or blank but a resource exists... PENDING
} else {
chatData.connection.login(username, password, JIVE_WEB_CHAT_RESOURCE_NAME);
}
chatData.connection.addPacketListener(this,
new PacketTypeFilter(Presence.class));
synchronized (SESSION_CHATDATA_MAP) {
SESSION_CHATDATA_MAP.put(sessionID, chatData);
}
synchronized (PACKET_ROOT_CHATDATA_MAP) {
Packet p = new IQ();
String root = this.getPacketIDRoot(p);
// PENDING -- we won't do anything with this packet, so it will ultimately look
// to the server as though a packet has disappeared -- is this ok with the
// server?
PACKET_ROOT_CHATDATA_MAP.put(root, chatData);
}
// Join groupChat room.
chatData.groupChat = chatData.connection.createGroupChat(room);
chatData.groupChat.join(nickname);
// Put the user's nickname in the session - this is used by the view to correctly
// display the user's messages in a different color:
request.getSession().setAttribute(NICKNAME_ATTRIBUTE_STRING, nickname);
request.getSession().setAttribute(ROOM_ATTRIBUTE_STRING, room);
} catch (XMPPException e) {
XMPPError err = e.getXMPPError();
errors.put("general", ((err != null) ? err.getMessage() : e.getMessage()));
if (chatData.groupChat != null) {
chatData.groupChat.leave();
}
}
}
if (errors.size() > 0) {
request.setAttribute(ERRORS_ATTRIBUTE_STRING, errors);
return ERROR_RETURN_CODE_STRING;
}
return SUCCESS_RETURN_CODE_STRING;
}
private void writeData (String data, HttpServletResponse response) {
try {
PrintWriter responseWriter = response.getWriter();
response.setContentType("text/html");
responseWriter.println(data);
responseWriter.close();
} catch (IOException ioe) {
// PENDING
}
}
// a hack class to hold a data glom (really hacky)
private class ChatData {
private XMPPConnection connection;
private GroupChat groupChat;
private Set newJoins = new HashSet();
private Set newDepartures = new HashSet();
}
/**
* Replaces all instances of oldString with newString in string.
*
* PENDING - why is this final?
* PENDING - take this out -- it fails under some cases...
*
* @param string the String to search to perform replacements on
* @param oldString the String that should be replaced by newString
* @param newString the String that will replace all instances of oldString
*
* @return a String will all instances of oldString replaced by newString
*/
static public final String replace (String string, String oldString, String newString) {
int i = 0;
// MAY RETURN THIS BLOCK
if (string == null) {
return null;
}
if (newString == null) {
return string;
}
// Make sure that oldString appears at least once before doing any processing.
if (( i=string.indexOf(oldString, i)) >= 0) {
// Use char []'s, as they are more efficient to deal with.
char[] string2 = string.toCharArray();
char[] newString2 = newString.toCharArray();
int oLength = oldString.length();
StringBuffer buf = new StringBuffer(string2.length);
int j = 1;
buf.append(string2, 0, i).append(newString2);
i += oLength;
// Replace all remaining instances of oldString with newString.
while ((i=string.indexOf(oldString, i)) > 0) {
buf.append(string2, j, (i - j)).append(newString2);
i += oLength;
j = i;
}
buf.append(string2, j, (string2.length - j));
return buf.toString();
}
return string;
}
/**
*
* HttpSessionListener implementation
*
*/
public void sessionCreated (HttpSessionEvent event) { }
public void sessionDestroyed (HttpSessionEvent event) {
String sessionID = event.getSession().getId();
ChatData chatData = null;
synchronized (SESSION_CHATDATA_MAP) {
chatData = (ChatData)SESSION_CHATDATA_MAP.remove(sessionID);
}
if (chatData != null) {
if (chatData.groupChat != null) {
chatData.groupChat.leave();
}
synchronized (PACKET_ROOT_CHATDATA_MAP) {
Packet p = new IQ();
String root = this.getPacketIDRoot(p);
PACKET_ROOT_CHATDATA_MAP.remove(root);
}
chatData.connection.close();
}
}
/**
*
* PacketListener implementation
*
*/
public void processPacket (Packet packet) {
Presence presence = (Presence)packet;
String root = null;
ChatData chatData = null;
String userName = null;
// MAY RETURN THIS BLOCK
if (presence.getMode() == Presence.Mode.INVISIBLE) {
return;
}
root = this.getPacketIDRoot(presence);
chatData = (ChatData)PACKET_ROOT_CHATDATA_MAP.get(root);
// MAY RETURN THIS BLOCK
if (chatData == null) {
return;
}
userName = StringUtils.parseResource(packet.getFrom());
if (presence.getType() == Presence.Type.UNAVAILABLE) {
synchronized (chatData.newDepartures) {
synchronized (chatData.newJoins) {
chatData.newJoins.remove(userName);
chatData.newDepartures.add(userName);
}
}
} else if (presence.getType() == Presence.Type.AVAILABLE) {
synchronized (chatData.newJoins) {
synchronized (chatData.newDepartures) {
chatData.newDepartures.remove(userName);
chatData.newJoins.add(userName);
}
}
}
}
}

View File

@ -1,126 +0,0 @@
/**
* $RCSfile$
* $Revision$
* $Date$
*
* Copyright (C) 1999-2002 CoolServlets, Inc. All rights reserved.
*
* This software is the proprietary information of CoolServlets, Inc.
* Use is subject to license terms.
*/
package org.jivesoftware.webchat;
/**
* A Filter that replaces [b][/b], [i][/i], [u][/u], [pre][/pre] tags with their HTML
* tag equivalents.
*/
public class TextStyle {
public String applyFilter(String string) {
if (string == null || string.length() == 0) {
return string;
}
// To figure out how many times we've made text replacements, we
// need to pass around integer count objects.
int[] boldStartCount = new int[1];
int[] italicsStartCount = new int[1];
int[] boldEndCount = new int[1];
int[] italicsEndCount = new int[1];
int[] underlineStartCount = new int[1];
int[] underlineEndCount = new int[1];
int[] preformatStartCount = new int[1];
int[] preformatEndCount = new int[1];
// Bold
string = replaceIgnoreCase(string, "[b]", "<b>", boldStartCount);
string = replaceIgnoreCase(string, "[/b]", "</b>", boldEndCount);
int bStartCount = boldStartCount[0];
int bEndCount = boldEndCount[0];
while (bStartCount > bEndCount) {
string = string.concat("</b>");
bEndCount++;
}
// Italics
string = replaceIgnoreCase(string, "[i]", "<i>", italicsStartCount);
string = replaceIgnoreCase(string, "[/i]", "</i>", italicsEndCount);
int iStartCount = italicsStartCount[0];
int iEndCount = italicsEndCount[0];
while (iStartCount > iEndCount) {
string = string.concat("</i>");
iEndCount++;
}
// Underline
string = replaceIgnoreCase(string, "[u]", "<u>", underlineStartCount);
string = replaceIgnoreCase(string, "[/u]", "</u>", underlineEndCount);
int uStartCount = underlineStartCount[0];
int uEndCount = underlineEndCount[0];
while (uStartCount > uEndCount) {
string = string.concat("</u>");
uEndCount++;
}
// Pre
string = replaceIgnoreCase(string, "[pre]", "<pre>", preformatStartCount);
string = replaceIgnoreCase(string, "[/pre]", "</pre>", preformatEndCount);
int preStartCount = preformatStartCount[0];
int preEndCount = preformatEndCount[0];
while (preStartCount > preEndCount) {
string = string.concat("</pre>");
preEndCount++;
}
return string;
}
/**
* Replaces all instances of oldString with newString in line with the
* added feature that matches of newString in oldString ignore case.
* The count paramater is set to the number of replaces performed.
*
* @param line the String to search to perform replacements on
* @param oldString the String that should be replaced by newString
* @param newString the String that will replace all instances of oldString
* @param count a value that will be updated with the number of replaces
* performed.
*
* @return a String will all instances of oldString replaced by newString
*/
private static final String replaceIgnoreCase(String line, String oldString,
String newString, int [] count)
{
if (line == null) {
return null;
}
String lcLine = line.toLowerCase();
String lcOldString = oldString.toLowerCase();
int i=0;
if ((i=lcLine.indexOf(lcOldString, i)) >= 0) {
int counter = 1;
char [] line2 = line.toCharArray();
char [] newString2 = newString.toCharArray();
int oLength = oldString.length();
StringBuffer buf = new StringBuffer(line2.length);
buf.append(line2, 0, i).append(newString2);
i += oLength;
int j = i;
while ((i=lcLine.indexOf(lcOldString, i)) > 0) {
counter++;
buf.append(line2, j, i-j).append(newString2);
i += oLength;
j = i;
}
buf.append(line2, j, line2.length - j);
count[0] = counter;
return buf.toString();
}
return line;
}
}

View File

@ -1,312 +0,0 @@
/**
* $RCSfile$
* $Revision$
* $Date$
*
* Copyright (C) 1999-2002 CoolServlets, Inc. All rights reserved.
*
* This software is the proprietary information of CoolServlets, Inc.
* Use is subject to license terms.
*/
package org.jivesoftware.webchat;
import java.util.*;
/**
* A Filter that converts URL's to working HTML web links.<p>
*
* The default set of patterns recognized are <code>ftp://path-of-url</code>,
* <code>http://path-of-url</code>, <code>https://path-of-url</code> but can be expanded upon.<p>
*
* In addition, the following patterns are also recognized.
*
* <code>[url path-of-url]descriptive text[/url]</code> and
* <code>[url=path-of-url]descriptive text[/url]</code>.<p>
*
* The <code>[url]</code> allows any path to be defined as link.
*/
public class URLFilter{
private ArrayList schemes = new ArrayList();
// define a preset default set of schemes
public URLFilter() {
schemes.add("http://");
schemes.add("https://");
schemes.add("ftp://");
}
public String applyFilter(String string) {
if (string == null || string.length() == 0) {
return string;
}
int length = string.length();
StringBuffer filtered = new StringBuffer((int) (length * 1.5));
ArrayList urlBlocks = new ArrayList(5);
// search for url's such as [url=..]text[/url] or [url ..]text[/url]
int start = string.indexOf("[url");
while (start != -1 && (start + 5 < length)) {
// check to verify we're not in another block
if (withinAnotherBlock(urlBlocks, start)) {
start = string.indexOf("[url", start + 5);
continue;
}
int end = string.indexOf("[/url]", start + 5);
if (end == -1 || end >= length) {
// went past end of string, skip
break;
}
String u = string.substring(start, end + 6);
int startTagClose = u.indexOf(']');
String url;
String description;
if (startTagClose > 5) {
url = u.substring(5, startTagClose);
description = u.substring(startTagClose + 1, u.length() - 6);
// Check the user entered URL for a "javascript:" or "file:" link. Only
// append the user entered link if it doesn't contain 'javascript:' and 'file:'
String lcURL = url.toLowerCase();
if (lcURL.indexOf("javascript:") == -1 && lcURL.indexOf("file:") == -1) {
URLBlock block = new URLBlock(start, end + 5, url, description);
urlBlocks.add(block);
}
}
else {
url = description = u.substring(startTagClose + 1, u.length() - 6);
// Check the user entered URL for a "javascript:" or "file:" link. Only
// append the user entered link if it doesn't contain 'javascript:' and 'file:'
String lcURL = url.toLowerCase();
if (lcURL.indexOf("javascript:") == -1 && lcURL.indexOf("file:") == -1) {
URLBlock block = new URLBlock(start, end + 5, url);
urlBlocks.add(block);
}
}
start = string.indexOf("[url", end + 6);
}
// now handle all the other urls
Iterator iter = schemes.iterator();
while (iter.hasNext()) {
String scheme = (String) iter.next();
start = string.indexOf(scheme, 0);
while (start != -1) {
int end = start;
// check context, don't handle patterns preceded by any of '"<=
if (start > 0) {
char c = string.charAt(start - 1);
if (c == '\'' || c == '"' || c == '<' || c == '=') {
start = string.indexOf(scheme, start + scheme.length());
continue;
}
}
// check to verify we're not in another block
if (withinAnotherBlock(urlBlocks, start)) {
start = string.indexOf(scheme, start + scheme.length());
continue;
}
// find the end of the url
int cur = start + scheme.length();
while (end == start && cur < length) {
char c = string.charAt(cur);
switch (c) {
case ' ':
end = cur;
break;
case '\t':
end = cur;
break;
case '\'':
end = cur;
break;
case '\"':
end = cur;
break;
case '<':
end = cur;
break;
case '[':
end = cur;
break;
case '\n':
end = cur;
break;
case '\r':
end = cur;
break;
default:
// acceptable character
}
cur++;
}
// if this is true it means the url goes to the end of the string
if (end == start) {
end = length - 1;
}
URLBlock block = new URLBlock(start, end-1, string.substring(start, end));
urlBlocks.add(block);
start = string.indexOf(scheme, end);
}
}
// sort the blocks so that they are in start index order
sortBlocks(urlBlocks);
// now, markup the urls and pass along the filter chain the rest
Iterator blocks = urlBlocks.iterator();
int last = 0;
while (blocks.hasNext()) {
URLBlock block = (URLBlock) blocks.next();
if (block.getStart() > 0) {
filtered.append(string.substring(last, block.getStart()));
}
last = block.getEnd() + 1;
filtered.append("<a href='").append(block.getUrl()).append("' target='_blank'>");
if (block.getDescription().length() > 0) {
filtered.append(block.getDescription());
}
else {
filtered.append(block.getUrl());
}
filtered.append("</a>");
}
if (last < string.length() - 1) {
filtered.append(string.substring(last));
}
return filtered.toString();
}
/**
* Returns the current supported uri schemes as a comma seperated string.
*
* @return the current supported uri schemes as a comma seperated string.
*/
public String getSchemes() {
StringBuffer buf = new StringBuffer(50);
for (int i = 0; i < schemes.size(); i++) {
buf.append((String) schemes.get(i)).append(",");
}
buf.deleteCharAt(buf.length() - 1);
return buf.toString();
}
/**
* Sets the current supported uri schemes as a comma seperated string.
*
* @param schemes a comma seperated string of uri schemes.
*/
public void setSchemes(String schemes) {
if (schemes == null) {
return;
}
// enpty the current list
this.schemes.clear();
StringTokenizer st = new StringTokenizer(schemes, ",");
while (st.hasMoreElements()) {
this.schemes.add(st.nextElement());
}
}
private void sortBlocks(ArrayList blocks) {
Collections.sort(blocks, new Comparator() {
public int compare(Object object1, Object object2) {
URLBlock b1 = (URLBlock) object1;
URLBlock b2 = (URLBlock) object2;
return (b1.getStart() > b2.getStart()) ? 1 : -1;
}
});
}
private boolean withinAnotherBlock(List blocks, int start) {
for (int i = 0; i < blocks.size(); i++) {
URLBlock block = (URLBlock) blocks.get(i);
if (start >= block.getStart() && start < block.getEnd()) {
return true;
}
}
return false;
}
class URLBlock {
int start = 0;
int end = 0;
String description = "";
String url = "";
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
URLBlock(int start, int end, String url) {
this.start = start;
this.end = end;
this.url = url;
}
URLBlock(int start, int end, String url, String description) {
this.start = start;
this.end = end;
this.description = description;
this.url = url;
}
public int getStart() {
return start;
}
public void setStart(int start) {
this.start = start;
}
public int getEnd() {
return end;
}
public void setEnd(int end) {
this.end = end;
}
}
}

View File

@ -1,188 +0,0 @@
/**
* $RCSfile$
* $Revision$
* $Date$
*
* Copyright (C) 1999-2003 Jive Software. All rights reserved.
*
* This software is the proprietary information of Jive Software.
* Use is subject to license terms.
*/
package org.jivesoftware.webchat;
import java.util.*;
/**
* This is a really good example of why software development projects have frameworks, and the
* other apps in their own modules that sit on top of the frameworks... this class should not
* be confused with com.jivesoftware.messenger.operator.util.URLTranscoder, which does a
* variant of the functionality found here.<br>
*
* The default set of patterns recognized are <code>ftp://path-of-url</code>,
* <code>http://path-of-url</code>, <code>https://path-of-url</code> but can be expanded upon.</br>
*
* This was originally URLTranscoder, from CoolServlets, but that class did basically nothing that
* i wanted, so i kept the schemes collection and that was about it.<br>
*
* @author loki der quaeler
*/
public class URLTranscoder {
static protected final String A_HREF_PREFIX = "<a href='";
static protected final String A_HREF_SUFFIX = "' target=_new>";
static protected final String A_HREF_CLOSING_TAG = "</a>";
protected ArrayList schemes;
public URLTranscoder () {
super();
this.schemes = new ArrayList();
this.schemes.add("http://");
this.schemes.add("https://");
this.schemes.add("ftp://");
}
/**
* Sets the current supported uri schemes.
*
* @param schemeCollection a collection of String instances of uri schemes.
*/
public synchronized void setSchemes (Collection schemeCollection) {
// MAY EXIT THIS BLOCK
if (schemes == null) {
return;
}
this.schemes.clear();
this.schemes.addAll(schemeCollection);
}
/**
* Returns a String based off the original text, but now with any a.href blocks html-ized
* inside. (for example, supplying the string "this: http://dict.leo.org/ is a cool url"
* returns "this: <a href='http://dict.leo.org/' target=_new>http://dict.leo.org/</a>
* is a cool url"
*/
public String encodeURLsInText (String text) {
StringBuffer rhett = null;;
List runs = this.getURLRunsInString(text);
Iterator it = null;
int lastStart = 0;
// MAY RETURN THIS BLOCK
if (runs.size() == 0) {
return text;
}
rhett = new StringBuffer();
it = runs.iterator();
while (it.hasNext()) {
URLRun run = (URLRun)it.next();
String url = text.substring(run.getStartIndex(), run.getEndIndex());
if (lastStart < run.getStartIndex()) {
rhett.append(text.substring(lastStart, run.getStartIndex()));
lastStart += run.getEndIndex();
}
rhett.append(A_HREF_PREFIX).append(url).append(A_HREF_SUFFIX).append(url);
rhett.append(A_HREF_CLOSING_TAG);
}
if (lastStart < text.length()) {
rhett.append(text.substring(lastStart, text.length()));
}
return rhett.toString();
}
protected List getURLRunsInString (String text) {
ArrayList rhett = new ArrayList();
Vector vStarts = new Vector();
Iterator sIt = this.schemes.iterator();
Integer[] iStarts = null;
char[] tArray = null;
while (sIt.hasNext()) {
String scheme = (String)sIt.next();
int index = text.indexOf(scheme);
while (index != -1) {
vStarts.add(new Integer(index));
index = text.indexOf(scheme, (index + 1));
}
}
// MAY RETURN THIS BLOCK
if (vStarts.size() == 0) {
return rhett;
}
iStarts = (Integer[])vStarts.toArray(new Integer[0]);
Arrays.sort(iStarts);
tArray = text.toCharArray();
for (int i = 0; i < iStarts.length; i++) {
int start = iStarts[i].intValue();
int end = start + 1;
while ((end < tArray.length) && (! this.characterIsURLTerminator(tArray[end]))) {
end++;
}
if (end == tArray.length) {
end--;
}
rhett.add(new URLRun(start, end));
}
return rhett;
}
protected boolean characterIsURLTerminator (char c) {
switch (c) {
case ' ':
case '\n':
case '(':
case ')':
case '>':
case '\t':
case '\r': return true;
}
return false;
}
protected class URLRun {
protected int start;
protected int end;
protected URLRun (int s, int e) {
super();
this.start = s;
this.end = e;
}
protected int getStartIndex () {
return this.start;
}
protected int getEndIndex () {
return this.end;
}
}
}

View File

@ -1,116 +0,0 @@
<%--
-
-
--%>
<%@ page import="java.util.*" %>
<% // Get error map as a request attribute:
Map errors = (Map)request.getAttribute("messenger.servlet.errors");
if (errors == null) { errors = new HashMap(); }
%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
<head>
<title>Create an account</title>
<link rel="stylesheet" href="<%= request.getContextPath() %>/style_sheet.jsp"
type="text/css">
</head>
<body class="deffr">
<table width="100%" height="100%" cellpadding="0" cellspacing="0" border="0">
<tr>
<td align="center" valign="middle">
<table cellpadding="0" cellspacing="0" border="0">
<tr>
<td>
<h3>Jive Account Creation</h3>
<% if (errors.get("general") != null) { %>
<p>
<span class="error-text">
Error creating account. <%= errors.get("general") %>
</span>
</p>
<br>
<% } %>
</td>
</tr>
<tr>
<td align="center">
<form action="<%= request.getContextPath() %>/ChatServlet"
method="post" name="createform">
<input type="hidden" name="command" value="create_account">
<table cellpadding="2" cellspacing="0" border="0">
<tr>
<td>Desired username:</td>
<td>
<input type="text" size="40" name="username"
class="text">
<% if (errors.get("empty_username") != null) { %>
<span class="error-text"><br>
Please enter a username.
</span>
<% } %>
</td>
</tr>
<tr>
<td>Desired password:</td>
<td>
<input type="password" size="40" name="password"
class="text">
<% if (errors.get("empty_password") != null) { %>
<span class="error-text"><br>
Please enter a password.
</span>
<% } %>
<% if (errors.get("mismatch_password") != null) { %>
<span class="error-text"><br>
Your passwords did not match.
</span>
<% } %>
</td>
</tr>
<tr>
<td>Retype your password:</td>
<td>
<input type="password" size="40" name="password_zwei"
class="text">
<% if (errors.get("empty_password_two") != null) { %>
<span class="error-text"><br>
You must retype your password.
</span>
<% } %>
</td>
</tr>
</table>
</td>
</tr>
<tr>
<td align="center">
<br>
<input type="submit" name="" value="Create account"
class="submit">
</form>
</td>
</tr>
<tr>
<td align="center">
<br><a href="index.jsp">Click here to return to the login page.</a>
</td>
</tr>
</table>
</td>
</tr>
</table>
<script language="JavaScript" type="text/javascript">
document.createform.username.focus();
</script>
</body>
</html>

View File

@ -1,19 +0,0 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Chat Form</title>
<link rel="stylesheet" href="<%= request.getContextPath() %>/style_sheet.jsp"
type="text/css">
</head>
<body>
<form name="chatform" action="<%= request.getContextPath() %>/ChatServlet" method="post">
<input type="hidden" name="command" value="write">
<input type="hidden" name="message" value="">
</form>
</body>
</html>

View File

@ -1,39 +0,0 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Web Chat Session</title>
<script language="JavaScript" type="text/javascript">
function launchWin() {
var newWin = window.open("frame_master.jsp", "chatWin",
"location=no,status=no,toolbar=no,personalbar=no,menubar=no,width=650,height=430");
}
</script>
<link rel="stylesheet" href="<%= request.getContextPath() %>/style_sheet.jsp"
type="text/css">
</head>
<body class="deffr" onload="launchWin();">
<h3>Chat Session Options</h3>
Your chat session should have already started. If for some reason it did
not, click <a href="#" onclick="launchWin(); return false;">this link</a>
to start your chat session.
<br><br>
Other options:
<ul>
<li><a href="email" onclick="alert('Coming soon'); return false;">Email Transcript</a>
<li><a href="index.jsp">Return to the login page.</a>
</ul>
</body>
</html>

View File

@ -1,182 +0,0 @@
function addChatText (someText, isAnnouncement) {
var yakDiv = window.parent.frames['yak'].document.getElementById('ytext');
var children = yakDiv.childNodes.length;
var appendFailed = false;
var spanElement = document.createElement("span");
if (! isAnnouncement) {
spanElement.setAttribute("class", "chat_text");
} else {
spanElement.setAttribute("class", "chat_announcement");
}
// it's easier to dump the possibily html-containing text into the innerHTML
// of the span element than deciphering and building sub-elements.
spanElement.innerHTML = someText;
try {
// various versions of IE crash out on this, and safari
yakDiv.appendChild(spanElement);
} catch (exception) {
appendFailed = true;
}
if (! appendFailed) {
// really make sure the browser appended
appendFailed = (children == yakDiv.childNodes.length);
}
if (appendFailed) {
// try this, the only way left
var inn = yakDiv.innerHTML;
inn += "<span class=\"";
inn += (isAnnouncement ? "chat_announcement\">" : "chat_text\">");
inn += someText + "</span><br>";
yakDiv.innerHTML = inn;
} else {
yakDiv.appendChild(document.createElement("br"));
}
scrollYakToEnd();
}
function addUserName (userName) {
var yakDiv = window.parent.frames['yak'].document.getElementById('ytext');
var children = yakDiv.childNodes.length;
var appendFailed = false;
var spanElement = document.createElement("span");
var userIsClientOwner = false;
var announcement = false;
if (userName == "") {
announcement = true;
spanElement.setAttribute("class", "chat_announcement");
userName = "room announcement";
} else if (userName == nickname) {
userIsClientOwner = true;
spanElement.setAttribute("class", "chat_owner");
} else {
spanElement.setAttribute("class", "chat_participant");
}
try {
spanElement.appendChild(document.createTextNode(userName + ": "));
// various versions of IE crash out on this, and safari
yakDiv.appendChild(spanElement);
} catch (exception) {
appendFailed = true;
}
if (! appendFailed) {
// really make sure the browser appended
appendFailed = (children == yakDiv.childNodes.length);
}
if (appendFailed) {
// try this, the only way left
var inn = yakDiv.innerHTML
inn += "<span class=\"";
if (announcement) {
inn += "chat_announcement"
} else if (userIsClientOwner) {
inn += "chat_owner";
} else {
inn += "chat_participant";
}
inn += "\">" + userName + ": </span>";
yakDiv.innerHTML = inn;
}
}
function scrollYakToEnd () {
var endDiv = window.parent.frames['yak'].document.getElementById('enddiv');
window.parent.frames['yak'].window.scrollTo(0, endDiv.offsetTop);
}
function userJoined (username) {
var parentDIV = window.parent.frames['participants'].document.getElementById('par__list');
var children = parentDIV.childNodes.length;
var appendFailed = false;
var divElement = document.createElement("div");
divElement.setAttribute("id", username);
try {
divElement.appendChild(document.createTextNode(username));
divElement.appendChild(document.createElement("br"));
parentDIV.appendChild(divElement);
} catch (exception) {
appendFailed = true;
}
if (! appendFailed) {
// really make sure the browser appended
appendFailed = (children == parentDIV.childNodes.length);
}
if (appendFailed) {
// try this, the only way left
var inn = parentDIV.innerHTML;
inn += "<div id=\"" + username + "\"> &middot; " + username + "<br></div>";
parentDIV.innerHTML = inn;
}
}
function userDeparted (username) {
var partDoc = window.parent.frames['participants'].document;
var parentDIV = partDoc.getElementById('par__list');
var userDIV = partDoc.getElementById(username);
var children = parentDIV.childNodes.length;
var removeFailed = false;
// MAY RETURN THIS BLOCK
if (userDIV == null) {
return;
}
try {
parentDIV.removeChild(userDIV);
} catch (exception) {
removeFailed = true;
}
if (! removeFailed) {
// really make sure the browser appended
removeFailed = (children == parentDIV.childNodes.length);
}
if (removeFailed) {
// try this, the only way left
var inn = parentDIV.innerHTML;
var openingTag = "<div id=\"" + username + "\">";
var index = inn.toLowerCase().indexOf(openingTag);
var patchedHTML = inn.substring(0, index);
var secondIndex = openingTag.length + username.length + 13;
patchedHTML += inn.substring(secondIndex, (inn.length));
parentDIV.innerHTML = inn;
}
}
function writeDate () {
var msg = "This frame loaded at: ";
var now = new Date();
msg += now + "<br><hr>";
document.write(msg);
}

View File

@ -1,33 +0,0 @@
<html>
<head>
<title><%= request.getSession().getAttribute("messenger.servlet.room") %>
- Jive Web Chat Client</title>
<script>
function frameSetLoaded () {
window.frames['poller'].location.href
= "<%= request.getContextPath() %>/ChatServlet?command=read";
}
function attemptLogout () {
window.frames['participants'].document.logout.submit();
}
</script>
<link rel="stylesheet" href="<%= request.getContextPath() %>/style_sheet.jsp"
type="text/css">
</head>
<frameset cols="*, 125" border="0" frameborder="0" framespacing="0"
onLoad="frameSetLoaded();" onUnload="attemptLogout();">
<frameset rows="0, 200, *, 0" border="0" frameborder="0" framespacing="0">
<frame name="submitter" src="chat-hiddenform.jsp" frameborder="0">
<frame name="yak" src="transcript_frame.html" frameborder="0">
<frame name="input" src="input_frame.jsp" frameborder="0">
<frame name="poller" src="" frameborder="0">
</frameset>
<frame name="participants" src="participants_frame.jsp" class="bordered_left">
</frameset>
</html>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 692 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 688 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 688 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 687 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 693 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 680 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 675 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 670 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 693 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 678 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 694 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 688 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 685 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 634 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 925 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 325 B

View File

@ -1,164 +0,0 @@
<%--
-
-
--%>
<%@ page import="java.util.*" %>
<% // Get error map as a request attribute:
Map errors = (Map)request.getAttribute("messenger.servlet.errors");
boolean allowAnonymous = true;
boolean allowAccountCreate = true;
boolean allowLogin = true;
String param = null;
if (errors == null) { errors = new HashMap(); }
param = application.getInitParameter("allowAnonymous");
if ((param != null) && (param.equalsIgnoreCase("false"))) {
allowAnonymous = false;
}
param = application.getInitParameter("allowAccountCreation");
if ((param != null) && (param.equalsIgnoreCase("false"))) {
allowAccountCreate = false;
}
param = application.getInitParameter("allowLogin");
if ((param != null) && (param.equalsIgnoreCase("false"))) {
allowLogin = false;
}
%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
<head>
<title>Jive Web Chat Client Login</title>
<script language="JavaScript" type="text/javascript">
function submitForm (el) {
el.form.submit();
}
function anonClick () {
document.loginform.command.value = "anon_login";
return true;
}
</script>
<link rel="stylesheet" href="<%= request.getContextPath() %>/style_sheet.jsp"
type="text/css">
</head>
<body class="deffr">
<table width="100%" height="100%" cellpadding="0" cellspacing="0" border="0">
<tr>
<td align="center" valign="middle">
<table cellpadding="0" cellspacing="0" border="0">
<tr>
<td>
<h3>Welcome to the Jive Web Chat Client - Please Login</h3>
<% if (errors.get("general") != null) { %>
<p class="error-text">
Error logging in. Make sure your username and
password are correct. <%= errors.get("general") %>
</p>
<% } %>
</td>
</tr>
<tr>
<td align="center">
<form action="<%= request.getContextPath() %>/ChatServlet"
method="post" name="loginform">
<input type="hidden" name="command" value="login">
<table cellpadding="2" cellspacing="0" border="0">
<% if (allowLogin) { %>
<tr>
<td>Username:</td>
<td>
<input type="text" size="40" name="username"
class="text">
<% if (errors.get("username") != null) { %>
<span class="error-text"><br>
Please enter a valid username.
</span>
<% } %>
</td>
</tr>
<tr>
<td>Password:</td>
<td>
<input type="password" size="40" name="password"
class="text">
<% if (errors.get("password") != null) { %>
<span class="error-text"><br>
Please enter a valid password.
</span>
<% } %>
</td>
</tr>
<% } %>
<tr>
<td>Nickname:</td>
<td>
<input type="text" size="40" name="nickname"
class="text">
<% if (errors.get("nickname") != null) { %>
<span class="error-text"><br>
Please enter a nickname.
</span>
<% } %>
</td>
</tr>
<tr>
<td>Room:</td>
<td>
<input type="text" size="40" name="room"
value="test@chat.jivesoftware.com" class="text">
<% if (errors.get("room") != null) { %>
<span class="error-text"><br>
Please enter a valid room.
</span>
<% } %>
</td>
</tr>
</table>
</td>
</tr>
<tr>
<td align="center">
<br>
<% if (allowLogin) { %>
<input type="submit" name="" value="Login and Chat"
class="submit">
<% } %>
<% if (allowAnonymous) { %>
<input type="submit" name="" value="Anonymously Chat"
onClick="return anonClick();" class="submit">
<% } %>
</form>
</td>
</tr>
<% if (allowAccountCreate) { %>
<tr>
<td align="center">
<br>Don't have an account and would like to create one?
<a href="account_creation.jsp">Click here.</a>
</td>
</tr>
<% } %>
</table>
</td>
</tr>
</table>
<script language="JavaScript" type="text/javascript">
<% if (allowLogin) { %>
document.loginform.username.focus();
<% } else { %>
document.loginform.nickname.focus();
<% } %>
</script>
</body>
</html>

View File

@ -1,75 +0,0 @@
<%@ page import="javax.servlet.*" %>
<% // Get error map as a request attribute:
String logoFilename = application.getInitParameter("logoFilename");
if (logoFilename == null) {
logoFilename = "images/logo.gif";
}
%>
<html>
<head>
<meta http-equiv="expires" content="0">
<script>
function updateButtonState (textAreaElement) {
if (textAreaElement.value != '') {
textAreaElement.form.send.disabled = false;
} else {
textAreaElement.form.send.disabled = true;
}
}
function handleKeyEvent (event, textAreaElement) {
var form = textAreaElement.form;
var keyCode = event.keyCode;
if (keyCode == null) {
keyCode = event.which;
}
if (keyCode == 13) {
submitForm(form);
form.message.value = '';
}
updateButtonState(textAreaElement);
}
function submitForm (formElement) {
var textAreaElement = formElement.message;
var text = textAreaElement.value;
var sForm = window.parent.frames['submitter'].document.chatform;
sForm.message.value = text;
sForm.submit();
textAreaElement.value = '';
updateButtonState(textAreaElement);
return false;
}
</script>
<link rel="stylesheet" href="<%= request.getContextPath() %>/style_sheet.jsp"
type="text/css">
</head>
<body class="deffr">
<center>
<form name="chat" onsubmit="return submitForm(this);">
<textarea name="message"
onkeyup="handleKeyEvent(event, this);"
onchange="updateButtonState(this);"></textarea>
<br>
<input type="submit" name="send" value="Send" class="submit_right" disabled>
</form>
</center>
<img src="<%= logoFilename %>" class="logo">
</body>
</html>

View File

@ -1,46 +0,0 @@
<html>
<head>
<meta http-equiv="expires" content="0">
<script>
function verifyLogout () {
if (confirm("Are you sure you'd like to logout")) {
// hacky solution to avoid logging out twice due to parent frame's onUnload
try {
document.logout.command.value = "silence";
} catch (e) { }
window.parent.close();
return true;
}
return false;
}
</script>
<link rel="stylesheet" href="<%= request.getContextPath() %>/style_sheet.jsp"
type="text/css">
</head>
<body class="deffr">
<center>In the room:</center>
<br>
<hr width=67%>
<div id="par__list"> </div>
<form name="logout" action="<%= request.getContextPath() %>/ChatServlet" method="post">
<input type="hidden" name="command" value="logout">
</form>
<span class="logout">
<a href="<%= request.getContextPath() %>/ChatServlet?command=logout"
onclick="return verifyLogout();" >
<img src="images/logout-16x16.gif" border="0" class="logout"> Logout</a></span>
</body>
</html>

View File

@ -1,132 +0,0 @@
<% // Set the content type of the this page to be CSS
String contentType = "text/css";
String chatAnnouncementColor = application.getInitParameter("chat.announcement-color");
String chatOwnerLabelColor = application.getInitParameter("chat.owner-label-color");
String chatParticipantLabelColor = application.getInitParameter("chat.participant-label-color");
String chatTextColor = application.getInitParameter("chat.text-color");
String errorTextColor = application.getInitParameter("error.text-color");
String linkColor = application.getInitParameter("link.color");
String linkHoverColor = application.getInitParameter("link.hover-color");
String linkVisitedColor = application.getInitParameter("link.visited-color");
String bodyBGColor = application.getInitParameter("body.background-color");
String bodyTextColor = application.getInitParameter("body.text-color");
String frameDividerColor = application.getInitParameter("frame.divider-color");
String buttonColor = application.getInitParameter("button.color");
String buttonTextColor = application.getInitParameter("button.text-color");
String textFieldColor = application.getInitParameter("textfield.color");
String textFieldTextColor = application.getInitParameter("textfield.text-color");
response.setContentType(contentType);
if (chatAnnouncementColor == null) {
chatAnnouncementColor = "#009d00";
}
if (chatOwnerLabelColor == null) {
chatOwnerLabelColor = "#aa0000";
}
if (chatParticipantLabelColor == null) {
chatParticipantLabelColor = "#0000aa";
}
if (chatTextColor == null) {
chatTextColor = "#434343";
}
if (errorTextColor == null) {
errorTextColor = "#ff0000";
}
if (linkColor == null) {
linkColor = "#045d30";
}
if (linkHoverColor == null) {
linkHoverColor = "#350000";
}
if (linkVisitedColor == null) {
linkVisitedColor = "#3b3757";
}
if (bodyBGColor == null) {
bodyBGColor = "#ffffff";
}
if (bodyTextColor == null) {
bodyTextColor = "#362f2d";
}
if (frameDividerColor == null) {
frameDividerColor = "#83272b";
}
if (buttonColor == null) {
buttonColor = "#d6dfdf";
}
if (buttonTextColor == null) {
buttonTextColor = "#333333";
}
if (textFieldColor == null) {
textFieldColor = "#f7f7fb";
}
if (textFieldTextColor == null) {
textFieldTextColor = "#333333";
}
%>
BODY, TD, TH { font-family : Tahoma, Arial, Verdana, sans serif; font-size: 13px; }
H3 { font-size : 1.2em; }
.error-text { color : <%= errorTextColor %>; }
/* default unvisited, visited and hover link presentation */
A:link { background: transparent; color: <%= linkColor %>;
text-decoration: none; }
A:visited { background: transparent; color: <%= linkVisitedColor %>;
text-decoration: none; }
A:hover { background: transparent; color: <%= linkHoverColor %>;
text-decoration: underline; }
/**
* site wide BODY style rule; the scrollbar stuff only works in IE for windows,
* but doesn't seem to hurt on other browsers..
*/
BODY.deffr { background-color: <%= bodyBGColor %>; color: <%= bodyTextColor %>;
scrollbar-face-color: <%= bodyBGColor %>;
scrollbar-shadow-color: <%= bodyTextColor %>;
scrollbar-highlight-color: <%= bodyBGColor %>;
scrollbar-darkshadow-color: <%= bodyBGColor %>;
scrollbar-track-color: <%= bodyBGColor %>;
scrollbar-arrow-color: <%= bodyTextColor %>; }
FRAME.bordered_left { border-left: 3px solid <%= frameDividerColor %>; }
IMG.logo { position: absolute; bottom: 12px; left: 10px; }
IMG.logout { vertical-align: middle; }
INPUT.submit { background-color: <%= buttonColor %>; color: <%= buttonTextColor %>;
font-size: 12px; font-family: Arial, Verdana, sans serif;
border-style: ridge; margin: 1px 5px 1px 5px; }
INPUT.submit_right { background-color: <%= buttonColor %>; color: <%= buttonTextColor %>;
font-size: 12px; font-family: Arial, Verdana, sans serif;
border-style: ridge; margin: 1px 5px 1px 5px;
position: absolute; right: 10px; }
INPUT.text { background-color: <%= textFieldColor %>; color: <%= textFieldTextColor %>;
font: normal 12px Arial, Verdana, sans serif; height: 20px; width: 271px;
border-style: groove; margin-left: 10px; }
SPAN.chat_text { font: normal 11px Arial, Verdana, sans serif;
color: <%= chatTextColor %>; }
SPAN.chat_announcement { font: italic 11px Arial, Verdana, sans serif;
color: <%= chatAnnouncementColor %>; }
SPAN.chat_owner { font: bold 11px Arial, Verdana, sans serif;
color: <%= chatOwnerLabelColor %>; }
SPAN.chat_participant { font: bold 11px Arial, Verdana, sans serif;
color: <%= chatParticipantLabelColor %>; }
SPAN.logout { position: absolute; bottom: 12px; right: 15px; }
TEXTAREA { color: <%= textFieldTextColor %>; font: normal 12px Arial, Verdana, sans serif;
width: 500px; height: 130px; }

View File

@ -1,13 +0,0 @@
<html>
<head>
<meta http-equiv="expires" content="0">
<link rel="stylesheet" href="style_sheet.jsp" type="text/css" media="screen">
</head>
<body class="deffr">
<div id="ytext"> <br></div><div id="enddiv"></div>
</body>
</html>

View File

@ -24,8 +24,14 @@
<!-- PROPERTIES -->
<!-- ======================================================================================= -->
<property file="${basedir}/build/build.properties" />
<!-- Smack Version -->
<property name="version.major" value="3" />
<property name="version.minor" value="0" />
<property name="version.revision" value="0" />
<property name="version.name" value="${version.major}.${version.minor}.${version.revision}" />
<property file="${basedir}/build/build.properties" />
<property name="compile.dir" value="${basedir}/classes" />
<property name="compile.test.dir" value="${basedir}/classes-test" />
<property name="jar.dest.dir" value="${basedir}" />
@ -35,11 +41,6 @@
<property name="test.dir" value="${basedir}/test" />
<property name="resources.dir" value="${basedir}/build/resources" />
<property name="version.major" value="2" />
<property name="version.minor" value="2" />
<property name="version.revision" value="1" />
<property name="version.name" value="${version.major}.${version.minor}.${version.revision}" />
<!-- Test props - override these defaults in the properties file or in command line -->
<property name="test.host" value="localhost" />
<property name="test.port" value="5222" />
@ -78,8 +79,8 @@
destdir="${compile.dir}"
includeAntRuntime="no"
debug="on"
source="1.3"
target="1.2"
source="1.5"
target="1.5"
>
<src path="${basedir}/source" />
<classpath>
@ -102,8 +103,8 @@
destdir="${compile.test.dir}"
includeAntRuntime="no"
debug="on"
source="1.3"
target="1.2"
source="1.5"
target="1.5"
>
<src path="${test.dir}" />
<classpath>

View File

@ -8,7 +8,8 @@
<content url="file://$MODULE_DIR$/../..">
<sourceFolder url="file://$MODULE_DIR$/../resources" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/../../source" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/../../test" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/../../test" isTestSource="true" />
<excludeFolder url="file://$MODULE_DIR$/../../release" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />

View File

@ -201,7 +201,7 @@
<module fileurl="file://$PROJECT_DIR$/Smack.iml" filepath="$PROJECT_DIR$/Smack.iml" />
</modules>
</component>
<component name="ProjectRootManager" version="2" assert-keyword="true" jdk-15="false" project-jdk-name="JDK 1.4.2" />
<component name="ProjectRootManager" version="2" assert-keyword="true" jdk-15="true" project-jdk-name="JDK 1.5.0" />
<component name="RmicSettings">
<option name="IS_EANABLED" value="false" />
<option name="DEBUGGING_INFO" value="true" />

View File

@ -1,353 +0,0 @@
/**
* $RCSfile$
* $Revision$
* $Date$
*
* Copyright 2003-2004 Jive Software.
*
* All rights reserved. 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.jivesoftware.smack;
import org.jivesoftware.smack.packet.Presence;
import org.jivesoftware.smack.packet.Message;
import org.jivesoftware.smack.packet.Packet;
import org.jivesoftware.smack.filter.*;
import java.util.*;
/**
* A GroupChat is a conversation that takes place among many users in a virtual
* room. When joining a group chat, you specify a nickname, which is the identity
* that other chat room users see.
*
* @see XMPPConnection#createGroupChat(String)
* @author Matt Tucker
*/
public class GroupChat {
private XMPPConnection connection;
private String room;
private String nickname = null;
private boolean joined = false;
private List participants = new ArrayList();
private List connectionListeners = new ArrayList();
private PacketFilter presenceFilter;
private PacketFilter messageFilter;
private PacketCollector messageCollector;
/**
* Creates a new group chat with the specified connection and room name. Note: no
* information is sent to or received from the server until you attempt to
* {@link #join(String) join} the chat room. On some server implementations,
* the room will not be created until the first person joins it.<p>
*
* Most XMPP servers use a sub-domain for the chat service (eg chat.example.com
* for the XMPP server example.com). You must ensure that the room address you're
* trying to connect to includes the proper chat sub-domain.
*
* @param connection the XMPP connection.
* @param room the name of the room in the form "roomName@service", where
* "service" is the hostname at which the multi-user chat
* service is running.
*/
public GroupChat(XMPPConnection connection, String room) {
this.connection = connection;
this.room = room;
// Create a collector for all incoming messages.
messageFilter = new AndFilter(new FromContainsFilter(room),
new PacketTypeFilter(Message.class));
messageFilter = new AndFilter(messageFilter, new PacketFilter() {
public boolean accept(Packet packet) {
Message msg = (Message)packet;
return msg.getType() == Message.Type.GROUP_CHAT;
}
});
messageCollector = connection.createPacketCollector(messageFilter);
// Create a listener for all presence updates.
presenceFilter = new AndFilter(new FromContainsFilter(room),
new PacketTypeFilter(Presence.class));
connection.addPacketListener(new PacketListener() {
public void processPacket(Packet packet) {
Presence presence = (Presence)packet;
String from = presence.getFrom();
if (presence.getType() == Presence.Type.AVAILABLE) {
synchronized (participants) {
if (!participants.contains(from)) {
participants.add(from);
}
}
}
else if (presence.getType() == Presence.Type.UNAVAILABLE) {
synchronized (participants) {
participants.remove(from);
}
}
}
}, presenceFilter);
}
/**
* Returns the name of the room this GroupChat object represents.
*
* @return the groupchat room name.
*/
public String getRoom() {
return room;
}
/**
* Joins the chat room using the specified nickname. If already joined
* using another nickname, this method will first leave the room and then
* re-join using the new nickname. The default timeout of 5 seconds for a reply
* from the group chat server that the join succeeded will be used.
*
* @param nickname the nickname to use.
* @throws XMPPException if an error occurs joining the room. In particular, a
* 409 error can occur if someone is already in the group chat with the same
* nickname.
*/
public synchronized void join(String nickname) throws XMPPException {
join(nickname, SmackConfiguration.getPacketReplyTimeout());
}
/**
* Joins the chat room using the specified nickname. If already joined as
* another nickname, will leave as that name first before joining under the new
* name.
*
* @param nickname the nickname to use.
* @param timeout the number of milleseconds to wait for a reply from the
* group chat that joining the room succeeded.
* @throws XMPPException if an error occurs joining the room. In particular, a
* 409 error can occur if someone is already in the group chat with the same
* nickname.
*/
public synchronized void join(String nickname, long timeout) throws XMPPException {
if (nickname == null || nickname.equals("")) {
throw new IllegalArgumentException("Nickname must not be null or blank.");
}
// If we've already joined the room, leave it before joining under a new
// nickname.
if (joined) {
leave();
}
// We join a room by sending a presence packet where the "to"
// field is in the form "roomName@service/nickname"
Presence joinPresence = new Presence(Presence.Type.AVAILABLE);
joinPresence.setTo(room + "/" + nickname);
// Wait for a presence packet back from the server.
PacketFilter responseFilter = new AndFilter(
new FromContainsFilter(room + "/" + nickname),
new PacketTypeFilter(Presence.class));
PacketCollector response = connection.createPacketCollector(responseFilter);
// Send join packet.
connection.sendPacket(joinPresence);
// Wait up to a certain number of seconds for a reply.
Presence presence = (Presence)response.nextResult(timeout);
response.cancel();
if (presence == null) {
throw new XMPPException("No response from server.");
}
else if (presence.getError() != null) {
throw new XMPPException(presence.getError());
}
this.nickname = nickname;
joined = true;
}
/**
* Returns true if currently in the group chat (after calling the {@link
* #join(String)} method.
*
* @return true if currently in the group chat room.
*/
public boolean isJoined() {
return joined;
}
/**
* Leave the chat room.
*/
public synchronized void leave() {
// If not joined already, do nothing.
if (!joined) {
return;
}
// We leave a room by sending a presence packet where the "to"
// field is in the form "roomName@service/nickname"
Presence leavePresence = new Presence(Presence.Type.UNAVAILABLE);
leavePresence.setTo(room + "/" + nickname);
connection.sendPacket(leavePresence);
// Reset participant information.
participants = new ArrayList();
nickname = null;
joined = false;
}
/**
* Returns the nickname that was used to join the room, or <tt>null</tt> if not
* currently joined.
*
* @return the nickname currently being used.
*/
public String getNickname() {
return nickname;
}
/**
* Returns the number of participants in the group chat.<p>
*
* Note: this value will only be accurate after joining the group chat, and
* may fluctuate over time. If you query this value directly after joining the
* group chat it may not be accurate, as it takes a certain amount of time for
* the server to send all presence packets to this client.
*
* @return the number of participants in the group chat.
*/
public int getParticipantCount() {
synchronized (participants) {
return participants.size();
}
}
/**
* Returns an Iterator (of Strings) for the list of fully qualified participants
* in the group chat. For example, "conference@chat.jivesoftware.com/SomeUser".
* Typically, a client would only display the nickname of the participant. To
* get the nickname from the fully qualified name, use the
* {@link org.jivesoftware.smack.util.StringUtils#parseResource(String)} method.
* Note: this value will only be accurate after joining the group chat, and may
* fluctuate over time.
*
* @return an Iterator for the participants in the group chat.
*/
public Iterator getParticipants() {
synchronized (participants) {
return Collections.unmodifiableList(new ArrayList(participants)).iterator();
}
}
/**
* Adds a packet listener that will be notified of any new Presence packets
* sent to the group chat. Using a listener is a suitable way to know when the list
* of participants should be re-loaded due to any changes.
*
* @param listener a packet listener that will be notified of any presence packets
* sent to the group chat.
*/
public void addParticipantListener(PacketListener listener) {
connection.addPacketListener(listener, presenceFilter);
connectionListeners.add(listener);
}
/**
* Sends a message to the chat room.
*
* @param text the text of the message to send.
* @throws XMPPException if sending the message fails.
*/
public void sendMessage(String text) throws XMPPException {
Message message = new Message(room, Message.Type.GROUP_CHAT);
message.setBody(text);
connection.sendPacket(message);
}
/**
* Creates a new Message to send to the chat room.
*
* @return a new Message addressed to the chat room.
*/
public Message createMessage() {
return new Message(room, Message.Type.GROUP_CHAT);
}
/**
* Sends a Message to the chat room.
*
* @param message the message.
* @throws XMPPException if sending the message fails.
*/
public void sendMessage(Message message) throws XMPPException {
connection.sendPacket(message);
}
/**
* Polls for and returns the next message, or <tt>null</tt> if there isn't
* a message immediately available. This method provides significantly different
* functionalty than the {@link #nextMessage()} method since it's non-blocking.
* In other words, the method call will always return immediately, whereas the
* nextMessage method will return only when a message is available (or after
* a specific timeout).
*
* @return the next message if one is immediately available and
* <tt>null</tt> otherwise.
*/
public Message pollMessage() {
return (Message)messageCollector.pollResult();
}
/**
* Returns the next available message in the chat. The method call will block
* (not return) until a message is available.
*
* @return the next message.
*/
public Message nextMessage() {
return (Message)messageCollector.nextResult();
}
/**
* Returns the next available message in the chat. The method call will block
* (not return) until a packet is available or the <tt>timeout</tt> has elapased.
* If the timeout elapses without a result, <tt>null</tt> will be returned.
*
* @param timeout the maximum amount of time to wait for the next message.
* @return the next message, or <tt>null</tt> if the timeout elapses without a
* message becoming available.
*/
public Message nextMessage(long timeout) {
return (Message)messageCollector.nextResult(timeout);
}
/**
* Adds a packet listener that will be notified of any new messages in the
* group chat. Only "group chat" messages addressed to this group chat will
* be delivered to the listener. If you wish to listen for other packets
* that may be associated with this group chat, you should register a
* PacketListener directly with the XMPPConnection with the appropriate
* PacketListener.
*
* @param listener a packet listener.
*/
public void addMessageListener(PacketListener listener) {
connection.addPacketListener(listener, messageFilter);
connectionListeners.add(listener);
}
public void finalize() throws Throwable {
super.finalize();
try {
if (messageCollector != null) {
messageCollector.cancel();
}
// Remove all the PacketListeners added to the connection by this GroupChat
for (Iterator it=connectionListeners.iterator(); it.hasNext();) {
connection.removePacketListener((PacketListener) it.next());
}
}
catch (Exception e) {}
}
}

View File

@ -135,17 +135,34 @@ public class PacketCollector {
public synchronized Packet nextResult(long timeout) {
// Wait up to the specified amount of time for a result.
if (resultQueue.isEmpty()) {
long waitTime = timeout;
long start = System.currentTimeMillis();
try {
wait(timeout);
// Keep waiting until the specified amount of time has elapsed, or
// a packet is available to return.
while (resultQueue.isEmpty()) {
if (waitTime <= 0) {
break;
}
wait(waitTime);
long now = System.currentTimeMillis();
waitTime -= (now - start);
start = now;
}
}
catch (InterruptedException ie) {
// Ignore.
}
// Still haven't found a result, so return null.
if (resultQueue.isEmpty()) {
return null;
}
// Return the packet that was found.
else {
return (Packet)resultQueue.removeLast();
}
}
// If still no result, return null.
if (resultQueue.isEmpty()) {
return null;
}
// There's already a packet waiting, so return it.
else {
return (Packet)resultQueue.removeLast();
}

View File

@ -25,6 +25,7 @@ import org.jivesoftware.smack.filter.*;
import org.jivesoftware.smack.util.StringUtils;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
/**
* Represents a user's roster, which is the collection of users a person receives
@ -68,10 +69,10 @@ public class Roster {
private static int defaultSubscriptionMode = SUBSCRIPTION_ACCEPT_ALL;
private XMPPConnection connection;
private Map groups;
private Map<String,RosterGroup> groups;
private List entries;
private List unfiledEntries;
private List rosterListeners;
private List<RosterListener> rosterListeners;
private Map presenceMap;
// The roster is marked as initialized when at least a single roster packet
// has been recieved and processed.
@ -110,10 +111,10 @@ public class Roster {
*/
Roster(final XMPPConnection connection) {
this.connection = connection;
groups = new Hashtable();
groups = new ConcurrentHashMap<String,RosterGroup>();
unfiledEntries = new ArrayList();
entries = new ArrayList();
rosterListeners = new ArrayList();
rosterListeners = new ArrayList<RosterListener>();
presenceMap = new HashMap();
// Listen for any roster packets.
PacketFilter rosterFilter = new PacketTypeFilter(RosterPacket.class);
@ -130,7 +131,7 @@ public class Roster {
*
* If using the manual mode, a PacketListener should be registered that
* listens for Presence packets that have a type of
* {@link org.jivesoftware.smack.packet.Presence.Type#SUBSCRIBE}.
* {@link org.jivesoftware.smack.packet.Presence.Type#subscribe}.
*
* @return the subscription mode.
*/
@ -145,7 +146,7 @@ public class Roster {
*
* If using the manual mode, a PacketListener should be registered that
* listens for Presence packets that have a type of
* {@link org.jivesoftware.smack.packet.Presence.Type#SUBSCRIBE}.
* {@link org.jivesoftware.smack.packet.Presence.Type#subscribe}.
*
* @param subscriptionMode the subscription mode.
*/
@ -251,7 +252,7 @@ public class Roster {
}
// Create a presence subscription packet and send.
Presence presencePacket = new Presence(Presence.Type.SUBSCRIBE);
Presence presencePacket = new Presence(Presence.Type.subscribe);
presencePacket.setTo(user);
connection.sendPacket(presencePacket);
}
@ -291,7 +292,7 @@ public class Roster {
throw new XMPPException(response.getError());
}
else {
}
}
@ -301,42 +302,26 @@ public class Roster {
* @return the number of entries in the roster.
*/
public int getEntryCount() {
HashMap entryMap = new HashMap();
// Loop through all roster groups.
for (Iterator groups = getGroups(); groups.hasNext(); ) {
RosterGroup rosterGroup = (RosterGroup) groups.next();
for (Iterator entries = rosterGroup.getEntries(); entries.hasNext(); ) {
entryMap.put(entries.next(), "");
}
}
synchronized (unfiledEntries) {
return entryMap.size() + unfiledEntries.size();
}
return getEntries().size();
}
/**
* Returns all entries in the roster, including entries that don't belong to
* any groups.
* Returns an unmodifiable collection of all entries in the roster, including entries
* that don't belong to any groups.
*
* @return all entries in the roster.
*/
public Iterator getEntries() {
ArrayList allEntries = new ArrayList();
public Collection<RosterEntry> getEntries() {
Set<RosterEntry> allEntries = new HashSet<RosterEntry>();
// Loop through all roster groups and add their entries to the answer
for (Iterator groups = getGroups(); groups.hasNext(); ) {
RosterGroup rosterGroup = (RosterGroup) groups.next();
for (Iterator entries = rosterGroup.getEntries(); entries.hasNext(); ) {
RosterEntry entry = (RosterEntry)entries.next();
if (!allEntries.contains(entry)) {
allEntries.add(entry);
}
}
for (RosterGroup rosterGroup: getGroups()) {
allEntries.addAll(rosterGroup.getEntries());
}
// Add the roster unfiled entries to the answer
synchronized (unfiledEntries) {
allEntries.addAll(unfiledEntries);
}
return allEntries.iterator();
return Collections.unmodifiableCollection(allEntries);
}
/**
@ -406,9 +391,7 @@ public class Roster {
* @return the roster group with the specified name.
*/
public RosterGroup getGroup(String name) {
synchronized (groups) {
return (RosterGroup)groups.get(name);
}
return groups.get(name);
}
/**
@ -417,21 +400,16 @@ public class Roster {
* @return the number of groups in the roster.
*/
public int getGroupCount() {
synchronized (groups) {
return groups.size();
}
return groups.size();
}
/**
* Returns an iterator the for all the roster groups.
* Returns an unmodiable collections of all the roster groups.
*
* @return an iterator for all roster groups.
*/
public Iterator getGroups() {
synchronized (groups) {
List groupsList = Collections.unmodifiableList(new ArrayList(groups.values()));
return groupsList.iterator();
}
public Collection<RosterGroup> getGroups() {
return Collections.unmodifiableCollection(groups.values());
}
/**
@ -483,7 +461,7 @@ public class Roster {
}
}
/**
/**
* Returns the presence info for a particular user's resource, or <tt>null</tt> if the user
* is unavailable (offline) or if no presence information is available, such as
* when you are not subscribed to the user's presence updates.
@ -603,7 +581,7 @@ public class Roster {
// If an "available" packet, add it to the presence map. Each presence map will hold
// for a particular user a map with the presence packets saved for each resource.
if (presence.getType() == Presence.Type.AVAILABLE) {
if (presence.getType() == Presence.Type.available) {
Map userPresences;
// Get the user presence map
if (presenceMap.get(key) == null) {
@ -628,7 +606,7 @@ public class Roster {
}
}
// If an "unavailable" packet, remove any entries in the presence map.
else if (presence.getType() == Presence.Type.UNAVAILABLE) {
else if (presence.getType() == Presence.Type.unavailable) {
if (presenceMap.get(key) != null) {
Map userPresences = (Map) presenceMap.get(key);
synchronized (userPresences) {
@ -648,27 +626,27 @@ public class Roster {
}
}
}
else if (presence.getType() == Presence.Type.SUBSCRIBE) {
else if (presence.getType() == Presence.Type.subscribe) {
if (subscriptionMode == SUBSCRIPTION_ACCEPT_ALL) {
// Accept all subscription requests.
Presence response = new Presence(Presence.Type.SUBSCRIBED);
Presence response = new Presence(Presence.Type.subscribed);
response.setTo(presence.getFrom());
connection.sendPacket(response);
}
else if (subscriptionMode == SUBSCRIPTION_REJECT_ALL) {
// Reject all subscription requests.
Presence response = new Presence(Presence.Type.UNSUBSCRIBED);
Presence response = new Presence(Presence.Type.unsubscribed);
response.setTo(presence.getFrom());
connection.sendPacket(response);
}
// Otherwise, in manual mode so ignore.
}
else if (presence.getType() == Presence.Type.UNSUBSCRIBE) {
else if (presence.getType() == Presence.Type.unsubscribe) {
if (subscriptionMode != SUBSCRIPTION_MANUAL) {
// Acknowledge and accept unsubscription notification so that the
// server will stop sending notifications saying that the contact
// has unsubscribed to our presence.
Presence response = new Presence(Presence.Type.UNSUBSCRIBED);
Presence response = new Presence(Presence.Type.unsubscribed);
response.setTo(presence.getFrom());
connection.sendPacket(response);
}
@ -690,8 +668,7 @@ public class Roster {
Collection deletedEntries = new ArrayList();
RosterPacket rosterPacket = (RosterPacket)packet;
for (Iterator i=rosterPacket.getRosterItems(); i.hasNext(); ) {
RosterPacket.Item item = (RosterPacket.Item)i.next();
for (RosterPacket.Item item : rosterPacket.getRosterItems()) {
RosterEntry entry = new RosterEntry(item.getUser(), item.getName(),
item.getItemType(), item.getItemStatus(), connection);
@ -733,7 +710,7 @@ public class Roster {
}
// If the roster entry belongs to any groups, remove it from the
// list of unfiled entries.
if (item.getGroupNames().hasNext()) {
if (!item.getGroupNames().isEmpty()) {
synchronized (unfiledEntries) {
unfiledEntries.remove(entry);
}
@ -749,18 +726,16 @@ public class Roster {
}
// Find the list of groups that the user currently belongs to.
List currentGroupNames = new ArrayList();
for (Iterator j = entry.getGroups(); j.hasNext(); ) {
RosterGroup group = (RosterGroup)j.next();
currentGroupNames.add(group.getName());
List<String> currentGroupNames = new ArrayList<String>();
for (RosterGroup rosterGroup : entry.getGroups()) {
currentGroupNames.add(rosterGroup.getName());
}
// If the packet is not of the type REMOVE then add the entry to the groups
if (!RosterPacket.ItemType.REMOVE.equals(item.getItemType())) {
// Create the new list of groups the user belongs to.
List newGroupNames = new ArrayList();
for (Iterator k = item.getGroupNames(); k.hasNext(); ) {
String groupName = (String)k.next();
List<String> newGroupNames = new ArrayList<String>();
for (String groupName : item.getGroupNames()) {
// Add the group name to the list.
newGroupNames.add(groupName);
@ -798,12 +773,9 @@ public class Roster {
// RosterGroup.removeEntry removes the entry immediately (locally) and the
// group could remain empty.
// TODO Check the performance/logic for rosters with large number of groups
for (Iterator it = getGroups(); it.hasNext();) {
RosterGroup group = (RosterGroup)it.next();
for (RosterGroup group : getGroups()) {
if (group.getEntryCount() == 0) {
synchronized (groups) {
groups.remove(group.getName());
}
groups.remove(group.getName());
}
}
}

View File

@ -106,21 +106,20 @@ public class RosterEntry {
}
/**
* Returns an iterator for all the roster groups that this entry belongs to.
* Returns an unmodifiable collection of the roster groups that this entry belongs to.
*
* @return an iterator for the groups this entry belongs to.
*/
public Iterator getGroups() {
List results = new ArrayList();
public Collection<RosterGroup> getGroups() {
List<RosterGroup> results = new ArrayList<RosterGroup>();
// Loop through all roster groups and find the ones that contain this
// entry. This algorithm should be fine
for (Iterator i=connection.roster.getGroups(); i.hasNext(); ) {
RosterGroup group = (RosterGroup)i.next();
for (RosterGroup group: connection.roster.getGroups()) {
if (group.contains(this)) {
results.add(group);
}
}
return results.iterator();
return Collections.unmodifiableCollection(results);
}
/**
@ -152,14 +151,15 @@ public class RosterEntry {
buf.append(name).append(": ");
}
buf.append(user);
Iterator groups = getGroups();
if (groups.hasNext()) {
Collection<RosterGroup> groups = getGroups();
if (!groups.isEmpty()) {
buf.append(" [");
RosterGroup group = (RosterGroup)groups.next();
Iterator<RosterGroup> iter = groups.iterator();
RosterGroup group = iter.next();
buf.append(group.getName());
while (groups.hasNext()) {
while (iter.hasNext()) {
buf.append(", ");
group = (RosterGroup)groups.next();
group = iter.next();
buf.append(group.getName());
}
buf.append("]");
@ -184,8 +184,7 @@ public class RosterEntry {
item.setItemType(entry.getType());
item.setItemStatus(entry.getStatus());
// Set the correct group names for the item.
for (Iterator j=entry.getGroups(); j.hasNext(); ) {
RosterGroup group = (RosterGroup)j.next();
for (RosterGroup group : entry.getGroups()) {
item.addGroupName(group.getName());
}
return item;

View File

@ -37,7 +37,7 @@ public class RosterGroup {
private String name;
private XMPPConnection connection;
private List entries;
private List<RosterEntry> entries;
/**
* Creates a new roster group instance.
@ -48,7 +48,7 @@ public class RosterGroup {
RosterGroup(String name, XMPPConnection connection) {
this.name = name;
this.connection = connection;
entries = new ArrayList();
entries = new ArrayList<RosterEntry>();
}
/**
@ -95,13 +95,13 @@ public class RosterGroup {
}
/**
* Returns an iterator for the entries in the group.
* Returns an unmodifiable collection of all entries in the group.
*
* @return an iterator for the entries in the group.
* @return all entries in the group.
*/
public Iterator getEntries() {
public Collection<RosterEntry> getEntries() {
synchronized (entries) {
return Collections.unmodifiableList(new ArrayList(entries)).iterator();
return Collections.unmodifiableList(new ArrayList<RosterEntry>(entries));
}
}

View File

@ -454,7 +454,7 @@ public class XMPPConnection {
// Set presence to online.
if (sendPresence) {
packetWriter.sendPacket(new Presence(Presence.Type.AVAILABLE));
packetWriter.sendPacket(new Presence(Presence.Type.available));
}
// Indicate that we're now authenticated.
@ -512,7 +512,7 @@ public class XMPPConnection {
roster = null;
// Set presence to online.
packetWriter.sendPacket(new Presence(Presence.Type.AVAILABLE));
packetWriter.sendPacket(new Presence(Presence.Type.available));
// Indicate that we're now authenticated.
authenticated = true;
@ -595,24 +595,6 @@ public class XMPPConnection {
return new Chat(this, participant);
}
/**
* Creates a new group chat connected to the specified room. The room name
* should be full address, such as <tt>room@chat.example.com</tt>.
* <p>
* Most XMPP servers use a sub-domain for the chat service (eg chat.example.com
* for the XMPP server example.com). You must ensure that the room address you're
* trying to connect to includes the proper chat sub-domain.
*
* @param room the fully qualifed name of the room.
* @return a new GroupChat object.
*/
public GroupChat createGroupChat(String room) {
if (!isConnected()) {
throw new IllegalStateException("Not connected to server.");
}
return new GroupChat(this, room);
}
/**
* Returns true if currently connected to the XMPP server.
*
@ -656,7 +638,7 @@ public class XMPPConnection {
*/
public void close() {
// Set presence to offline.
packetWriter.sendPacket(new Presence(Presence.Type.UNAVAILABLE));
packetWriter.sendPacket(new Presence(Presence.Type.unavailable));
packetReader.shutdown();
packetWriter.shutdown();
// Wait 150 ms for processes to clean-up, then shutdown.

View File

@ -26,16 +26,16 @@ import org.jivesoftware.smack.util.StringUtils;
* Represents XMPP presence packets. Every presence packet has a type, which is one of
* the following values:
* <ul>
* <li><tt>Presence.Type.AVAILABLE</tt> -- (Default) indicates the user is available to
* <li>{@link Presence.Type#available available} -- (Default) indicates the user is available to
* receive messages.
* <li><tt>Presence.Type.UNAVAILABLE</tt> -- the user is unavailable to receive messages.
* <li><tt>Presence.Type.SUBSCRIBE</tt> -- request subscription to recipient's presence.
* <li><tt>Presence.Type.SUBSCRIBED</tt> -- grant subscription to sender's presence.
* <li><tt>Presence.Type.UNSUBSCRIBE</tt> -- request removal of subscription to sender's
* presence.
* <li><tt>Presence.Type.UNSUBSCRIBED</tt> -- grant removal of subscription to sender's
* presence.
* <li><tt>Presence.Type.ERROR</tt> -- the presence packet contains an error message.
* <li>{@link Presence.Type#unavailable unavailable} -- the user is unavailable to receive messages.
* <li>{@link Presence.Type#subscribe subscribe} -- request subscription to recipient's presence.
* <li>{@link Presence.Type#subscribed subscribed} -- grant subscription to sender's presence.
* <li>{@link Presence.Type#unsubscribe unsubscribe} -- request removal of subscription to
* sender's presence.
* <li>{@link Presence.Type#unsubscribed unsubscribed} -- grant removal of subscription to
* sender's presence.
* <li>{@link Presence.Type#error error} -- the presence packet contains an error message.
* </ul><p>
*
* A number of attributes are optional:
@ -44,8 +44,9 @@ import org.jivesoftware.smack.util.StringUtils;
* <li>Priority -- non-negative numerical priority of a sender's resource. The
* highest resource priority is the default recipient of packets not addressed
* to a particular resource.
* <li>Mode -- one of five presence modes: available (the default), chat, away,
* xa (extended away, and dnd (do not disturb).
* <li>Mode -- one of five presence modes: {@link Mode#available available} (the default),
* {@link Mode#chat chat}, {@link Mode#away away}, {@link Mode#xa xa} (extended away), and
* {@link Mode#dnd dnd} (do not disturb).
* </ul><p>
*
* Presence packets are used for two purposes. First, to notify the server of our
@ -57,10 +58,10 @@ import org.jivesoftware.smack.util.StringUtils;
*/
public class Presence extends Packet {
private Type type = Type.AVAILABLE;
private Type type = Type.available;
private String status = null;
private int priority = -1;
private Mode mode = Mode.AVAILABLE;
private Mode mode = Mode.available;
/**
* Creates a new presence update. Status, priority, and mode are left un-set.
@ -179,7 +180,7 @@ public class Presence extends Packet {
if (getFrom() != null) {
buf.append(" from=\"").append(StringUtils.escapeForXML(getFrom())).append("\"");
}
if (type != Type.AVAILABLE) {
if (type != Type.available) {
buf.append(" type=\"").append(type).append("\"");
}
buf.append(">");
@ -189,7 +190,7 @@ public class Presence extends Packet {
if (priority != -1) {
buf.append("<priority>").append(priority).append("</priority>");
}
if (mode != null && mode != Mode.AVAILABLE) {
if (mode != null && mode != Mode.available) {
buf.append("<show>").append(mode).append("</show>");
}
@ -219,105 +220,78 @@ public class Presence extends Packet {
}
/**
* A typsafe enum class to represent the presecence type.
* A enum to represent the presecence type. Not that presence type is often confused
* with presence mode. Generally, if a user is signed into a server, they have a presence
* type of {@link #available available}, even if the mode is {@link Mode#away away},
* {@link Mode#dnd dnd}, etc. The presence type is only {@link #unavailable unavailable} when
* the user is signing out of the server.
*/
public static class Type {
public enum Type {
public static final Type AVAILABLE = new Type("available");
public static final Type UNAVAILABLE = new Type("unavailable");
public static final Type SUBSCRIBE = new Type("subscribe");
public static final Type SUBSCRIBED = new Type("subscribed");
public static final Type UNSUBSCRIBE = new Type("unsubscribe");
public static final Type UNSUBSCRIBED = new Type("unsubscribed");
public static final Type ERROR = new Type("error");
private String value;
private Type(String value) {
this.value = value;
}
public String toString() {
return value;
}
/**
* The user is available to receive messages (default).
*/
available,
/**
* Returns the type constant associated with the String value.
* The user is unavailable to receive messages.
*/
public static Type fromString(String value) {
if (value == null) {
return AVAILABLE;
}
value = value.toLowerCase();
if ("unavailable".equals(value)) {
return UNAVAILABLE;
}
else if ("subscribe".equals(value)) {
return SUBSCRIBE;
}
else if ("subscribed".equals(value)) {
return SUBSCRIBED;
}
else if ("unsubscribe".equals(value)) {
return UNSUBSCRIBE;
}
else if ("unsubscribed".equals(value)) {
return UNSUBSCRIBED;
}
else if ("error".equals(value)) {
return ERROR;
}
// Default to available.
else {
return AVAILABLE;
}
}
unavailable,
/**
* Request subscription to recipient's presence.
*/
subscribe,
/**
* Grant subscription to sender's presence.
*/
subscribed,
/**
* Request removal of subscription to sender's presence.
*/
unsubscribe,
/**
* Grant removal of subscription to sender's presence.
*/
unsubscribed,
/**
* The presence packet contains an error message.
*/
error
}
/**
* A typsafe enum class to represent the presence mode.
* An enum to represent the presence mode.
*/
public static class Mode {
public static final Mode AVAILABLE = new Mode("available");
public static final Mode CHAT = new Mode("chat");
public static final Mode AWAY = new Mode("away");
public static final Mode EXTENDED_AWAY = new Mode("xa");
public static final Mode DO_NOT_DISTURB = new Mode("dnd");
private String value;
private Mode(String value) {
this.value = value;
}
public String toString() {
return value;
}
public enum Mode {
/**
* Returns the mode constant associated with the String value.
* Available (the default).
*/
public static Mode fromString(String value) {
if (value == null) {
return AVAILABLE;
}
value = value.toLowerCase();
if (value.equals("chat")) {
return CHAT;
}
else if (value.equals("away")) {
return AWAY;
}
else if (value.equals("xa")) {
return EXTENDED_AWAY;
}
else if (value.equals("dnd")) {
return DO_NOT_DISTURB;
}
else {
return AVAILABLE;
}
}
available,
/**
* Free to chat.
*/
chat,
/**
* Away.
*/
away,
/**
* Away for an extended period of time.
*/
xa,
/**
* Do not disturb.
*/
dnd
}
}
}

View File

@ -23,6 +23,7 @@ package org.jivesoftware.smack.packet;
import org.jivesoftware.smack.util.StringUtils;
import java.util.*;
import java.util.concurrent.CopyOnWriteArraySet;
/**
* Represents XMPP roster packets.
@ -31,7 +32,7 @@ import java.util.*;
*/
public class RosterPacket extends IQ {
private final List rosterItems = new ArrayList();
private final List<Item> rosterItems = new ArrayList<Item>();
/**
* Adds a roster item to the packet.
@ -56,14 +57,13 @@ public class RosterPacket extends IQ {
}
/**
* Returns an Iterator for the roster items in the packet.
* Returns an unmodifiable collection for the roster items in the packet.
*
* @return and Iterator for the roster items in the packet.
* @return an unmodifiable collection for the roster items in the packet.
*/
public Iterator getRosterItems() {
public Collection<Item> getRosterItems() {
synchronized (rosterItems) {
List entries = Collections.unmodifiableList(new ArrayList(rosterItems));
return entries.iterator();
return Collections.unmodifiableList(new ArrayList<Item>(rosterItems));
}
}
@ -71,8 +71,7 @@ public class RosterPacket extends IQ {
StringBuffer buf = new StringBuffer();
buf.append("<query xmlns=\"jabber:iq:roster\">");
synchronized (rosterItems) {
for (int i=0; i<rosterItems.size(); i++) {
Item entry = (Item)rosterItems.get(i);
for (Item entry : rosterItems) {
buf.append(entry.toXML());
}
}
@ -90,7 +89,7 @@ public class RosterPacket extends IQ {
private String name;
private ItemType itemType;
private ItemStatus itemStatus;
private final List groupNames;
private final Set<String> groupNames;
/**
* Creates a new roster item.
@ -103,7 +102,7 @@ public class RosterPacket extends IQ {
this.name = name;
itemType = null;
itemStatus = null;
groupNames = new ArrayList();
groupNames = new CopyOnWriteArraySet<String>();
}
/**
@ -170,15 +169,13 @@ public class RosterPacket extends IQ {
}
/**
* Returns an Iterator for the group names (as Strings) that the roster item
* Returns an unmodifiable set of the group names that the roster item
* belongs to.
*
* @return an Iterator for the group names.
* @return an unmodifiable set of the group names.
*/
public Iterator getGroupNames() {
synchronized (groupNames) {
return Collections.unmodifiableList(groupNames).iterator();
}
public Set<String> getGroupNames() {
return Collections.unmodifiableSet(groupNames);
}
/**
@ -187,11 +184,7 @@ public class RosterPacket extends IQ {
* @param groupName the group name.
*/
public void addGroupName(String groupName) {
synchronized (groupNames) {
if (!groupNames.contains(groupName)) {
groupNames.add(groupName);
}
}
groupNames.add(groupName);
}
/**
@ -200,9 +193,7 @@ public class RosterPacket extends IQ {
* @param groupName the group name.
*/
public void removeGroupName(String groupName) {
synchronized (groupNames) {
groupNames.remove(groupName);
}
groupNames.remove(groupName);
}
public String toXML() {
@ -218,11 +209,8 @@ public class RosterPacket extends IQ {
buf.append(" ask=\"").append(itemStatus).append("\"");
}
buf.append(">");
synchronized (groupNames) {
for (int i=0; i<groupNames.size(); i++) {
String groupName = (String)groupNames.get(i);
buf.append("<group>").append(StringUtils.escapeForXML(groupName)).append("</group>");
}
for (String groupName : groupNames) {
buf.append("<group>").append(StringUtils.escapeForXML(groupName)).append("</group>");
}
buf.append("</item>");
return buf.toString();

View File

@ -131,7 +131,16 @@ public class PacketParserUtils {
* @throws Exception if an exception occurs while parsing the packet.
*/
public static Presence parsePresence(XmlPullParser parser) throws Exception {
Presence.Type type = Presence.Type.fromString(parser.getAttributeValue("", "type"));
Presence.Type type = Presence.Type.available;
String typeString = parser.getAttributeValue("", "type");
if (typeString != null && !typeString.equals("")) {
try {
type = Presence.Type.valueOf(typeString);
}
catch (IllegalArgumentException iae) {
System.err.println("Found invalid presence type " + typeString);
}
}
Presence presence = new Presence(type);
presence.setTo(parser.getAttributeValue("", "to"));
@ -154,14 +163,22 @@ public class PacketParserUtils {
int priority = Integer.parseInt(parser.nextText());
presence.setPriority(priority);
}
catch (NumberFormatException nfe) { }
catch (NumberFormatException nfe) {
// Ignore.
}
catch (IllegalArgumentException iae) {
// Presence priority is out of range so assume priority to be zero
presence.setPriority(0);
}
}
else if (elementName.equals("show")) {
presence.setMode(Presence.Mode.fromString(parser.nextText()));
String modeText = parser.nextText();
try {
presence.setMode(Presence.Mode.valueOf(modeText));
}
catch (IllegalArgumentException iae) {
System.err.println("Found invalid presence mode " + modeText);
}
}
else if (elementName.equals("error")) {
presence.setError(parseError(parser));

View File

@ -129,8 +129,9 @@ public class RosterExchangeManager {
Message msg = new Message(targetUserID);
// Create a RosterExchange Package and add it to the message
RosterExchange rosterExchange = new RosterExchange();
for (Iterator it = rosterGroup.getEntries(); it.hasNext();)
rosterExchange.addRosterEntry((RosterEntry) it.next());
for (RosterEntry entry : rosterGroup.getEntries()) {
rosterExchange.addRosterEntry(entry);
}
msg.addExtension(rosterExchange);
// Send the message that contains the roster

View File

@ -47,7 +47,7 @@ public class DeafOccupantInterceptor implements PacketInterceptor {
public void interceptPacket(Packet packet) {
Presence presence = (Presence) packet;
// Check if user is joining a room
if (Presence.Type.AVAILABLE == presence.getType() &&
if (Presence.Type.available == presence.getType() &&
presence.getExtension("x", "http://jabber.org/protocol/muc") != null) {
// Add extension that indicates that user wants to be a deaf occupant
packet.addExtension(new DeafExtension());

View File

@ -291,7 +291,7 @@ public class MultiUserChat {
}
// We create a room by sending a presence packet to room@service/nick
// and signal support for MUC. The owner will be automatically logged into the room.
Presence joinPresence = new Presence(Presence.Type.AVAILABLE);
Presence joinPresence = new Presence(Presence.Type.available);
joinPresence.setTo(room + "/" + nickname);
// Indicate the the client supports MUC
joinPresence.addExtension(new MUCInitialPresence());
@ -422,7 +422,7 @@ public class MultiUserChat {
}
// We join a room by sending a presence packet where the "to"
// field is in the form "roomName@service/nickname"
Presence joinPresence = new Presence(Presence.Type.AVAILABLE);
Presence joinPresence = new Presence(Presence.Type.available);
joinPresence.setTo(room + "/" + nickname);
// Indicate the the client supports MUC
@ -484,7 +484,7 @@ public class MultiUserChat {
}
// We leave a room by sending a presence packet where the "to"
// field is in the form "roomName@service/nickname"
Presence leavePresence = new Presence(Presence.Type.UNAVAILABLE);
Presence leavePresence = new Presence(Presence.Type.unavailable);
leavePresence.setTo(room + "/" + nickname);
// Invoke presence interceptors so that extra information can be dynamically added
for (Iterator it = presenceInterceptors.iterator(); it.hasNext();) {
@ -944,7 +944,7 @@ public class MultiUserChat {
// We change the nickname by sending a presence packet where the "to"
// field is in the form "roomName@service/nickname"
// We don't have to signal the MUC support again
Presence joinPresence = new Presence(Presence.Type.AVAILABLE);
Presence joinPresence = new Presence(Presence.Type.available);
joinPresence.setTo(room + "/" + nickname);
// Invoke presence interceptors so that extra information can be dynamically added
for (Iterator it = presenceInterceptors.iterator(); it.hasNext();) {
@ -995,7 +995,7 @@ public class MultiUserChat {
}
// We change the availability status by sending a presence packet to the room with the
// new presence status and mode
Presence joinPresence = new Presence(Presence.Type.AVAILABLE);
Presence joinPresence = new Presence(Presence.Type.available);
joinPresence.setStatus(status);
joinPresence.setMode(mode);
joinPresence.setTo(room + "/" + nickname);
@ -2112,7 +2112,7 @@ public class MultiUserChat {
String from = presence.getFrom();
String myRoomJID = room + "/" + nickname;
boolean isUserStatusModification = presence.getFrom().equals(myRoomJID);
if (presence.getType() == Presence.Type.AVAILABLE) {
if (presence.getType() == Presence.Type.available) {
Presence oldPresence;
synchronized (occupantsMap) {
oldPresence = (Presence)occupantsMap.get(from);
@ -2145,7 +2145,7 @@ public class MultiUserChat {
}
}
}
else if (presence.getType() == Presence.Type.UNAVAILABLE) {
else if (presence.getType() == Presence.Type.unavailable) {
synchronized (occupantsMap) {
occupantsMap.remove(from);
}

View File

@ -64,8 +64,8 @@ public class RosterExchange implements PacketExtension {
*/
public RosterExchange(Roster roster) {
// Add all the roster entries to the new RosterExchange
for (Iterator rosterEntries = roster.getEntries(); rosterEntries.hasNext();) {
this.addRosterEntry((RosterEntry) rosterEntries.next());
for (RosterEntry rosterEntry : roster.getEntries()) {
this.addRosterEntry(rosterEntry);
}
}
@ -76,15 +76,16 @@ public class RosterExchange implements PacketExtension {
*/
public void addRosterEntry(RosterEntry rosterEntry) {
// Obtain a String[] from the roster entry groups name
ArrayList groupNamesList = new ArrayList();
List<String> groupNamesList = new ArrayList<String>();
String[] groupNames;
for (Iterator groups = rosterEntry.getGroups(); groups.hasNext();) {
groupNamesList.add(((RosterGroup) groups.next()).getName());
for (RosterGroup group : rosterEntry.getGroups()) {
groupNamesList.add(group.getName());
}
groupNames = (String[]) groupNamesList.toArray(new String[groupNamesList.size()]);
groupNames = groupNamesList.toArray(new String[groupNamesList.size()]);
// Create a new Entry based on the rosterEntry and add it to the packet
RemoteRosterEntry remoteRosterEntry = new RemoteRosterEntry(rosterEntry.getUser(), rosterEntry.getName(), groupNames);
RemoteRosterEntry remoteRosterEntry = new RemoteRosterEntry(rosterEntry.getUser(),
rosterEntry.getName(), groupNames);
addRosterEntry(remoteRosterEntry);
}

View File

@ -3,11 +3,11 @@
<testcase>
<!-- Host and port of the XMPP server to use -->
<host>localhost</host>
<host>zeushome2</host>
<port>5222</port>
<!-- Chat and MUC domain names to use -->
<chat>chat.localhost</chat>
<muc>conference.localhost</muc>
<chat>chat</chat>
<muc>conference</muc>
</testcase>

View File

@ -42,7 +42,7 @@ public class MessageTest extends SmackTestCase {
*/
public void testOfflineMessage() {
// Make user2 unavailable
getConnection(1).sendPacket(new Presence(Presence.Type.UNAVAILABLE));
getConnection(1).sendPacket(new Presence(Presence.Type.unavailable));
try {
Thread.sleep(500);
@ -56,7 +56,7 @@ public class MessageTest extends SmackTestCase {
// User2 becomes available again
PacketCollector collector = getConnection(1).createPacketCollector(new MessageTypeFilter(Message.Type.CHAT));
getConnection(1).sendPacket(new Presence(Presence.Type.AVAILABLE));
getConnection(1).sendPacket(new Presence(Presence.Type.available));
// Check that offline messages are retrieved by user2 which is now available
Message message = (Message) collector.nextResult(2500);

View File

@ -37,10 +37,10 @@ public class PresencePriorityTest extends SmackTestCase {
conn = new XMPPConnection(getHost(), getPort());
conn.login(getUsername(1), getUsername(1), "OtherPlace");
// Change the presence priorities of User_1
getConnection(1).sendPacket(new Presence(Presence.Type.AVAILABLE, null, 1,
Presence.Mode.AVAILABLE));
conn.sendPacket(new Presence(Presence.Type.AVAILABLE, null, 2,
Presence.Mode.AVAILABLE));
getConnection(1).sendPacket(new Presence(Presence.Type.available, null, 1,
Presence.Mode.available));
conn.sendPacket(new Presence(Presence.Type.available, null, 2,
Presence.Mode.available));
Thread.sleep(150);
// Create the chats between the participants
Chat chat0 = new Chat(getConnection(0), getBareJID(1));
@ -55,10 +55,10 @@ public class PresencePriorityTest extends SmackTestCase {
chat1.nextMessage(1000));
// Invert the presence priorities of User_1
getConnection(1).sendPacket(new Presence(Presence.Type.AVAILABLE, null, 2,
Presence.Mode.AVAILABLE));
conn.sendPacket(new Presence(Presence.Type.AVAILABLE, null, 1,
Presence.Mode.AVAILABLE));
getConnection(1).sendPacket(new Presence(Presence.Type.available, null, 2,
Presence.Mode.available));
conn.sendPacket(new Presence(Presence.Type.available, null, 1,
Presence.Mode.available));
Thread.sleep(150);
// Test delivery of message to the presence with highest priority
@ -78,14 +78,14 @@ public class PresencePriorityTest extends SmackTestCase {
assertNotNull("Resource with highest priority didn't receive the message",
chat1.nextMessage(2000));
getConnection(1).sendPacket(new Presence(Presence.Type.AVAILABLE, null, 2,
Presence.Mode.AVAILABLE));
getConnection(1).sendPacket(new Presence(Presence.Type.available, null, 2,
Presence.Mode.available));
// User_1 will log in again using another resource
conn = new XMPPConnection(getHost(), getPort());
conn.login(getUsername(1), getUsername(1), "OtherPlace");
conn.sendPacket(new Presence(Presence.Type.AVAILABLE, null, 1,
Presence.Mode.AVAILABLE));
conn.sendPacket(new Presence(Presence.Type.available, null, 1,
Presence.Mode.available));
chat2 = new Chat(conn, getBareJID(0), chat0.getThreadID());
Thread.sleep(150);
@ -97,10 +97,10 @@ public class PresencePriorityTest extends SmackTestCase {
chat2.nextMessage(1000));
// Invert the presence priorities of User_1
getConnection(1).sendPacket(new Presence(Presence.Type.AVAILABLE, null, 1,
Presence.Mode.AVAILABLE));
conn.sendPacket(new Presence(Presence.Type.AVAILABLE, null, 2,
Presence.Mode.AVAILABLE));
getConnection(1).sendPacket(new Presence(Presence.Type.available, null, 1,
Presence.Mode.available));
conn.sendPacket(new Presence(Presence.Type.available, null, 2,
Presence.Mode.available));
Thread.sleep(150);
// Test delivery of message to the presence with highest priority

View File

@ -58,6 +58,7 @@ import org.jivesoftware.smack.util.StringUtils;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
/**
* Tests the Roster functionality by creating and removing roster entries.
@ -91,12 +92,8 @@ public class RosterTest extends SmackTestCase {
Thread.sleep(50);
}
Iterator it = roster.getEntries();
while (it.hasNext()) {
RosterEntry entry = (RosterEntry) it.next();
Iterator groups = entry.getGroups();
while (groups.hasNext()) {
RosterGroup rosterGroup = (RosterGroup) groups.next();
for (RosterEntry entry : roster.getEntries()) {
for (RosterGroup rosterGroup : entry.getGroups()) {
rosterGroup.removeEntry(entry);
}
}
@ -172,9 +169,7 @@ public class RosterTest extends SmackTestCase {
assertNotNull("Presence not received", roster.getPresence(getBareJID(1)));
assertNotNull("Presence not received", roster.getPresence(getBareJID(2)));
Iterator it = roster.getEntries();
while (it.hasNext()) {
RosterEntry entry = (RosterEntry) it.next();
for (RosterEntry entry : roster.getEntries()) {
roster.removeEntry(entry);
Thread.sleep(250);
}
@ -216,9 +211,7 @@ public class RosterTest extends SmackTestCase {
Thread.sleep(200);
Iterator it = roster.getEntries();
while (it.hasNext()) {
RosterEntry entry = (RosterEntry) it.next();
for (RosterEntry entry : roster.getEntries()) {
roster.removeEntry(entry);
Thread.sleep(250);
}
@ -256,18 +249,14 @@ public class RosterTest extends SmackTestCase {
Thread.sleep(200);
// Change the roster entry name and check if the change was made
Iterator it = roster.getEntries();
while (it.hasNext()) {
RosterEntry entry = (RosterEntry) it.next();
for (RosterEntry entry : roster.getEntries()) {
entry.setName("gato11");
assertEquals("gato11", entry.getName());
}
// Reload the roster and check the name again
roster.reload();
Thread.sleep(2000);
it = roster.getEntries();
while (it.hasNext()) {
RosterEntry entry = (RosterEntry) it.next();
for (RosterEntry entry : roster.getEntries()) {
assertEquals("gato11", entry.getName());
}
@ -302,10 +291,8 @@ public class RosterTest extends SmackTestCase {
}
//assertNotNull("Presence not received", roster.getPresence(getBareJID(0)));
Iterator it = roster.getEntries();
while (it.hasNext()) {
RosterEntry entry = (RosterEntry) it.next();
assertFalse("The roster entry belongs to a group", entry.getGroups().hasNext());
for (RosterEntry entry : roster.getEntries()) {
assertFalse("The roster entry belongs to a group", !entry.getGroups().isEmpty());
}
// Change the roster entry name and check if the change was made
@ -313,12 +300,9 @@ public class RosterTest extends SmackTestCase {
// Reload the roster and check the name again
Thread.sleep(200);
it = roster.getEntries();
while (it.hasNext()) {
RosterEntry entry = (RosterEntry) it.next();
for (RosterEntry entry : roster.getEntries()) {
assertEquals("Name of roster entry is wrong", "NewName", entry.getName());
assertTrue("The roster entry does not belong to any group", entry.getGroups()
.hasNext());
assertTrue("The roster entry does not belong to any group", !entry.getGroups().isEmpty());
}
// Wait up to 5 seconds to receive presences of the new roster contacts
initial = System.currentTimeMillis();
@ -372,12 +356,12 @@ public class RosterTest extends SmackTestCase {
RosterEntry entry = roster2.getEntry(getBareJID(1));
assertNotNull("No entry for user 1 was found", entry);
ArrayList groups = new ArrayList();
Iterator groupsItr = entry.getGroups();
groups.add(((RosterGroup)groupsItr.next()).getName());
groups.add(((RosterGroup)groupsItr.next()).getName());
assertTrue("Friends group was not found", groups.contains("Friends"));
assertTrue("NewGroup group was not found", groups.contains("NewGroup"));
List<String> groupNames = new ArrayList<String>();
for (RosterGroup rosterGroup : entry.getGroups()) {
groupNames.add(rosterGroup.getName());
}
assertTrue("Friends group was not found", groupNames.contains("Friends"));
assertTrue("NewGroup group was not found", groupNames.contains("NewGroup"));
// Close the new connection
con2.close();
@ -584,12 +568,11 @@ public class RosterTest extends SmackTestCase {
private void cleanUpRoster() {
for (int i=0; i<getMaxConnections(); i++) {
// Delete all the entries from the roster
Iterator it = getConnection(i).getRoster().getEntries();
while (it.hasNext()) {
RosterEntry entry = (RosterEntry) it.next();
for (RosterEntry entry : getConnection(i).getRoster().getEntries()) {
try {
getConnection(i).getRoster().removeEntry(entry);
} catch (XMPPException e) {
}
catch (XMPPException e) {
e.printStackTrace();
fail(e.getMessage());
}

View File

@ -55,8 +55,8 @@ public abstract class SmackTestCase extends TestCase {
private String serviceName = "localhost";
private int port = 5222;
private String chatDomain = "chat.localhost";
private String mucDomain = "conference.localhost";
private String chatDomain = "chat";
private String mucDomain = "conference";
private XMPPConnection[] connections = null;
@ -172,7 +172,7 @@ public abstract class SmackTestCase extends TestCase {
* @return the default MUC service domain.
*/
protected String getMUCDomain() {
return mucDomain;
return mucDomain + "." + serviceName;
}
protected void setUp() throws Exception {

View File

@ -58,7 +58,7 @@ public class OfflineMessageManagerTest extends SmackTestCase {
*/
public void testReadAndDelete() {
// Make user2 unavailable
getConnection(1).sendPacket(new Presence(Presence.Type.UNAVAILABLE));
getConnection(1).sendPacket(new Presence(Presence.Type.unavailable));
try {
Thread.sleep(500);
@ -103,7 +103,7 @@ public class OfflineMessageManagerTest extends SmackTestCase {
// User2 becomes available again
PacketCollector collector = getConnection(1).createPacketCollector(
new MessageTypeFilter(Message.Type.CHAT));
getConnection(1).sendPacket(new Presence(Presence.Type.AVAILABLE));
getConnection(1).sendPacket(new Presence(Presence.Type.available));
// Check that no offline messages was sent to the user
Message message = (Message) collector.nextResult(2500);
@ -127,7 +127,7 @@ public class OfflineMessageManagerTest extends SmackTestCase {
*/
public void testFetchAndPurge() {
// Make user2 unavailable
getConnection(1).sendPacket(new Presence(Presence.Type.UNAVAILABLE));
getConnection(1).sendPacket(new Presence(Presence.Type.unavailable));
try {
Thread.sleep(500);
@ -161,7 +161,7 @@ public class OfflineMessageManagerTest extends SmackTestCase {
// User2 becomes available again
PacketCollector collector = getConnection(1).createPacketCollector(
new MessageTypeFilter(Message.Type.CHAT));
getConnection(1).sendPacket(new Presence(Presence.Type.AVAILABLE));
getConnection(1).sendPacket(new Presence(Presence.Type.available));
// Check that no offline messages was sent to the user
Message message = (Message) collector.nextResult(2500);

View File

@ -104,10 +104,10 @@ public class RosterExchangeManagerTest extends SmackTestCase {
public void testSendRosterGroup() {
// Send user1's RosterGroups to user2
try {
RosterExchangeManager rosterExchangeManager =
new RosterExchangeManager(getConnection(0));
for (Iterator it = getConnection(0).getRoster().getGroups(); it.hasNext();)
rosterExchangeManager.send((RosterGroup) it.next(), getBareJID(1));
RosterExchangeManager rosterExchangeManager = new RosterExchangeManager(getConnection(0));
for (RosterGroup rosterGroup : getConnection(0).getRoster().getGroups()) {
rosterExchangeManager.send(rosterGroup, getBareJID(1));
}
}
catch (Exception e) {
e.printStackTrace();

View File

@ -91,7 +91,9 @@ public class MultiUserChatTest extends SmackTestCase {
* protocol.
*/
public void testGroupchatCompatibility() {
try {
// TODO: this test needs to be re-written so that it manually emulates the old-style
// TODO: group chat protocol. Tne GroupChat class was deleted for Smack 3.0.
/*try {
Message message;
GroupChat groupchat = new GroupChat(getConnection(1), room);
@ -103,7 +105,7 @@ public class MultiUserChatTest extends SmackTestCase {
assertNotNull("Presence of user2 in room is missing", presence);
assertEquals(
"Presence mode of user2 is wrong",
Presence.Mode.AVAILABLE,
Presence.Mode.available,
presence.getMode());
// User using old client send a message
@ -126,7 +128,7 @@ public class MultiUserChatTest extends SmackTestCase {
catch (Exception e) {
e.printStackTrace();
fail(e.getMessage());
}
}*/
}
public void testDiscussionHistory() {
@ -202,16 +204,16 @@ public class MultiUserChatTest extends SmackTestCase {
assertNotNull("Presence of user2 in room is missing", presence);
assertEquals(
"Presence mode of user2 is wrong",
Presence.Mode.AVAILABLE,
Presence.Mode.available,
presence.getMode());
// User2 changes his availability to AWAY
muc2.changeAvailabilityStatus("Gone to have lunch", Presence.Mode.AWAY);
muc2.changeAvailabilityStatus("Gone to have lunch", Presence.Mode.away);
Thread.sleep(200);
// User1 checks the presence of user2 in the room
presence = muc.getOccupantPresence(room + "/testbot2");
assertNotNull("Presence of user2 in room is missing", presence);
assertEquals("Presence mode of user2 is wrong", Presence.Mode.AWAY, presence.getMode());
assertEquals("Presence mode of user2 is wrong", Presence.Mode.away, presence.getMode());
assertEquals(
"Presence status of user2 is wrong",
"Gone to have lunch",
@ -258,7 +260,7 @@ public class MultiUserChatTest extends SmackTestCase {
assertNotNull("Presence of user2 in room is missing", presence);
assertEquals(
"Presence mode of user2 is wrong",
Presence.Mode.AVAILABLE,
Presence.Mode.available,
presence.getMode());
// Anonymous user leaves the room