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
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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>
|
|
@ -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>
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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, "&", "&");
|
||||
body = this.replace(body, "<", "<");
|
||||
body = this.replace(body, ">", ">");
|
||||
|
||||
// replace newlines in the body:
|
||||
body = this.replace(body, "\r", "");
|
||||
body = this.replace(body, "\n", "<br>");
|
||||
|
||||
// encode the quotes
|
||||
body = this.replace(body, "\"", """);
|
||||
|
||||
// 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -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>
|
|
@ -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>
|
|
@ -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>
|
|
@ -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 + "\"> · " + 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);
|
||||
}
|
|
@ -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>
|
Before Width: | Height: | Size: 692 B |
Before Width: | Height: | Size: 688 B |
Before Width: | Height: | Size: 688 B |
Before Width: | Height: | Size: 687 B |
Before Width: | Height: | Size: 693 B |
Before Width: | Height: | Size: 1.1 KiB |
Before Width: | Height: | Size: 680 B |
Before Width: | Height: | Size: 675 B |
Before Width: | Height: | Size: 670 B |
Before Width: | Height: | Size: 1.1 KiB |
Before Width: | Height: | Size: 693 B |
Before Width: | Height: | Size: 678 B |
Before Width: | Height: | Size: 694 B |
Before Width: | Height: | Size: 688 B |
Before Width: | Height: | Size: 685 B |
Before Width: | Height: | Size: 634 B |
Before Width: | Height: | Size: 925 B |
Before Width: | Height: | Size: 325 B |
|
@ -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>
|
|
@ -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>
|
|
@ -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>
|
|
@ -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; }
|
|
@ -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>
|
|
@ -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>
|
||||
|
|
|
@ -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" />
|
||||
|
|
|
@ -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" />
|
||||
|
|
|
@ -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) {}
|
||||
}
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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();
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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>
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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
|
||||
|
|