Smack 1.5.1 + SMACK-73. Branch generated to include TLS support in HEAD.
git-svn-id: http://svn.igniterealtime.org/svn/repos/smack/trunk@2716 b35dd754-fafc-0310-a699-88a17e54d16e
42
CopyOftrunk/apps/webchat/build/ant
Normal file
|
@ -0,0 +1,42 @@
|
|||
#! /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
|
||||
|
52
CopyOftrunk/apps/webchat/build/ant.bat
Normal file
|
@ -0,0 +1,52 @@
|
|||
@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
|
||||
|
91
CopyOftrunk/apps/webchat/build/build.xml
Normal file
|
@ -0,0 +1,91 @@
|
|||
<?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>
|
BIN
CopyOftrunk/apps/webchat/build/lib/servlet.jar
Normal file
167
CopyOftrunk/apps/webchat/source/config/WEB-INF/web.xml
Normal file
|
@ -0,0 +1,167 @@
|
|||
<?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>
|
|
@ -0,0 +1,292 @@
|
|||
/**
|
||||
* $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;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,729 @@
|
|||
/**
|
||||
* $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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,126 @@
|
|||
/**
|
||||
* $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;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,312 @@
|
|||
/**
|
||||
* $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;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,188 @@
|
|||
/**
|
||||
* $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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
116
CopyOftrunk/apps/webchat/source/web/account_creation.jsp
Normal file
|
@ -0,0 +1,116 @@
|
|||
<%--
|
||||
-
|
||||
-
|
||||
--%>
|
||||
|
||||
<%@ 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>
|
19
CopyOftrunk/apps/webchat/source/web/chat-hiddenform.jsp
Normal file
|
@ -0,0 +1,19 @@
|
|||
<!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>
|
39
CopyOftrunk/apps/webchat/source/web/chat-launcher.jsp
Normal file
|
@ -0,0 +1,39 @@
|
|||
<!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>
|
182
CopyOftrunk/apps/webchat/source/web/common.js
Normal file
|
@ -0,0 +1,182 @@
|
|||
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);
|
||||
}
|
33
CopyOftrunk/apps/webchat/source/web/frame_master.jsp
Normal file
|
@ -0,0 +1,33 @@
|
|||
<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>
|
BIN
CopyOftrunk/apps/webchat/source/web/images/emoticons/angry.gif
Normal file
After Width: | Height: | Size: 692 B |
BIN
CopyOftrunk/apps/webchat/source/web/images/emoticons/blush.gif
Normal file
After Width: | Height: | Size: 688 B |
After Width: | Height: | Size: 688 B |
BIN
CopyOftrunk/apps/webchat/source/web/images/emoticons/cool.gif
Normal file
After Width: | Height: | Size: 687 B |
BIN
CopyOftrunk/apps/webchat/source/web/images/emoticons/cry.gif
Normal file
After Width: | Height: | Size: 693 B |
BIN
CopyOftrunk/apps/webchat/source/web/images/emoticons/devil.gif
Normal file
After Width: | Height: | Size: 1.1 KiB |
BIN
CopyOftrunk/apps/webchat/source/web/images/emoticons/grin.gif
Normal file
After Width: | Height: | Size: 680 B |
BIN
CopyOftrunk/apps/webchat/source/web/images/emoticons/happy.gif
Normal file
After Width: | Height: | Size: 675 B |
BIN
CopyOftrunk/apps/webchat/source/web/images/emoticons/laugh.gif
Normal file
After Width: | Height: | Size: 670 B |
BIN
CopyOftrunk/apps/webchat/source/web/images/emoticons/love.gif
Normal file
After Width: | Height: | Size: 1.1 KiB |
After Width: | Height: | Size: 693 B |
BIN
CopyOftrunk/apps/webchat/source/web/images/emoticons/plain.gif
Normal file
After Width: | Height: | Size: 678 B |
BIN
CopyOftrunk/apps/webchat/source/web/images/emoticons/sad.gif
Normal file
After Width: | Height: | Size: 694 B |
BIN
CopyOftrunk/apps/webchat/source/web/images/emoticons/shocked.gif
Normal file
After Width: | Height: | Size: 688 B |
BIN
CopyOftrunk/apps/webchat/source/web/images/emoticons/silly.gif
Normal file
After Width: | Height: | Size: 685 B |
BIN
CopyOftrunk/apps/webchat/source/web/images/emoticons/wink.gif
Normal file
After Width: | Height: | Size: 634 B |
BIN
CopyOftrunk/apps/webchat/source/web/images/logo.gif
Normal file
After Width: | Height: | Size: 925 B |
BIN
CopyOftrunk/apps/webchat/source/web/images/logout-16x16.gif
Normal file
After Width: | Height: | Size: 325 B |
164
CopyOftrunk/apps/webchat/source/web/index.jsp
Normal file
|
@ -0,0 +1,164 @@
|
|||
<%--
|
||||
-
|
||||
-
|
||||
--%>
|
||||
|
||||
<%@ 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>
|
75
CopyOftrunk/apps/webchat/source/web/input_frame.jsp
Normal file
|
@ -0,0 +1,75 @@
|
|||
<%@ 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>
|
46
CopyOftrunk/apps/webchat/source/web/participants_frame.jsp
Normal file
|
@ -0,0 +1,46 @@
|
|||
<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>
|
132
CopyOftrunk/apps/webchat/source/web/style_sheet.jsp
Normal file
|
@ -0,0 +1,132 @@
|
|||
<% // 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; }
|
13
CopyOftrunk/apps/webchat/source/web/transcript_frame.html
Normal file
|
@ -0,0 +1,13 @@
|
|||
<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>
|
309
CopyOftrunk/build/README.html
Normal file
|
@ -0,0 +1,309 @@
|
|||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<title>Smack Source Distribution</title>
|
||||
<style type="text/css">
|
||||
BODY {
|
||||
font-size : 100%;
|
||||
}
|
||||
BODY, TD, TH {
|
||||
font-family : tahoma, verdana, arial, helvetica, sans-serif;
|
||||
font-size : 0.8em;
|
||||
}
|
||||
A:hover {
|
||||
text-decoration : none;
|
||||
}
|
||||
.pageheader {
|
||||
font-family : arial, helvetica, sans-serif;
|
||||
font-size : 14pt;
|
||||
font-weight: bold;
|
||||
}
|
||||
.header {
|
||||
font-family : arial, helvetica, sans-serif;
|
||||
font-size : 12pt;
|
||||
font-weight: bold;
|
||||
}
|
||||
.subheader {
|
||||
font-weight: bold;
|
||||
color: #600;
|
||||
}
|
||||
.path {
|
||||
color : #3333cc;
|
||||
}
|
||||
.question {
|
||||
font-style : italic;
|
||||
}
|
||||
.answer {
|
||||
padding-left : 15px;
|
||||
}
|
||||
.code {
|
||||
font-family : courier new;
|
||||
border : 1px #ccc solid;
|
||||
padding : 6px;
|
||||
margin : 5px 20px 5px 20px;
|
||||
}
|
||||
TT {
|
||||
font-family : courier new;
|
||||
font-weight : bold;
|
||||
color : #060;
|
||||
}
|
||||
PRE, CODE {
|
||||
font-family : courier new;
|
||||
font-size : 100%;
|
||||
}
|
||||
.footer {
|
||||
font-size : 0.8em;
|
||||
color : #666;
|
||||
text-align : center;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body bgcolor="#ffffff">
|
||||
|
||||
<font size=4>
|
||||
Smack Source Distribution<br>
|
||||
</font><br>
|
||||
<p>
|
||||
|
||||
This document provides detailed information for developers that wish to
|
||||
compile and make changes to the Smack source code.
|
||||
|
||||
<p>For additional developer resources, please visit:
|
||||
<a href="http://www.jivesoftware.org/smack/">
|
||||
http://www.jivesoftware.org/smack/</a>. The Smack build process is based on Ant. Visit the
|
||||
<a href="http://jakarta.apache.org/ant/index.html">Ant website</a>
|
||||
for more information. There is no need to download and install Ant - a version of it is included
|
||||
in this distribution.
|
||||
<p>
|
||||
This documentation is divided into two sections:
|
||||
<ol>
|
||||
<li> <a href="#setup">Setup</a> -- how to setup your environment for Smack development.
|
||||
<li> <a href="#tasks">Build tasks</a> -- tasks that can be performed using the build program.
|
||||
</ol>
|
||||
|
||||
<p><a name="setup"><b><font color="#0066cc">1.</font> Setup Your Environment</b></a><p>
|
||||
|
||||
Getting your machine ready for Smack development requires a few steps. Wherever
|
||||
possible, instructions are provided for both Unix/Linux and Windows users.
|
||||
<p>
|
||||
<b><a name="javaSetup">Configure Java</a></b>
|
||||
<ul>
|
||||
Java 2 (JDK 1.2 or later) must be installed and setup on your machine. To test the installation,
|
||||
open a shell in a Unix or a MS-DOS prompt in Windows. Check your version of
|
||||
Java with "java -version" -- it must version 1.2 or greater.
|
||||
If Java isn't installed, download a copy from the
|
||||
<a href="http://java.sun.com/">Java website</a>.
|
||||
<p>
|
||||
<font color="red">Important!</font> -- the Smack build tool needs to know
|
||||
where Java is installed on your system. You must configure the "JAVA_HOME"
|
||||
environment variable to point to the correct directory. Instructions on
|
||||
how to set this variable for various platforms are as follows:
|
||||
<p>
|
||||
<ul>
|
||||
<li> Unix/Linux
|
||||
<ol>
|
||||
<li>Edit the ".profile" file in your home directory (or
|
||||
corresponding file for your shell).
|
||||
<li>Set the JAVA_HOME environment variable by adding the
|
||||
following line to the file:
|
||||
<p></font><code>
|
||||
export JAVA_HOME=/usr/local/jdk1.3
|
||||
</code><font face="verdana, arial, helvetica" size=2>
|
||||
<p>
|
||||
The value "/usr/local/jdk1.3" should be replaced with your actual
|
||||
Java directory. Be sure there are no spaces after the end of
|
||||
the directory name. Do not add an extra slash after the directory name.
|
||||
<li>Save changes to the file and then "source" it:
|
||||
<p></font><code>
|
||||
source .profile
|
||||
</code><font face="verdana, arial, helvetica" size=2>
|
||||
<p>
|
||||
The JAVA_HOME variable should now be configured correctly.
|
||||
</ol>
|
||||
<p>
|
||||
<li> WindowsNT/2000
|
||||
<ol>
|
||||
<li>Navigate to your desktop and right click on "My Computer";
|
||||
choose properties.
|
||||
<li>Select the "Advanced" tab and click on the
|
||||
"Environment Variables" button.
|
||||
<li>Click the "New..." button in the System variables section.
|
||||
Enter the variable name "JAVA_HOME" and set the variable
|
||||
value to the full path of your Java installation. For example,
|
||||
"c:\jdk1.3". Be sure to not add an extra slash to the end
|
||||
of the directory name.
|
||||
<li>Click "OK" in all of the menus to accept the changes.
|
||||
<li>Close any open command prompt windows. The next time you
|
||||
open a command prompt, the "JAVA_HOME" variable will be set
|
||||
correctly.
|
||||
</ol>
|
||||
<p>
|
||||
<li> Windows95/98
|
||||
<ol>
|
||||
<li>Open your autoexec.bat file (often at "c:\autoexec.bat") using Notepad.
|
||||
<li>Add a line to the end of the file that resembles the following:
|
||||
<p></font><code>
|
||||
set JAVA_HOME=c:\jdk1.3
|
||||
</code><font face="verdana, arial, helvetica" size=2>
|
||||
<p>
|
||||
The value "c:\jdk1.3" should be replaced with your actual
|
||||
Java directory. Be sure there are no spaces between
|
||||
the "=" sign or after the end of the directory name. Do
|
||||
not add an extra slash after the directory name.
|
||||
<li>Save changes to autoexec.bat and restart your computer.
|
||||
</ol>
|
||||
</ul>
|
||||
</ul>
|
||||
|
||||
<p><b><a name="checkout">Test the Build Script</a></b><p>
|
||||
<ul>
|
||||
Navigate into the subdirectory of this distribution named "build" via the command-line.<p>
|
||||
|
||||
<table boder=0 cellpadding=2 cellspacing=0><td bgcolor="#EEEEEE">
|
||||
<font face="verdana, arial, helvetica" size=2>
|
||||
<font color="red">Linux/Unix users only:</font>You must make the ant script
|
||||
executable. From the build directory, type:
|
||||
<p></font><code>
|
||||
chmod u+x ant
|
||||
</code><font face="verdana, arial, helvetica" size=2>
|
||||
</td></table>
|
||||
|
||||
<p>
|
||||
Now, invoke the build tool to compile the Smack source code
|
||||
|
||||
<p>
|
||||
Windows:</font><code> ant <br>
|
||||
</code><font face="verdana, arial, helvetica" size=2>
|
||||
Unix/Linux:</font><code> ./ant
|
||||
</code><font face="verdana, arial, helvetica" size=2>
|
||||
<p>
|
||||
|
||||
If the build tool is invoked correctly and Smack compiles, you've correctly
|
||||
configured your copy of the Smack developer distribution.
|
||||
|
||||
</ul>
|
||||
|
||||
<p><b>Finished!</b><p>
|
||||
<ul>
|
||||
If you've gotten this far, you've finished setting up the Smack developer
|
||||
distribution. Now, read below to learn about all of the tasks that you can perform
|
||||
with the build tool.
|
||||
</ul>
|
||||
|
||||
<br><br>
|
||||
|
||||
<p><b><a name="tasks"><font color="#0066cc">2.</font> Build Tasks</a></b><p>
|
||||
|
||||
The list of build tasks is below. All build commands should be
|
||||
run from the "build" directory of your Smack distribution.
|
||||
|
||||
<br><br>
|
||||
|
||||
For a list of the commands and a brief description from the command line, type
|
||||
<code>ant -projecthelp</code>. For more complete help, read the documentation below.
|
||||
|
||||
<br><br>
|
||||
|
||||
To execute a build task, type <code>ant [options] targetname</code> where "targetname" is
|
||||
one of the targets listed below:
|
||||
|
||||
<ul>
|
||||
<li><a href="#noparams"><i>Default</i></a>
|
||||
<li><a href="#compile">compile</a>
|
||||
<li><a href="#jar">jar</a>
|
||||
<li><a href="#javadoc">javadoc</a>
|
||||
<li><a href="#clean">clean</a>
|
||||
</ul>
|
||||
<p>
|
||||
Each task is documented with a syntax guide and description. Optional paramaters
|
||||
for each task are enclosed with braces.
|
||||
|
||||
<!--COMPILE-->
|
||||
<p><b><a name="noparams"><i>Default</i></a></b>
|
||||
<ul>
|
||||
<i>Syntax:</i><p>
|
||||
|
||||
</font><code>
|
||||
ant<br>
|
||||
</code><font face="verdana, arial, helvetica" size=2>
|
||||
|
||||
<p><i>Description:</i></p>
|
||||
|
||||
Equivalent of calling "ant <a href="#jar">jar</a>".
|
||||
|
||||
<p>[<a href="#tasks">return to task list</a>]
|
||||
</ul>
|
||||
|
||||
<!--COMPILE-->
|
||||
<p><b><a name="compile">compile</a></b>
|
||||
<ul>
|
||||
<i>Syntax:</i><p>
|
||||
|
||||
</font><code>
|
||||
ant compile <br>
|
||||
</code><font face="verdana, arial, helvetica" size=2>
|
||||
|
||||
<p><i>Description:</i></p>
|
||||
|
||||
Compiles all the Smack source code.
|
||||
The build directory is the "classes" directory under your Smack source distribution.
|
||||
|
||||
<p>[<a href="#tasks">return to task list</a>]
|
||||
</ul>
|
||||
|
||||
|
||||
<!--JAR-->
|
||||
<p><b><a name="jar">jar</a></b>
|
||||
<ul>
|
||||
<i>Syntax:</i><p>
|
||||
|
||||
</font><code>
|
||||
ant jar <br>
|
||||
</code><font face="verdana, arial, helvetica" size=2>
|
||||
|
||||
<p><i>Description:</i></p>
|
||||
|
||||
Bundles the Smack class files into a JAR file (smack.jar)
|
||||
that is suitable for adding
|
||||
into the classpath of an application server.
|
||||
<p>[<a href="#tasks">return to task list</a>]
|
||||
</ul>
|
||||
|
||||
|
||||
<!--JAVADOC-->
|
||||
<p><b><a name="javadoc">javadoc</a></b>
|
||||
<ul>
|
||||
<i>Syntax:</i><p>
|
||||
|
||||
</font><code>
|
||||
ant javadoc <br>
|
||||
</code><font face="verdana, arial, helvetica" size=2>
|
||||
|
||||
<p><i>Description:</i></p>
|
||||
|
||||
JavaDocs all Smack source code in the source directory.
|
||||
|
||||
<p>[<a href="#tasks">return to task list</a>]
|
||||
</ul>
|
||||
|
||||
<!--CLEAN-->
|
||||
<p><b><a name="clean">clean</a></b>
|
||||
<ul>
|
||||
<i>Syntax:</i><p>
|
||||
|
||||
</font><code>
|
||||
ant clean<br>
|
||||
</code><font face="verdana, arial, helvetica" size=2>
|
||||
|
||||
<p><i>Description:</i></p>
|
||||
|
||||
Cleans your Smack distribution directory by deleting compiled class files, the
|
||||
smack.jar file and Javadoc files.<p>
|
||||
|
||||
<p>[<a href="#tasks">return to task list</a>]
|
||||
</ul>
|
||||
|
||||
</body>
|
||||
</html>
|
42
CopyOftrunk/build/ant
Normal file
|
@ -0,0 +1,42 @@
|
|||
#! /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:./ant.jar:./junit.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
|
||||
|
BIN
CopyOftrunk/build/ant-contrib.jar
Normal file
51
CopyOftrunk/build/ant.bat
Normal file
|
@ -0,0 +1,51 @@
|
|||
@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;.\ant.jar;.\junit.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
|
||||
|
BIN
CopyOftrunk/build/ant.jar
Normal file
15
CopyOftrunk/build/build.properties
Normal file
|
@ -0,0 +1,15 @@
|
|||
#
|
||||
# $RCSfile$
|
||||
# $Revision$
|
||||
# $Date$
|
||||
#
|
||||
|
||||
# Test properties. Uncomment these to override default values declared
|
||||
# in the build.xml file.
|
||||
|
||||
# test.host=
|
||||
# test.port=
|
||||
# test.admin.username=
|
||||
# test.admin.password=
|
||||
# test.admin.resource=
|
||||
# test.smack.debug=
|
311
CopyOftrunk/build/build.xml
Normal file
|
@ -0,0 +1,311 @@
|
|||
<?xml version="1.0"?>
|
||||
|
||||
<!-- Smack Build Script ========================================== -->
|
||||
<!-- Jive Software ============================================== -->
|
||||
|
||||
<!--
|
||||
$RCSfile$
|
||||
$Revision$
|
||||
$Date$
|
||||
-->
|
||||
|
||||
<project name="Smack" default="all" basedir="..">
|
||||
|
||||
<!-- TASKDEFS -->
|
||||
<!-- ======================================================================================= -->
|
||||
<!-- ======================================================================================= -->
|
||||
|
||||
<taskdef resource="net/sf/antcontrib/antcontrib.properties">
|
||||
<classpath>
|
||||
<pathelement location="${basedir}/build/ant-contrib.jar"/>
|
||||
</classpath>
|
||||
</taskdef>
|
||||
|
||||
<!-- PROPERTIES -->
|
||||
<!-- ======================================================================================= -->
|
||||
|
||||
<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}" />
|
||||
<property name="javadoc.dest.dir" value="${basedir}/javadoc" />
|
||||
<property name="build.lib.dir" value="${basedir}/build/lib" />
|
||||
<property name="merge.lib.dir" value="${basedir}/build/merge" />
|
||||
|
||||
<property name="version.major" value="1" />
|
||||
<property name="version.minor" value="5" />
|
||||
<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" />
|
||||
<property name="test.admin.username" value="admin" />
|
||||
<property name="test.admin.password" value="admin" />
|
||||
<property name="test.admin.resource" value="Test" />
|
||||
<property name="test.smack.debug" value="false" />
|
||||
|
||||
<!-- PATHS, DEPENDIENCIES, PATTERNS -->
|
||||
<!-- ======================================================================================= -->
|
||||
<!-- ======================================================================================= -->
|
||||
|
||||
<patternset id="test.cases">
|
||||
<include name="org/jivesoftware/smack/**/*Test.java" />
|
||||
<exclude name="org/jivesoftware/smack/**/Messenger*Test.java" />
|
||||
</patternset>
|
||||
|
||||
<patternset id="messenger.test.cases">
|
||||
<include name="org/jivesoftware/smack/**/Messenger*Test.java" />
|
||||
</patternset>
|
||||
|
||||
<!-- TARGETS -->
|
||||
<!-- ======================================================================================= -->
|
||||
|
||||
<!-- all -->
|
||||
<!-- ======================================================================================= -->
|
||||
<target name="all" depends="jar" description="Calls 'jar' target by default">
|
||||
</target>
|
||||
|
||||
<!-- compile -->
|
||||
<!-- ======================================================================================= -->
|
||||
<target name="compile" description="Compiles all source to ${compile.dir}.">
|
||||
<!-- make target dir -->
|
||||
<mkdir dir="${compile.dir}" />
|
||||
<javac
|
||||
destdir="${compile.dir}"
|
||||
includeAntRuntime="no"
|
||||
debug="on"
|
||||
source="1.3"
|
||||
target="1.2"
|
||||
>
|
||||
<src path="${basedir}/source" />
|
||||
<classpath>
|
||||
<fileset dir="${build.lib.dir}">
|
||||
<include name="*.jar"/>
|
||||
</fileset>
|
||||
<fileset dir="${merge.lib.dir}">
|
||||
<include name="*.jar"/>
|
||||
</fileset>
|
||||
</classpath>
|
||||
</javac>
|
||||
</target>
|
||||
|
||||
<!-- compile-test -->
|
||||
<!-- ======================================================================================= -->
|
||||
<target name="compile-test" description="Compiles all source to ${compile.dir}.">
|
||||
<!-- make target dir -->
|
||||
<mkdir dir="${compile.test.dir}" />
|
||||
<javac
|
||||
destdir="${compile.test.dir}"
|
||||
includeAntRuntime="no"
|
||||
debug="on"
|
||||
source="1.3"
|
||||
target="1.2"
|
||||
>
|
||||
<src path="${basedir}/test" />
|
||||
<classpath>
|
||||
<fileset dir="${build.lib.dir}">
|
||||
<include name="*.jar"/>
|
||||
</fileset>
|
||||
<fileset dir="${merge.lib.dir}">
|
||||
<include name="*.jar"/>
|
||||
</fileset>
|
||||
<fileset dir="${basedir}/build">
|
||||
<include name="junit.jar"/>
|
||||
<include name="xmlunit.jar"/>
|
||||
</fileset>
|
||||
<pathelement location="${compile.dir}" />
|
||||
</classpath>
|
||||
</javac>
|
||||
</target>
|
||||
|
||||
<!-- jar -->
|
||||
<!-- ======================================================================================= -->
|
||||
<target name="jar" depends="compile" unless="jar.uptodate" description="Produces smack.jar">
|
||||
|
||||
<copy todir="${compile.dir}/META-INF" file="${basedir}/build/resources/META-INF/smack-config.xml" />
|
||||
<jar destfile="${jar.dest.dir}/smack.jar"
|
||||
basedir="${compile.dir}"
|
||||
includes="org/jivesoftware/smack/**/*.class, **/smack-config.xml"
|
||||
>
|
||||
<zipfileset src="${merge.lib.dir}/xpp.jar"/>
|
||||
</jar>
|
||||
<copy todir="${compile.dir}/META-INF" file="${basedir}/build/resources/META-INF/smack.providers" />
|
||||
<jar destfile="${jar.dest.dir}/smackx.jar"
|
||||
basedir="${compile.dir}"
|
||||
includes="org/jivesoftware/smackx/**/*.class, **/*.providers"
|
||||
excludes="org/jivesoftware/smackx/debugger/*.class"
|
||||
>
|
||||
<manifest>
|
||||
<attribute name="Class-Path" value="smack.jar" />
|
||||
</manifest>
|
||||
</jar>
|
||||
<copy todir="${compile.dir}/images">
|
||||
<fileset dir="${basedir}/build/resources/images">
|
||||
<include name="*.png"/>
|
||||
</fileset>
|
||||
</copy>
|
||||
<jar destfile="${jar.dest.dir}/smackx-debug.jar"
|
||||
basedir="${compile.dir}"
|
||||
includes="org/jivesoftware/smackx/debugger/*.class, **/*.png"
|
||||
>
|
||||
<manifest>
|
||||
<attribute name="Class-Path" value="smack.jar" />
|
||||
</manifest>
|
||||
</jar>
|
||||
<delete file="${compile.dir}/META-INF/smack-config.xml" />
|
||||
<delete file="${compile.dir}/META-INF/smack.providers" />
|
||||
<delete>
|
||||
<fileset dir="${compile.dir}/images">
|
||||
<include name="*.png"/>
|
||||
</fileset>
|
||||
</delete>
|
||||
</target>
|
||||
|
||||
<!-- jar -->
|
||||
<!-- ======================================================================================= -->
|
||||
<target name="jar-test" depends="compile-test" description="Produces jar of test code">
|
||||
<jar destfile="${jar.dest.dir}/smack-test.jar"
|
||||
basedir="${compile.test.dir}"
|
||||
includes="org/jivesoftware/smack/**/*.class"
|
||||
/>
|
||||
</target>
|
||||
|
||||
<!-- javadoc -->
|
||||
<!-- ======================================================================================= -->
|
||||
<target name="javadoc" description="JavaDocs the Smack source code">
|
||||
|
||||
<mkdir dir="${javadoc.dest.dir}" />
|
||||
<javadoc
|
||||
packagenames="org.jivesoftware.smack.*, org.jivesoftware.smackx.*"
|
||||
sourcepath="${basedir}/source"
|
||||
destdir="${javadoc.dest.dir}"
|
||||
author="true"
|
||||
windowtitle="Smack ${version.name} Documentation"
|
||||
overview="${basedir}/source/overview.html"
|
||||
>
|
||||
<classpath>
|
||||
<fileset dir="${build.lib.dir}">
|
||||
<include name="*.jar"/>
|
||||
</fileset>
|
||||
<fileset dir="${merge.lib.dir}">
|
||||
<include name="*.jar"/>
|
||||
</fileset>
|
||||
</classpath>
|
||||
<doctitle><![CDATA[<font face="arial,helvetica">Smack ${version.name}</font>]]></doctitle>
|
||||
<header><![CDATA[<b>Smack</b>]]></header>
|
||||
<bottom><![CDATA[<i>Copyright © 2003 Jive Software. </i>]]></bottom>
|
||||
<link href="http://java.sun.com/j2se/1.3/docs/api/" />
|
||||
<link href="http://java.sun.com/j2ee/sdk_1.2.1/techdocs/api/" />
|
||||
</javadoc>
|
||||
</target>
|
||||
|
||||
|
||||
<!-- test -->
|
||||
<!-- ======================================================================================= -->
|
||||
<target name="test" depends="compile, jar-test" unless="no.test">
|
||||
|
||||
<echo>
|
||||
|
||||
|
||||
**** no.test: ${no.test}
|
||||
|
||||
|
||||
</echo>
|
||||
|
||||
<property name="test.messenger" value="false" />
|
||||
|
||||
<if>
|
||||
<not><equals arg1="test.messenger" arg2="true" /></not>
|
||||
<then>
|
||||
<property name="test.classes" value="test.cases" />
|
||||
</then>
|
||||
</if>
|
||||
|
||||
<junit printsummary="on"
|
||||
fork="false"
|
||||
haltonfailure="false"
|
||||
failureproperty="tests.failed"
|
||||
showoutput="true">
|
||||
|
||||
<sysproperty key="smack.test.host" value="${test.host}" />
|
||||
<sysproperty key="smack.test.port" value="${test.port}" />
|
||||
<sysproperty key="smack.test.admin.username" value="${test.admin.username}" />
|
||||
<sysproperty key="smack.test.admin.password" value="${test.admin.password}" />
|
||||
<sysproperty key="smack.test.admin.resource" value="${test.admin.resource}" />
|
||||
<sysproperty key="smack.debug" value="${test.smack.debug}" />
|
||||
|
||||
<classpath>
|
||||
<fileset dir="${build.lib.dir}">
|
||||
<include name="*.jar"/>
|
||||
</fileset>
|
||||
<fileset dir="${basedir}/build">
|
||||
<include name="xmlunit.jar"/>
|
||||
</fileset>
|
||||
<fileset dir="${merge.lib.dir}">
|
||||
<include name="*.jar"/>
|
||||
</fileset>
|
||||
<fileset dir="${basedir}">
|
||||
<include name="smack-test.jar"/>
|
||||
</fileset>
|
||||
<pathelement location="${compile.dir}" />
|
||||
</classpath>
|
||||
|
||||
<formatter type="brief" usefile="false"/>
|
||||
|
||||
<batchtest>
|
||||
<fileset dir="${basedir}/test">
|
||||
<patternset refid="${test.classes}" />
|
||||
</fileset>
|
||||
</batchtest>
|
||||
</junit>
|
||||
|
||||
<fail if="tests.failed" message="** Tests failed, see test log. **" />
|
||||
</target>
|
||||
|
||||
|
||||
<!-- test -->
|
||||
<!-- ======================================================================================= -->
|
||||
<target name="test.messenger" depends="compile, jar-test" unless="no.test">
|
||||
<antcall target="test" inheritall="true" inheritrefs="true">
|
||||
<param name="test.messenger" value="true" />
|
||||
<param name="test.classes" value="messenger.test.cases" />
|
||||
</antcall>
|
||||
</target>
|
||||
|
||||
|
||||
<!-- release -->
|
||||
<!-- ======================================================================================= -->
|
||||
<target name="release" if="release.exists" depends="release-exists">
|
||||
<antcall target="jar">
|
||||
<param name="no.test" value="true" />
|
||||
</antcall>
|
||||
<antcall target="javadoc">
|
||||
<param name="no.test" value="true" />
|
||||
</antcall>
|
||||
<ant antfile="${basedir}/build/release.xml" />
|
||||
</target>
|
||||
|
||||
|
||||
<!-- release-exists -->
|
||||
<!-- ======================================================================================= -->
|
||||
<target name="release-exists" >
|
||||
<available file="${basedir}/build/release.xml" property="release.exists"/>
|
||||
</target>
|
||||
|
||||
|
||||
<!-- clean -->
|
||||
<!-- ======================================================================================= -->
|
||||
<target name="clean" description="Deletes all generated content.">
|
||||
<delete dir="${javadoc.dest.dir}" />
|
||||
<delete dir="${compile.dir}" />
|
||||
<delete dir="${compile.test.dir}" />
|
||||
<delete file="${basedir}/smack.jar" />
|
||||
<delete file="${basedir}/smackx.jar" />
|
||||
<delete file="${basedir}/smackx-debug.jar" />
|
||||
<delete file="${basedir}/smack-test.jar" />
|
||||
<delete dir="${basedir}/release" />
|
||||
</target>
|
||||
|
||||
</project>
|
BIN
CopyOftrunk/build/junit.jar
Normal file
BIN
CopyOftrunk/build/lib/jcert.jar
Normal file
BIN
CopyOftrunk/build/lib/jnet.jar
Normal file
BIN
CopyOftrunk/build/lib/jsse.jar
Normal file
BIN
CopyOftrunk/build/merge/xpp.jar
Normal file
80
CopyOftrunk/build/projects/Smack.iml
Normal file
|
@ -0,0 +1,80 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module version="4" relativePaths="true" type="JAVA_MODULE">
|
||||
<component name="ModuleRootManager" />
|
||||
<component name="NewModuleRootManager">
|
||||
<output url="file://$MODULE_DIR$/../../classes" />
|
||||
<exclude-output />
|
||||
<exclude-exploded />
|
||||
<content url="file://$MODULE_DIR$/../..">
|
||||
<sourceFolder url="file://$MODULE_DIR$/../../source" isTestSource="false" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/../../test" isTestSource="false" />
|
||||
</content>
|
||||
<orderEntry type="inheritedJdk" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
<orderEntry type="module-library">
|
||||
<library>
|
||||
<CLASSES>
|
||||
<root url="jar://$MODULE_DIR$/../lib/jsse.jar!/" />
|
||||
</CLASSES>
|
||||
<JAVADOC />
|
||||
<SOURCES />
|
||||
</library>
|
||||
</orderEntry>
|
||||
<orderEntry type="module-library" exported="">
|
||||
<library>
|
||||
<CLASSES>
|
||||
<root url="jar://$MODULE_DIR$/../merge/xpp.jar!/" />
|
||||
</CLASSES>
|
||||
<JAVADOC />
|
||||
<SOURCES />
|
||||
</library>
|
||||
</orderEntry>
|
||||
<orderEntry type="module-library">
|
||||
<library>
|
||||
<CLASSES>
|
||||
<root url="jar://$MODULE_DIR$/../lib/jcert.jar!/" />
|
||||
</CLASSES>
|
||||
<JAVADOC />
|
||||
<SOURCES />
|
||||
</library>
|
||||
</orderEntry>
|
||||
<orderEntry type="module-library">
|
||||
<library>
|
||||
<CLASSES>
|
||||
<root url="jar://$MODULE_DIR$/../lib/jnet.jar!/" />
|
||||
</CLASSES>
|
||||
<JAVADOC />
|
||||
<SOURCES />
|
||||
</library>
|
||||
</orderEntry>
|
||||
<orderEntry type="module-library">
|
||||
<library>
|
||||
<CLASSES>
|
||||
<root url="jar://$MODULE_DIR$/../ant.jar!/" />
|
||||
</CLASSES>
|
||||
<JAVADOC />
|
||||
<SOURCES />
|
||||
</library>
|
||||
</orderEntry>
|
||||
<orderEntry type="module-library">
|
||||
<library>
|
||||
<CLASSES>
|
||||
<root url="jar://$MODULE_DIR$/../ant-contrib.jar!/" />
|
||||
</CLASSES>
|
||||
<JAVADOC />
|
||||
<SOURCES />
|
||||
</library>
|
||||
</orderEntry>
|
||||
<orderEntry type="module-library">
|
||||
<library>
|
||||
<CLASSES>
|
||||
<root url="jar://$MODULE_DIR$/../junit.jar!/" />
|
||||
</CLASSES>
|
||||
<JAVADOC />
|
||||
<SOURCES />
|
||||
</library>
|
||||
</orderEntry>
|
||||
<orderEntryProperties />
|
||||
</component>
|
||||
</module>
|
||||
|
217
CopyOftrunk/build/projects/Smack.ipr
Normal file
|
@ -0,0 +1,217 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4" relativePaths="true">
|
||||
<component name="AntConfiguration">
|
||||
<defaultAnt bundledAnt="true" />
|
||||
<buildFile url="file://$PROJECT_DIR$/../build.xml">
|
||||
<additionalClassPath />
|
||||
<antReference projectDefault="true" />
|
||||
<customJdkName value="" />
|
||||
<maximumHeapSize value="128" />
|
||||
<properties />
|
||||
</buildFile>
|
||||
</component>
|
||||
<component name="CodeStyleSettingsManager">
|
||||
<option name="PER_PROJECT_SETTINGS">
|
||||
<value>
|
||||
<option name="LINE_SEPARATOR" value=" " />
|
||||
<option name="ELSE_ON_NEW_LINE" value="true" />
|
||||
<option name="WHILE_ON_NEW_LINE" value="true" />
|
||||
<option name="CATCH_ON_NEW_LINE" value="true" />
|
||||
<option name="FINALLY_ON_NEW_LINE" value="true" />
|
||||
<option name="ALIGN_MULTILINE_PARAMETERS" value="false" />
|
||||
<option name="BLANK_LINES_AFTER_CLASS_HEADER" value="1" />
|
||||
<option name="RIGHT_MARGIN" value="100" />
|
||||
</value>
|
||||
</option>
|
||||
<option name="USE_PER_PROJECT_SETTINGS" value="true" />
|
||||
</component>
|
||||
<component name="CompilerConfiguration">
|
||||
<option name="DEFAULT_COMPILER" value="Javac" />
|
||||
<option name="CLEAR_OUTPUT_DIRECTORY" value="false" />
|
||||
<option name="DEPLOY_AFTER_MAKE" value="0" />
|
||||
<resourceExtensions>
|
||||
<entry name=".+\.(properties|xml|html|dtd|tld)" />
|
||||
<entry name=".+\.(gif|png|jpeg|jpg)" />
|
||||
</resourceExtensions>
|
||||
</component>
|
||||
<component name="DataSourceManagerImpl" />
|
||||
<component name="DependenciesAnalyzeManager">
|
||||
<option name="myForwardDirection" value="false" />
|
||||
</component>
|
||||
<component name="DependencyValidationManager" />
|
||||
<component name="EntryPointsManager">
|
||||
<entry_points />
|
||||
</component>
|
||||
<component name="ExportToHTMLSettings">
|
||||
<option name="PRINT_LINE_NUMBERS" value="false" />
|
||||
<option name="OPEN_IN_BROWSER" value="false" />
|
||||
<option name="OUTPUT_DIRECTORY" />
|
||||
</component>
|
||||
<component name="GUI Designer component loader factory" />
|
||||
<component name="JavacSettings">
|
||||
<option name="DEBUGGING_INFO" value="true" />
|
||||
<option name="GENERATE_NO_WARNINGS" value="false" />
|
||||
<option name="DEPRECATION" value="true" />
|
||||
<option name="ADDITIONAL_OPTIONS_STRING" value="" />
|
||||
<option name="MAXIMUM_HEAP_SIZE" value="128" />
|
||||
</component>
|
||||
<component name="JavadocGenerationManager">
|
||||
<option name="OUTPUT_DIRECTORY" />
|
||||
<option name="OPTION_SCOPE" value="protected" />
|
||||
<option name="OPTION_HIERARCHY" value="true" />
|
||||
<option name="OPTION_NAVIGATOR" value="true" />
|
||||
<option name="OPTION_INDEX" value="true" />
|
||||
<option name="OPTION_SEPARATE_INDEX" value="true" />
|
||||
<option name="OPTION_DOCUMENT_TAG_USE" value="false" />
|
||||
<option name="OPTION_DOCUMENT_TAG_AUTHOR" value="false" />
|
||||
<option name="OPTION_DOCUMENT_TAG_VERSION" value="false" />
|
||||
<option name="OPTION_DOCUMENT_TAG_DEPRECATED" value="true" />
|
||||
<option name="OPTION_DEPRECATED_LIST" value="true" />
|
||||
<option name="OTHER_OPTIONS" value="" />
|
||||
<option name="HEAP_SIZE" />
|
||||
<option name="OPEN_IN_BROWSER" value="true" />
|
||||
</component>
|
||||
<component name="JikesSettings">
|
||||
<option name="JIKES_PATH" value="" />
|
||||
<option name="DEBUGGING_INFO" value="true" />
|
||||
<option name="DEPRECATION" value="true" />
|
||||
<option name="GENERATE_NO_WARNINGS" value="false" />
|
||||
<option name="IS_EMACS_ERRORS_MODE" value="true" />
|
||||
<option name="ADDITIONAL_OPTIONS_STRING" value="" />
|
||||
</component>
|
||||
<component name="Palette2">
|
||||
<group name="Swing">
|
||||
<item class="com.intellij.uiDesigner.HSpacer" tooltip-text="Horizontal Spacer" icon="/com/intellij/uiDesigner/icons/hspacer.png" removable="false">
|
||||
<default-constraints vsize-policy="1" hsize-policy="6" anchor="0" fill="1" />
|
||||
</item>
|
||||
<item class="com.intellij.uiDesigner.VSpacer" tooltip-text="Vertical Spacer" icon="/com/intellij/uiDesigner/icons/vspacer.png" removable="false">
|
||||
<default-constraints vsize-policy="6" hsize-policy="1" anchor="0" fill="2" />
|
||||
</item>
|
||||
<item class="javax.swing.JPanel" icon="/com/intellij/uiDesigner/icons/panel.png" removable="false">
|
||||
<default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3" />
|
||||
</item>
|
||||
<item class="javax.swing.JScrollPane" icon="/com/intellij/uiDesigner/icons/scrollPane.png" removable="false">
|
||||
<default-constraints vsize-policy="7" hsize-policy="7" anchor="0" fill="3" />
|
||||
</item>
|
||||
<item class="javax.swing.JButton" icon="/com/intellij/uiDesigner/icons/button.png" removable="false">
|
||||
<default-constraints vsize-policy="0" hsize-policy="3" anchor="0" fill="1" />
|
||||
<initial-values>
|
||||
<property name="text" value="Button" />
|
||||
</initial-values>
|
||||
</item>
|
||||
<item class="javax.swing.JRadioButton" icon="/com/intellij/uiDesigner/icons/radioButton.png" removable="false">
|
||||
<default-constraints vsize-policy="0" hsize-policy="3" anchor="8" fill="0" />
|
||||
<initial-values>
|
||||
<property name="text" value="RadioButton" />
|
||||
</initial-values>
|
||||
</item>
|
||||
<item class="javax.swing.JCheckBox" icon="/com/intellij/uiDesigner/icons/checkBox.png" removable="false">
|
||||
<default-constraints vsize-policy="0" hsize-policy="3" anchor="8" fill="0" />
|
||||
<initial-values>
|
||||
<property name="text" value="CheckBox" />
|
||||
</initial-values>
|
||||
</item>
|
||||
<item class="javax.swing.JLabel" icon="/com/intellij/uiDesigner/icons/label.png" removable="false">
|
||||
<default-constraints vsize-policy="0" hsize-policy="0" anchor="8" fill="0" />
|
||||
<initial-values>
|
||||
<property name="text" value="Label" />
|
||||
</initial-values>
|
||||
</item>
|
||||
<item class="javax.swing.JTextField" icon="/com/intellij/uiDesigner/icons/textField.png" removable="false">
|
||||
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
|
||||
<preferred-size width="150" height="-1" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JPasswordField" icon="/com/intellij/uiDesigner/icons/passwordField.png" removable="false">
|
||||
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
|
||||
<preferred-size width="150" height="-1" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JFormattedTextField" icon="/com/intellij/uiDesigner/icons/formattedTextField.png" removable="false">
|
||||
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
|
||||
<preferred-size width="150" height="-1" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JTextArea" icon="/com/intellij/uiDesigner/icons/textArea.png" removable="false">
|
||||
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
|
||||
<preferred-size width="150" height="50" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JTextPane" icon="/com/intellij/uiDesigner/icons/textPane.png" removable="false">
|
||||
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
|
||||
<preferred-size width="150" height="50" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JEditorPane" icon="/com/intellij/uiDesigner/icons/editorPane.png" removable="false">
|
||||
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
|
||||
<preferred-size width="150" height="50" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JComboBox" icon="/com/intellij/uiDesigner/icons/comboBox.png" removable="false">
|
||||
<default-constraints vsize-policy="0" hsize-policy="2" anchor="8" fill="1" />
|
||||
</item>
|
||||
<item class="javax.swing.JTable" icon="/com/intellij/uiDesigner/icons/table.png" removable="false">
|
||||
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
|
||||
<preferred-size width="150" height="50" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JList" icon="/com/intellij/uiDesigner/icons/list.png" removable="false">
|
||||
<default-constraints vsize-policy="6" hsize-policy="2" anchor="0" fill="3">
|
||||
<preferred-size width="150" height="50" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JTree" icon="/com/intellij/uiDesigner/icons/tree.png" removable="false">
|
||||
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
|
||||
<preferred-size width="150" height="50" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JTabbedPane" icon="/com/intellij/uiDesigner/icons/tabbedPane.png" removable="false">
|
||||
<default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3">
|
||||
<preferred-size width="200" height="200" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JSplitPane" icon="/com/intellij/uiDesigner/icons/splitPane.png" removable="false">
|
||||
<default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3">
|
||||
<preferred-size width="200" height="200" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JSpinner" icon="/com/intellij/uiDesigner/icons/spinner.png" removable="false">
|
||||
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1" />
|
||||
</item>
|
||||
<item class="javax.swing.JSlider" icon="/com/intellij/uiDesigner/icons/slider.png" removable="false">
|
||||
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1" />
|
||||
</item>
|
||||
</group>
|
||||
</component>
|
||||
<component name="ProjectModuleManager">
|
||||
<modules>
|
||||
<module fileurl="file://$PROJECT_DIR$/Smack.iml" filepath="$PROJECT_DIR$/Smack.iml" />
|
||||
</modules>
|
||||
</component>
|
||||
<component name="ProjectRootManager" version="2" assert-keyword="false" jdk-15="false" project-jdk-name="JDK 1.4.2" />
|
||||
<component name="RmicSettings">
|
||||
<option name="IS_EANABLED" value="false" />
|
||||
<option name="DEBUGGING_INFO" value="true" />
|
||||
<option name="GENERATE_NO_WARNINGS" value="false" />
|
||||
<option name="GENERATE_IIOP_STUBS" value="false" />
|
||||
<option name="ADDITIONAL_OPTIONS_STRING" value="" />
|
||||
</component>
|
||||
<component name="libraryTable">
|
||||
<library name="Smack">
|
||||
<CLASSES>
|
||||
<root url="jar://$PROJECT_DIR$/../lib/jcert.jar!/" />
|
||||
<root url="jar://$PROJECT_DIR$/../lib/jnet.jar!/" />
|
||||
<root url="jar://$PROJECT_DIR$/../lib/jsse.jar!/" />
|
||||
<root url="jar://$PROJECT_DIR$/../merge/xpp.jar!/" />
|
||||
</CLASSES>
|
||||
<JAVADOC />
|
||||
<SOURCES />
|
||||
</library>
|
||||
</component>
|
||||
<component name="uidesigner-configuration">
|
||||
<option name="INSTRUMENT_CLASSES" value="true" />
|
||||
<option name="COPY_FORMS_RUNTIME_TO_OUTPUT" value="true" />
|
||||
</component>
|
||||
<UsedPathMacros />
|
||||
</project>
|
||||
|
188
CopyOftrunk/build/release.xml
Normal file
|
@ -0,0 +1,188 @@
|
|||
<?xml version="1.0"?>
|
||||
|
||||
<!-- Smack Build Script ========================================== -->
|
||||
<!-- Jive Software ============================================== -->
|
||||
|
||||
<!--
|
||||
$RCSfile$
|
||||
$Revision$
|
||||
$Date$
|
||||
-->
|
||||
|
||||
<project name="Smack Release Script" default="all" basedir="..">
|
||||
|
||||
<!-- Include Ant Optional Tasks -->
|
||||
<taskdef resource="net/sf/antcontrib/antcontrib.properties">
|
||||
<classpath>
|
||||
<pathelement location="${basedir}/build/ant-contrib.jar"/>
|
||||
</classpath>
|
||||
</taskdef>
|
||||
|
||||
<!-- PROPERTIES -->
|
||||
<!-- ======================================================================================= -->
|
||||
|
||||
<!-- TARGETS -->
|
||||
<!-- ======================================================================================= -->
|
||||
|
||||
<!-- all -->
|
||||
<!-- ======================================================================================= -->
|
||||
<target name="all">
|
||||
<!-- create release properties -->
|
||||
<if>
|
||||
<equals arg1="${dailybuild}" arg2="true" />
|
||||
<then>
|
||||
<tstamp>
|
||||
<format property="build.date" pattern="yyyy-MM-dd" locale="en"/>
|
||||
</tstamp>
|
||||
<property name="release.name" value="smack-${build.date}" />
|
||||
<property name="release-dev.name" value="smack-dev-${build.date}" />
|
||||
</then>
|
||||
<else>
|
||||
<property name="release.name" value="smack-${version.name}" />
|
||||
<property name="release-dev.name" value="smack-dev-${version.name}" />
|
||||
</else>
|
||||
</if>
|
||||
<property name="release.dir" value="${basedir}/release/${release.name}" />
|
||||
<property name="release-dev.dir" value="${basedir}/release/${release-dev.name}" />
|
||||
<!-- create release dirs -->
|
||||
<mkdir dir="${release.dir}" />
|
||||
<mkdir dir="${release-dev.dir}" />
|
||||
<!-- Copy smack.jar -->
|
||||
<copy todir="${release.dir}">
|
||||
<fileset dir="${jar.dest.dir}" includes="smack.jar" />
|
||||
<fileset dir="${jar.dest.dir}" includes="smackx.jar" />
|
||||
<fileset dir="${jar.dest.dir}" includes="smackx-debug.jar" />
|
||||
</copy>
|
||||
<copy todir="${release-dev.dir}">
|
||||
<fileset dir="${jar.dest.dir}" includes="smack.jar" />
|
||||
<fileset dir="${jar.dest.dir}" includes="smackx.jar" />
|
||||
<fileset dir="${jar.dest.dir}" includes="smackx-debug.jar" />
|
||||
</copy>
|
||||
<!-- Copy build dir -->
|
||||
<copy todir="${release-dev.dir}/build">
|
||||
<fileset dir="${basedir}/build">
|
||||
<include name="ant*" />
|
||||
<include name="junit.jar" />
|
||||
<include name="build.xml" />
|
||||
<include name="README.html" />
|
||||
<include name="lib/*.jar" />
|
||||
<include name="merge/*.jar" />
|
||||
</fileset>
|
||||
</copy>
|
||||
<!-- Copy Javadocs -->
|
||||
<copy todir="${release.dir}/javadoc">
|
||||
<fileset dir="${basedir}/javadoc" includes="**/*.*" />
|
||||
</copy>
|
||||
<copy todir="${release-dev.dir}/javadoc">
|
||||
<fileset dir="${basedir}/javadoc" includes="**/*.*" />
|
||||
</copy>
|
||||
<!-- Copy documentation -->
|
||||
<copy todir="${release.dir}/documentation">
|
||||
<fileset dir="${basedir}/documentation" includes="**/*.*" />
|
||||
</copy>
|
||||
<copy todir="${release-dev.dir}/documentation">
|
||||
<fileset dir="${basedir}/documentation" includes="**/*.*" />
|
||||
</copy>
|
||||
<!-- Copy source -->
|
||||
<copy todir="${release-dev.dir}/source">
|
||||
<fileset dir="${basedir}/source" includes="**/*.java" />
|
||||
<fileset dir="${basedir}/source" includes="**/*.html" />
|
||||
</copy>
|
||||
<copy todir="${release-dev.dir}/test">
|
||||
<fileset dir="${basedir}/test" includes="**/*.java" />
|
||||
</copy>
|
||||
<!-- Copy resources -->
|
||||
<copy todir="${release-dev.dir}/build/resources">
|
||||
<fileset dir="${basedir}/build/resources" includes="META-INF/smack.providers" />
|
||||
<fileset dir="${basedir}/build/resources" includes="META-INF/smack-config.xml" />
|
||||
</copy>
|
||||
<copy todir="${release-dev.dir}/build/resources/images">
|
||||
<fileset dir="${basedir}/build/resources/images">
|
||||
<include name="*.png"/>
|
||||
</fileset>
|
||||
</copy>
|
||||
<!-- Copy readme.html and changelog.html -->
|
||||
<copy todir="${release.dir}">
|
||||
<fileset dir="${basedir}/build/resources/releasedocs" includes="*.html" />
|
||||
</copy>
|
||||
<copy todir="${release-dev.dir}">
|
||||
<fileset dir="${basedir}/build/resources/releasedocs" includes="*.html" />
|
||||
</copy>
|
||||
<!-- Package -->
|
||||
<if>
|
||||
<equals arg1="${dailybuild}" arg2="true" />
|
||||
<then>
|
||||
<zip destfile="${basedir}/release/${release-dev.name}.zip"
|
||||
basedir="${release-dev.dir}/.."
|
||||
includes="${release-dev.name}/**/*.*"
|
||||
/>
|
||||
<tar destfile="${basedir}/release/${release-dev.name}.tar.gz"
|
||||
basedir="${release-dev.dir}/.."
|
||||
includes="${release-dev.name}/**/*.*"
|
||||
compression="gzip"
|
||||
/>
|
||||
</then>
|
||||
<else>
|
||||
<zip destfile="${basedir}/release/${release.name}.zip"
|
||||
basedir="${release.dir}/.."
|
||||
includes="${release.name}/**/*.*"
|
||||
/>
|
||||
<tar destfile="${basedir}/release/${release.name}.tar.gz"
|
||||
basedir="${release.dir}/.."
|
||||
includes="${release.name}/**/*.*"
|
||||
compression="gzip"
|
||||
/>
|
||||
<zip destfile="${basedir}/release/${release-dev.name}.zip"
|
||||
basedir="${release-dev.dir}/.."
|
||||
includes="${release-dev.name}/**/*.*"
|
||||
/>
|
||||
<tar destfile="${basedir}/release/${release-dev.name}.tar.gz"
|
||||
basedir="${release-dev.dir}/.."
|
||||
includes="${release-dev.name}/**/*.*"
|
||||
compression="gzip"
|
||||
/>
|
||||
</else>
|
||||
</if>
|
||||
|
||||
<echo>
|
||||
-----------------------------------------------
|
||||
Release made, testing Ant targets of release...
|
||||
-----------------------------------------------
|
||||
</echo>
|
||||
|
||||
<!-- call the release tester -->
|
||||
<antcall target="test" />
|
||||
</target>
|
||||
|
||||
<!-- test -->
|
||||
<!-- ======================================================================================= -->
|
||||
<target name="test">
|
||||
<property name="testdir" value="${release-dev.dir}/.test" />
|
||||
|
||||
<!-- copy the build to a temp dir so we can run sanity tests -->
|
||||
<mkdir dir="${testdir}" />
|
||||
<copy todir="${testdir}">
|
||||
<fileset dir="${release-dev.dir}">
|
||||
<exclude name=".test/**/*.*" />
|
||||
</fileset>
|
||||
</copy>
|
||||
|
||||
<!-- run sanity tests -->
|
||||
<ant dir="${testdir}" antfile="build/build.xml" target="jar" inheritAll="false">
|
||||
<property name="no.test" value="true" />
|
||||
</ant>
|
||||
<ant dir="${testdir}" antfile="build/build.xml" target="javadoc" inheritAll="false">
|
||||
<property name="no.test" value="true" />
|
||||
</ant>
|
||||
<ant dir="${testdir}" antfile="build/build.xml" target="clean" inheritAll="false">
|
||||
<property name="no.test" value="true" />
|
||||
</ant>
|
||||
|
||||
<echo>
|
||||
----------------------------
|
||||
...release tests pass, done.
|
||||
----------------------------
|
||||
</echo>
|
||||
</target>
|
||||
|
||||
</project>
|
18
CopyOftrunk/build/resources/META-INF/smack-config.xml
Normal file
|
@ -0,0 +1,18 @@
|
|||
<?xml version="1.0"?>
|
||||
<!-- Smack configuration file. -->
|
||||
<smack>
|
||||
|
||||
<!-- Classes that will be loaded when Smack starts -->
|
||||
<startupClasses>
|
||||
<className>org.jivesoftware.smackx.ServiceDiscoveryManager</className>
|
||||
<className>org.jivesoftware.smackx.XHTMLManager</className>
|
||||
<className>org.jivesoftware.smackx.muc.MultiUserChat</className>
|
||||
</startupClasses>
|
||||
|
||||
<!-- Paket reply timeout in milliseconds -->
|
||||
<packetReplyTimeout>5000</packetReplyTimeout>
|
||||
|
||||
<!-- Keep-alive interval in milleseconds -->
|
||||
<keepAliveInterval>30000</keepAliveInterval>
|
||||
|
||||
</smack>
|
124
CopyOftrunk/build/resources/META-INF/smack.providers
Normal file
|
@ -0,0 +1,124 @@
|
|||
<?xml version="1.0"?>
|
||||
<!-- Providers file for default Smack extensions -->
|
||||
<smackProviders>
|
||||
|
||||
<!-- Private Data Storage -->
|
||||
<iqProvider>
|
||||
<elementName>query</elementName>
|
||||
<namespace>jabber:iq:private</namespace>
|
||||
<className>org.jivesoftware.smackx.PrivateDataManager$PrivateDataIQProvider</className>
|
||||
</iqProvider>
|
||||
|
||||
<!-- Time -->
|
||||
<iqProvider>
|
||||
<elementName>query</elementName>
|
||||
<namespace>jabber:iq:time</namespace>
|
||||
<className>org.jivesoftware.smackx.packet.Time</className>
|
||||
</iqProvider>
|
||||
|
||||
<!-- Roster Exchange -->
|
||||
<extensionProvider>
|
||||
<elementName>x</elementName>
|
||||
<namespace>jabber:x:roster</namespace>
|
||||
<className>org.jivesoftware.smackx.provider.RosterExchangeProvider</className>
|
||||
</extensionProvider>
|
||||
|
||||
<!-- Message Events -->
|
||||
<extensionProvider>
|
||||
<elementName>x</elementName>
|
||||
<namespace>jabber:x:event</namespace>
|
||||
<className>org.jivesoftware.smackx.provider.MessageEventProvider</className>
|
||||
</extensionProvider>
|
||||
|
||||
<!-- XHTML -->
|
||||
<extensionProvider>
|
||||
<elementName>html</elementName>
|
||||
<namespace>http://jabber.org/protocol/xhtml-im</namespace>
|
||||
<className>org.jivesoftware.smackx.provider.XHTMLExtensionProvider</className>
|
||||
</extensionProvider>
|
||||
|
||||
<!-- Group Chat Invitations -->
|
||||
<extensionProvider>
|
||||
<elementName>x</elementName>
|
||||
<namespace>jabber:x:conference</namespace>
|
||||
<className>org.jivesoftware.smackx.GroupChatInvitation$Provider</className>
|
||||
</extensionProvider>
|
||||
|
||||
<!-- Service Discovery # Items -->
|
||||
<iqProvider>
|
||||
<elementName>query</elementName>
|
||||
<namespace>http://jabber.org/protocol/disco#items</namespace>
|
||||
<className>org.jivesoftware.smackx.provider.DiscoverItemsProvider</className>
|
||||
</iqProvider>
|
||||
|
||||
<!-- Service Discovery # Info -->
|
||||
<iqProvider>
|
||||
<elementName>query</elementName>
|
||||
<namespace>http://jabber.org/protocol/disco#info</namespace>
|
||||
<className>org.jivesoftware.smackx.provider.DiscoverInfoProvider</className>
|
||||
</iqProvider>
|
||||
|
||||
<!-- Data Forms-->
|
||||
<extensionProvider>
|
||||
<elementName>x</elementName>
|
||||
<namespace>jabber:x:data</namespace>
|
||||
<className>org.jivesoftware.smackx.provider.DataFormProvider</className>
|
||||
</extensionProvider>
|
||||
|
||||
<!-- MUC User -->
|
||||
<extensionProvider>
|
||||
<elementName>x</elementName>
|
||||
<namespace>http://jabber.org/protocol/muc#user</namespace>
|
||||
<className>org.jivesoftware.smackx.provider.MUCUserProvider</className>
|
||||
</extensionProvider>
|
||||
|
||||
<!-- MUC Admin -->
|
||||
<iqProvider>
|
||||
<elementName>query</elementName>
|
||||
<namespace>http://jabber.org/protocol/muc#admin</namespace>
|
||||
<className>org.jivesoftware.smackx.provider.MUCAdminProvider</className>
|
||||
</iqProvider>
|
||||
|
||||
<!-- MUC Owner -->
|
||||
<iqProvider>
|
||||
<elementName>query</elementName>
|
||||
<namespace>http://jabber.org/protocol/muc#owner</namespace>
|
||||
<className>org.jivesoftware.smackx.provider.MUCOwnerProvider</className>
|
||||
</iqProvider>
|
||||
|
||||
<!-- Delayed Delivery -->
|
||||
<extensionProvider>
|
||||
<elementName>x</elementName>
|
||||
<namespace>jabber:x:delay</namespace>
|
||||
<className>org.jivesoftware.smackx.provider.DelayInformationProvider</className>
|
||||
</extensionProvider>
|
||||
|
||||
<!-- Version -->
|
||||
<iqProvider>
|
||||
<elementName>query</elementName>
|
||||
<namespace>jabber:iq:version</namespace>
|
||||
<className>org.jivesoftware.smackx.packet.Version</className>
|
||||
</iqProvider>
|
||||
|
||||
<!-- VCard -->
|
||||
<iqProvider>
|
||||
<elementName>vCard</elementName>
|
||||
<namespace>vcard-temp</namespace>
|
||||
<className>org.jivesoftware.smackx.provider.VCardProvider</className>
|
||||
</iqProvider>
|
||||
|
||||
<!-- Offline Message Requests -->
|
||||
<iqProvider>
|
||||
<elementName>offline</elementName>
|
||||
<namespace>http://jabber.org/protocol/offline</namespace>
|
||||
<className>org.jivesoftware.smackx.packet.OfflineMessageRequest$Provider</className>
|
||||
</iqProvider>
|
||||
|
||||
<!-- Offline Message Indicator -->
|
||||
<extensionProvider>
|
||||
<elementName>offline</elementName>
|
||||
<namespace>http://jabber.org/protocol/offline</namespace>
|
||||
<className>org.jivesoftware.smackx.packet.OfflineMessageInfo$Provider</className>
|
||||
</extensionProvider>
|
||||
|
||||
</smackProviders>
|
BIN
CopyOftrunk/build/resources/images/message.png
Normal file
After Width: | Height: | Size: 759 B |
BIN
CopyOftrunk/build/resources/images/nav_left_blue.png
Normal file
After Width: | Height: | Size: 793 B |
BIN
CopyOftrunk/build/resources/images/nav_right_red.png
Normal file
After Width: | Height: | Size: 774 B |
BIN
CopyOftrunk/build/resources/images/photo_portrait.png
Normal file
After Width: | Height: | Size: 702 B |
BIN
CopyOftrunk/build/resources/images/question_and_answer.png
Normal file
After Width: | Height: | Size: 783 B |
BIN
CopyOftrunk/build/resources/images/trafficlight_green.png
Normal file
After Width: | Height: | Size: 633 B |
BIN
CopyOftrunk/build/resources/images/trafficlight_off.png
Normal file
After Width: | Height: | Size: 626 B |
BIN
CopyOftrunk/build/resources/images/trafficlight_red.png
Normal file
After Width: | Height: | Size: 616 B |
BIN
CopyOftrunk/build/resources/images/unknown.png
Normal file
After Width: | Height: | Size: 723 B |
BIN
CopyOftrunk/build/resources/images/warning.png
Normal file
After Width: | Height: | Size: 719 B |
120
CopyOftrunk/build/resources/releasedocs/README.html
Normal file
|
@ -0,0 +1,120 @@
|
|||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<title>Smack Readme</title>
|
||||
<style type="text/css">
|
||||
BODY {
|
||||
font-size : 100%;
|
||||
}
|
||||
BODY, TD, TH {
|
||||
font-family : tahoma, verdana, arial, helvetica, sans-serif;
|
||||
font-size : 0.8em;
|
||||
}
|
||||
A:hover {
|
||||
text-decoration : none;
|
||||
}
|
||||
.pageheader {
|
||||
font-family : arial, helvetica, sans-serif;
|
||||
font-size : 14pt;
|
||||
font-weight: bold;
|
||||
}
|
||||
.header {
|
||||
font-family : tahoma, arial, helvetica, sans-serif;
|
||||
font-size : 1.4em;
|
||||
font-weight: bold;
|
||||
border-bottom : 1px #ccc solid;
|
||||
padding-bottom : 2px;
|
||||
}
|
||||
.subheader {
|
||||
font-weight: bold;
|
||||
color: #600;
|
||||
}
|
||||
TT {
|
||||
font-family : courier new;
|
||||
font-weight : bold;
|
||||
color : #060;
|
||||
}
|
||||
PRE {
|
||||
font-family : courier new;
|
||||
font-size : 100%;
|
||||
}
|
||||
.footer {
|
||||
font-size : 0.8em;
|
||||
color : #666;
|
||||
text-align : center;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<div class="header">
|
||||
Smack Readme
|
||||
</div>
|
||||
|
||||
<p>
|
||||
<table boder=0>
|
||||
<tr>
|
||||
<td>version:</td>
|
||||
<td><b>1.5.1</b></td>
|
||||
</tr><tr>
|
||||
<td>released:</td>
|
||||
<td><b>August 12, 2005</b></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<p>
|
||||
Thank you for downloading Smack!
|
||||
<p>
|
||||
|
||||
Start off by viewing the <a href="documentation/index.html">documentation</a>
|
||||
that can be found in the "documentation" directory included with this distribution.
|
||||
<p>
|
||||
Further information can be found on the <a href="http://www.jivesoftware.org/smack">
|
||||
Smack website</a>. If you need help using or would like to make contributions or
|
||||
fixes to the code, please visit the
|
||||
<a href="http://www.jivesoftware.org/forums/forum.jspa?forumID=39">online forum</a>.
|
||||
|
||||
<p><b>About the Distribution</b><p>
|
||||
|
||||
The <tt>smack.jar</tt> file in the main distribution folder is the only binary file
|
||||
required for embedding XMPP functionality into client applications. The optional
|
||||
<tt>smackx.jar</tt> contains the <a href="documentation/extensions/index.html">Smack extensions</a>
|
||||
while <tt>smackx-debug.jar</tt> contains an enhanced debugger.<p>
|
||||
|
||||
If you downloaded the developer release, the full source of the library is included in
|
||||
the <tt>source</tt> directory and can be compiled using the build scripts found in the
|
||||
<tt>build</tt> directory (please see the README file in the build directory for further details).
|
||||
|
||||
<p><b>Changelog and Upgrading</b><p>
|
||||
|
||||
View the <a href="changelog.html">changelog</a> for a list of changes since the
|
||||
last release.
|
||||
|
||||
<p><b>License Agreements</b><p>
|
||||
<ul>
|
||||
<li>Use of thie Smack source code is governed by the Apache License:
|
||||
<pre>
|
||||
Copyright 2002-2005 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.
|
||||
</pre></li>
|
||||
|
||||
<li>Smack contains icons and images licensed from INCORS GmbH. You are not licensed
|
||||
to use these icons outside of Smack.</li>
|
||||
|
||||
<li>Third-party source code is licensed as noted in their source files.
|
||||
|
||||
</ul>
|
||||
</body>
|
||||
</html>
|
296
CopyOftrunk/build/resources/releasedocs/changelog.html
Normal file
|
@ -0,0 +1,296 @@
|
|||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<title>Smack Changelog</title>
|
||||
<style type="text/css">
|
||||
BODY {
|
||||
font-size : 100%;
|
||||
}
|
||||
BODY, TD, TH {
|
||||
font-family : tahoma, verdana, arial, helvetica, sans-serif;
|
||||
font-size : 0.8em;
|
||||
}
|
||||
A:hover {
|
||||
text-decoration : none;
|
||||
}
|
||||
.pageheader {
|
||||
font-family : arial, helvetica, sans-serif;
|
||||
font-size : 14pt;
|
||||
font-weight: bold;
|
||||
}
|
||||
.header {
|
||||
font-family : tahoma, arial, helvetica, sans-serif;
|
||||
font-size : 1.4em;
|
||||
font-weight: bold;
|
||||
border-bottom : 1px #ccc solid;
|
||||
padding-bottom : 2px;
|
||||
}
|
||||
.bugNum {
|
||||
color: #666;
|
||||
}
|
||||
.subheader {
|
||||
font-weight: bold;
|
||||
color: #600;
|
||||
}
|
||||
TT {
|
||||
font-family : courier new;
|
||||
font-weight : bold;
|
||||
color : #060;
|
||||
}
|
||||
PRE {
|
||||
font-family : courier new;
|
||||
font-size : 100%;
|
||||
}
|
||||
.footer {
|
||||
font-size : 0.8em;
|
||||
color : #666;
|
||||
text-align : center;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<div class="header">
|
||||
Smack Changelog
|
||||
</div>
|
||||
|
||||
<p>
|
||||
<b>1.5.1</b> -- August 12, 2005
|
||||
<p>
|
||||
<ul>
|
||||
<li>[<a href='http://www.jivesoftware.org/issues/browse/SMACK-60'>SMACK-60</a>] - Presence priorities out of range were crashing the connection.</li>
|
||||
<li>[<a href='http://www.jivesoftware.org/issues/browse/SMACK-63'>SMACK-63</a>] - Sometimes XMPPConnection#getRoster() was taking too long.</li>
|
||||
<li>[<a href='http://www.jivesoftware.org/issues/browse/SMACK-66'>SMACK-66</a>] - Wrong attribute name and date format when requesting history since a given date.</li>
|
||||
<li>[<a href='http://www.jivesoftware.org/issues/browse/SMACK-70'>SMACK-70</a>] - IQ Time now uses a 0-23 hour format.</li>
|
||||
|
||||
<li>[<a href='http://www.jivesoftware.org/issues/browse/SMACK-25'>SMACK-25</a>] - Added support for JEP-13: Flexible Offline Message Retrieval.</li>
|
||||
<li>[<a href='http://www.jivesoftware.org/issues/browse/SMACK-58'>SMACK-58</a>] - Added support for JEP-54: vCards. Thanks to Kirill Maximov.</li>
|
||||
<li>[<a href='http://www.jivesoftware.org/issues/browse/SMACK-53'>SMACK-53</a>] - Added support for JEP-92: Software Version.</li>
|
||||
<li>[<a href='http://www.jivesoftware.org/issues/browse/SMACK-61'>SMACK-61</a>] - Added new debugger that prints on the stdout.</li>
|
||||
<li>[<a href='http://www.jivesoftware.org/issues/browse/SMACK-71'>SMACK-71</a>] - Created new FromMatchesFilter that checks for exact matching.</li>
|
||||
|
||||
|
||||
<li>[<a href='http://www.jivesoftware.org/issues/browse/SMACK-52'>SMACK-52</a>] - Added constructor to XMPPConnection for better connection control.</li>
|
||||
<li>[<a href='http://www.jivesoftware.org/issues/browse/SMACK-56'>SMACK-56</a>] - Reported data can now hold more than one value.</li>
|
||||
<li>[<a href='http://www.jivesoftware.org/issues/browse/SMACK-57'>SMACK-57</a>] - RoomInfo now includes the room JID.</li>
|
||||
<li>[<a href='http://www.jivesoftware.org/issues/browse/SMACK-59'>SMACK-59</a>] - Date format for delayed dates is configurable.</li>
|
||||
<li>[<a href='http://www.jivesoftware.org/issues/browse/SMACK-62'>SMACK-62</a>] - The username and password fields are now optional in Registration.</li>
|
||||
<li>[<a href='http://www.jivesoftware.org/issues/browse/SMACK-67'>SMACK-67</a>] - Parsing of delayed dates was improved to be smarter.</li>
|
||||
<li>[<a href='http://www.jivesoftware.org/issues/browse/SMACK-68'>SMACK-68</a>] - PacketParserUtils#parseProperties is now public.</li>
|
||||
<li>[<a href='http://www.jivesoftware.org/issues/browse/SMACK-69'>SMACK-69</a>] - Adding or removing entries from a group can now throw an XMPPException.</li>
|
||||
</ul>
|
||||
|
||||
<p>
|
||||
<b>1.5.0</b> -- March 30, 2005
|
||||
<p>
|
||||
<ul>
|
||||
<li>[<a href='http://www.jivesoftware.org/issues/browse/SMACK-7'>SMACK-7</a>] - Fixed issue that caused Smack to fail when X11 was not installed on Unix.</li>
|
||||
<li>[<a href='http://www.jivesoftware.org/issues/browse/SMACK-32'>SMACK-32</a>] - Getting the system classloader could raise a security exception.</li>
|
||||
<li>[<a href='http://www.jivesoftware.org/issues/browse/SMACK-33'>SMACK-33</a>] - MUCOwner.Item now includes the "role" attribute.</li>
|
||||
<li>[<a href='http://www.jivesoftware.org/issues/browse/SMACK-37'>SMACK-37</a>] - Fixing timing issue that could make logins slow.</li>
|
||||
<li>[<a href='http://www.jivesoftware.org/issues/browse/SMACK-42'>SMACK-42</a>] - The pretty print of the EnhancedDebugger was not working well with Java 1.5.</li>
|
||||
<li>[<a href='http://www.jivesoftware.org/issues/browse/SMACK-43'>SMACK-43</a>] - Occupant#getNick() answers null when the info is available.</li>
|
||||
<li>[<a href='http://www.jivesoftware.org/issues/browse/SMACK-46'>SMACK-46</a>] - Support for cancelling notifications in message events was missing.</li>
|
||||
<li>[<a href='http://www.jivesoftware.org/issues/browse/SMACK-48'>SMACK-48</a>] - PacketListeners were not being removed from the connection when the chat finishes.</li>
|
||||
<li>[<a href='http://www.jivesoftware.org/issues/browse/SMACK-50'>SMACK-50</a>] - XML representation of Presence packets did not include error element.</li>
|
||||
|
||||
<li>[<a href='http://www.jivesoftware.org/issues/browse/SMACK-4'>SMACK-4</a>] - Implemented room management in batch mode.</li>
|
||||
<li>[<a href='http://www.jivesoftware.org/issues/browse/SMACK-11'>SMACK-11</a>] - Implemented discovery of extended information of MUC rooms.</li>
|
||||
<li>[<a href='http://www.jivesoftware.org/issues/browse/SMACK-13'>SMACK-13</a>] - Implemented discovery of MUC rooms hosted by a service.</li>
|
||||
<li>[<a href='http://www.jivesoftware.org/issues/browse/SMACK-38'>SMACK-38</a>] - Notify when an occupant joins or leaves a group chat room.</li>
|
||||
<li>[<a href='http://www.jivesoftware.org/issues/browse/SMACK-39'>SMACK-39</a>] - Added support for discovering MUC services.</li>
|
||||
<li>[<a href='http://www.jivesoftware.org/issues/browse/SMACK-41'>SMACK-41</a>] - Added support for JEP-91: Delayed Delivery.</li>
|
||||
|
||||
<li>[<a href='http://www.jivesoftware.org/issues/browse/SMACK-49'>SMACK-49</a>] - Modified Smack to use latest minimal version of XPP.</li>
|
||||
|
||||
<li>[<a href='http://www.jivesoftware.org/issues/browse/SMACK-40'>SMACK-40</a>] - Packet extensions can now be sent when inviting a user to a room.</li>
|
||||
<li>[<a href='http://www.jivesoftware.org/issues/browse/SMACK-44'>SMACK-44</a>] - PacketReader can now parse errors that follow XMPP 1.0.</li>
|
||||
<li>[<a href='http://www.jivesoftware.org/issues/browse/SMACK-45'>SMACK-45</a>] - Sorted the list of providers in the EnhancedDebugger window.</li>
|
||||
<li>[<a href='http://www.jivesoftware.org/issues/browse/SMACK-47'>SMACK-47</a>] - Added a public API for parsing Messages and Presences.</li>
|
||||
</ul>
|
||||
|
||||
<p>
|
||||
<b>1.4.1</b> - November 15, 2004
|
||||
<p>
|
||||
<ul>
|
||||
<li><font color="#777777">(SMACK-21)</font> The reader and listener threads in PacketReader are now stopped if an error occurs while starting up PacketReader. Thanks to Steve Reichert.
|
||||
<li><font color="#777777">(SMACK-22)</font> XMPP addresses are now treated as case insensitive.
|
||||
<li><font color="#777777">(SMACK-3)</font> Fixed possible NullPointerException when parsing invalid XHTML text.
|
||||
<li><font color="#777777">(SMACK-8)</font> Answer an item-not-found error when Smack receives a service discovery for information and node is not null.
|
||||
<li><font color="#777777">(SMACK-17)</font> An incorrect namespace was being used for granting and revoking admin/owner privileges.
|
||||
<li><font color="#777777">(SMACK-19)</font> The roster should be able to hold any valid JID format. Thanks to Adam Olsen.
|
||||
<li><font color="#777777">(SMACK-20</font> Parsing MUCOwner packets could freeze the client.
|
||||
<li><font color="#777777">(SMACK-18)</font> Implemented JEP-128. A service discovery for information can now include a dataform or any possible packet extension.
|
||||
<li><font color="#777777">(SMACK-15)</font> Allow registration entries with blank values.
|
||||
<li><font color="#777777">(SMACK-16)</font> Added <tt>String getAccountAttribute(String)</tt> method to AccountManager class.
|
||||
<li><font color="#777777">(SMACK-23)</font> Connection listeners can now be removed while notifying that the connection is being closed. Fixes ConcurrentModificationException triggered on close.
|
||||
</ul>
|
||||
|
||||
<p>
|
||||
<b>1.4.0</b> - August 10, 2004
|
||||
<p>
|
||||
<ul>
|
||||
<li><font color="#777777">(SMACK-99)</font> Added support for Multi User Chat (JEP 45) as a Smack Extension.
|
||||
<li><font color="#777777">(SMACK-125)</font> Added support for Data Forms (JEP 04) as a Smack Extension.
|
||||
<li><font color="#777777">(SMACK-143)</font> Fixed memory leak problem by closing ObjectOutputStream while writing out Object properties.
|
||||
<li><font color="#777777">(SMACK-145)</font> Fixed memory leak problem by cancelling unused collectors.
|
||||
<li><font color="#777777">(SMACK-138)</font> Fixed error parsing properties of Messages.
|
||||
<li><font color="#777777">(SMACK-135)</font> Invalid characters in the TO and FROM fields of any packet were escaped in order to
|
||||
prevent the connection from closing. Thanks to Ian Sollars.
|
||||
<li><font color="#777777">(SMACK-140)</font> Added new constructor to XMPPConnection <tt>XMPPConnection(String host, int port,
|
||||
SocketFactory socketFactory)</tt> that allows a user to pass in the SocketFactory to use.
|
||||
<li><font color="#777777">(SMACK-131)</font> Remove cached presence info when user was deleted from roster.
|
||||
<li><font color="#777777">(SMACK-123)</font> TimerTask was removed to make Smack JDK 1.2 compatible again.
|
||||
<li><font color="#777777">(SMACK-130)</font> Use notifyAll() instead of notify() in PacketWriter.
|
||||
<li><font color="#777777">(SMACK-137)</font> Fixed security exception with unsigned applets using try/catch around System.getProperty.
|
||||
<li><font color="#777777">(SMACK-127)</font> IQ packets can now have extensions.
|
||||
<li><font color="#777777">(SMACK-128)</font> Registration can now include a registration data form.
|
||||
<li><font color="#777777">(SMACK-136)</font> Keep-alive process should flush stream.
|
||||
<li><font color="#777777">(SMACK-121)</font> Delay of keep-alive is now configurable.
|
||||
<li><font color="#777777">(SMACK-149)</font> A disco info request directed to a Smack client didn't answer the client's identity.
|
||||
<li><font color="#777777">(SMACK-150)</font> Added <tt>canPublishItems(String entityID)</tt> method to ServiceDiscoveryManager in
|
||||
order to discover whether a server supports publishing of items or not.
|
||||
<li><font color="#777777">(SMACK-133)</font> Node attribute was missing in DiscoverInfo and DiscoverItems XML representations.
|
||||
<li><font color="#777777">(SMACK-134)</font> Added <tt>setNodeInformationProvider(String node, NodeInformationProvider listener)</tt>
|
||||
method to ServiceDiscoveryManager and created new <tt>NodeInformationProvider</tt> interface in order to provide information about
|
||||
nodes defined in the client.
|
||||
<li><font color="#777777">(SMACK-139)</font> Added new menu option to the enhanced debugger in order to close all the tabs of which
|
||||
their connections are not active anymore.
|
||||
<li><font color="#777777">(SMACK-124)</font> Don't set L&F in debuggers.
|
||||
<li><font color="#777777">(SMACK-122)</font> Added documentation about the new enhanced debugger.
|
||||
<li><font color="#777777">(SMACK-142)</font> Base class for existing test cases was created.
|
||||
</ul>
|
||||
|
||||
<p>
|
||||
<b>1.3.0</b> - March 11, 2004
|
||||
<p>
|
||||
<ul>
|
||||
<li><font color="#777777">(SMACK-103, SMACK-105)</font> Fixed bugs with error packets (sending and receiving).
|
||||
<li><font color="#777777">(SMACK-109)</font> Renaming RosterGroups fails.
|
||||
<li><font color="#777777">(SMACK-91)</font> Add support for Service Discovery (JEP 30) as a Smack Extension.
|
||||
<li><font color="#777777">(SMACK-94)</font> Host name as reported by server should be used in the Connection object.
|
||||
<li><font color="#777777">(SMACK-97)</font> SUBSCRIPTION_* constants are misspelled in the Roster class.
|
||||
<li><font color="#777777">(SMACK-107)</font> Allow packet reply timeout to be set.
|
||||
<li><font color="#777777">(SMACK-41)</font> Unrecognized IQs should generate a "not implemented" error.
|
||||
<li><font color="#777777">(SMACK-116)</font> Roster entries are not being removed from the group immediately when deleted.
|
||||
<li><font color="#777777">(SMACK-100)</font> Incoming packets should only have ID's if they are set.
|
||||
<li><font color="#777777">(SMACK-104)</font> Fixed bug parsing server information.
|
||||
<li><font color="#777777">(SMACK-112)</font> Add a mechanism to set the roster's subscription mode before login.
|
||||
<li><font color="#777777">(SMACK-117)</font> PacketWriter never terminates daemon threads.
|
||||
<li><font color="#777777">(SMACK-113)</font> Once a debugger gets closed it still collects packets - OutOfMemory problem.
|
||||
<li><font color="#777777">(SMACK-102)</font> Add methods to get all packet providers.
|
||||
<li><font color="#777777">(SMACK-95)</font> Add group chat invitation support as a Smack Extension.
|
||||
<li><font color="#777777">(SMACK-93)</font> New debug window with many enhancements.
|
||||
<li><font color="#777777">(SMACK-110)</font> Added keep-alives so the TCP-IP timeouts wouldn't break connections to a server.
|
||||
<li><font color="#777777">(SMACK-101)</font> Add version number information to API.
|
||||
<li><font color="#777777">(SMACK-96)</font> Make AndFilter and OrFilter chainable.
|
||||
<li><font color="#777777">(SMACK-108)</font> Handle multiple presences when a user is connected from different resources.
|
||||
<li><font color="#777777">(SMACK-111)</font> Add listener support for new connections.
|
||||
<li><font color="#777777">(SMACK-92)</font> Add support for "Discovering Support for XHTML-IM".
|
||||
<li><font color="#777777">(SMACK-106)</font> Chat objects no longer have to depend on a threadID (this is settable).
|
||||
<li><font color="#777777">(SMACK-120)</font> Chat.getChatID() is now Chat.getThreadID().
|
||||
</ul>
|
||||
|
||||
<p>
|
||||
<b>1.2.1</b> - September 28, 2003
|
||||
<p>
|
||||
<ul>
|
||||
<li><font color="#777777">(SMACK-79)</font> Added XHTML message support as a Smack extension, which allows sending
|
||||
richly formatted messages.
|
||||
<li><font color="#777777">(SMACK-88)</font> Fixed bug with parsing registation packets that contain extra data.
|
||||
<li><font color="#777777">(SMACK-90)</font> Added support for getting registration instructions.
|
||||
<li><font color="#777777">(SMACK-85)</font> Exceptions in the PacketWriter now correctly generates a connection
|
||||
error event.
|
||||
<li><font color="#777777">(SMACK-84)</font> Added <tt>isSecureConnection()</tt> method to XMPPConnection class.
|
||||
<li><font color="#777777">(SMACK-86)</font> Added <tt>isJoined()</tt> method to GroupChat class.
|
||||
<li><font color="#777777">(SMACK-87, SMACK-82)</font> Added the following methods related to rosters:
|
||||
<tt>Roster.contains(String user)</tt>, <tt>Roster.getEntry(String user)</tt>,
|
||||
<tt>RosterGroup.getEntry(String user)</tt>, <tt>Roster.removeEntry(RosterEntry entry)</tt>.
|
||||
<li><font color="#777777">(SMACK-73)</font> Fixed bugs handling roster remove and update operations.
|
||||
</ul>
|
||||
|
||||
<p>
|
||||
<b>1.2.0</b> - August 29, 2003
|
||||
<p>
|
||||
<ul>
|
||||
<li><font color="red"><b>!</b></font> A package structure and documentation has been added for Smack extensions,
|
||||
which cover extensions to the XMPP protocol. The initial extensions are
|
||||
for message events (JEP 22), roster item exchange (JEP 93), entity
|
||||
time (JEP 90), and private data storage (JEP 49).
|
||||
<li><font color="red"><b>!</b></font> The smack.providers file is now loaded from META-INF/smack.providers
|
||||
rather than WEB-INF/smack.providers. This location makes much more sense
|
||||
for generic JAR files, but may break existing provider implementations
|
||||
until the provider file is moved.
|
||||
<li>Fixed IQ error sub-packets.
|
||||
<li>The default packet extension handler didn't deal with empty
|
||||
elements well and also had a bug with attribute handling.
|
||||
<li>Added a ConnectionListener feature which allows clients
|
||||
to be notified of normally closed connections, and connections
|
||||
closed due to errors.
|
||||
<li>Fixed bug where the roster list could become corrupted after
|
||||
moving a user back and forther between groups.
|
||||
<li>Fixed bug where in some cases presence packets were not getting
|
||||
tracked by the Roster class correctly.
|
||||
<li>RosterListener has a new notification method that is called every time
|
||||
the presence of a user in the roster is updated.
|
||||
<li>Added Roster.getEntries() method to return all entries in the roster.
|
||||
<li>Added RosterGroup.contains(String) method to check to see if an XMPP
|
||||
address is part of the group.
|
||||
<li>Minor fixes to Javadocs.
|
||||
<li>Content can be copied and cleared from the debug window using
|
||||
a pop-up menu.
|
||||
<li>The Chat constructor that took an existing chatID as an argument
|
||||
did not propertly initialize support for message listeners.
|
||||
<li>Added support for anonymous logins.
|
||||
<li>IQ is now an abstract class.
|
||||
<li>Fixed bug where XHTML messgaes could cause parsing errors.
|
||||
</ul>
|
||||
|
||||
<p>
|
||||
<b>1.1.1</b> - June 25, 2003
|
||||
<p>
|
||||
<ul>
|
||||
<li>Setting Object packet properties was broken.
|
||||
<li>Added getRoom() method to GroupChat.
|
||||
</ul>
|
||||
|
||||
<p>
|
||||
<b>1.1.0</b> - June 19, 2003
|
||||
<p>
|
||||
<ul>
|
||||
<li>New system to handle custom IQ packets and custom packet extensions through
|
||||
the new provider sub-package.
|
||||
<li>Added packet filters for packet extensions.
|
||||
<li>Added additional options for responding to subscription requests.
|
||||
<li>Added method to retrieve the roster item count from roster packets.
|
||||
<li>Added ability to set the ItemStatus on a roster packet.
|
||||
<li>Added remove option to roster packet.
|
||||
<li>Various documentation fixes/improvements.
|
||||
<li>Fixed NullPointer exception on the setName method of the RosterEntry class.
|
||||
<li>Groupchat class was listening for wrong message types -- fixed.
|
||||
<li>Changed properties element name to "properties" instead of "x". <b>Note:</b> this will
|
||||
break compatability between earlier versions if they are trying to send packet
|
||||
properties back and forth. However, we thought it was best to make this change now.
|
||||
<li>Turning on debugging via a system property wasn't working.
|
||||
<li>Fixed spelling error in Roster class method name.
|
||||
<li>Fixed stream not being closed properly.
|
||||
<li>The "to contains" and "from contains" filters now ignore case.
|
||||
</ul>
|
||||
|
||||
<p>
|
||||
<b>1.0.1</b> - April 30, 2003
|
||||
<p>
|
||||
<ul>
|
||||
<li>Fixed bug that caused applets using Smack to crash with a security exception.
|
||||
</ul>
|
||||
|
||||
<p>
|
||||
<b>1.0.0</b> - April 25, 2003
|
||||
<p>
|
||||
<ul>
|
||||
<li>Initial official release.
|
||||
</ul>
|
||||
|
||||
</body>
|
||||
</html>
|
116
CopyOftrunk/documentation/debugging.html
Normal file
|
@ -0,0 +1,116 @@
|
|||
<html>
|
||||
<head>
|
||||
<title>Smack: Debugging - Jive Software</title>
|
||||
<link rel="stylesheet" type="text/css" href="style.css" />
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<div class="header">
|
||||
Debugging with Smack
|
||||
</div>
|
||||
|
||||
<div class="nav">
|
||||
« <a href="index.html">Table of Contents</a>
|
||||
</div>
|
||||
|
||||
<p>
|
||||
Smack includes two built-in debugging consoles that will let you track all XML traffic between
|
||||
the client and server. A <a href="#lite">lite debugger</a> which is part of the <tt>smack.jar</tt>
|
||||
and an <a href="#enhanced">enhanced debugger</a> contained in <tt>smackx-debug.jar</tt>.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Debugging mode can be enabled in two different ways:
|
||||
</p>
|
||||
|
||||
<ol>
|
||||
<li>Add the following line of code <b>before</b> creating new connections:<p>
|
||||
<tt>XMPPConnection.DEBUG_ENABLED = true;</tt><p>
|
||||
|
||||
<li>Set the Java system property <tt>smack.debugEnabled</tt> to true. The
|
||||
system property can be set on the command line such as:<p>
|
||||
<tt>java -Dsmack.debugEnabled=true SomeApp </tt>
|
||||
</ol>
|
||||
|
||||
<p>
|
||||
If you wish to explicitly disable debug mode in your application, including using the command-line parameter,
|
||||
add the following line to your application before opening new connections:
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<tt>XMPPConnection.DEBUG_ENABLED = false;</tt>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Smack uses the following logic to decide the debugger console to use:
|
||||
</p>
|
||||
|
||||
<ol>
|
||||
<li>It will first try use the debugger class specified in the Java system property
|
||||
<tt>smack.debuggerClass</tt>. If you need to develop your own debugger,
|
||||
implement the <tt>SmackDebugger</tt> interface and then set the system property
|
||||
on the command line such as:<p>
|
||||
<tt>java -Dsmack.debuggerClass=my.company.com.MyDebugger SomeApp </tt><p>
|
||||
|
||||
<li>If step 1 fails then Smack will try to use the enhanced debugger. The
|
||||
file <tt>smackx-debug.jar</tt> contains the enhanced debugger. Therefore you will need
|
||||
to place the jar file in the classpath. For situations where space is an issue you
|
||||
may want to only deploy <tt>smack.jar</tt> in which case the enhanced debugger won't be
|
||||
available.<p>
|
||||
|
||||
<li>The last option if the previous two steps fail is to use the lite debugger. The lite
|
||||
debugger is a very good option for situations where you need to have low memory footprint.
|
||||
</ol>
|
||||
|
||||
<p class="subheader">
|
||||
<a name="enhanced">Enhanced Debugger</a>
|
||||
</p>
|
||||
|
||||
<img src="images/enhanceddebugger.png" width="479" height="400" alt="Full Debug Window" border="0" align="right">
|
||||
|
||||
When debugging mode is enabled, a debug window will appear containing tabs for each new created connection.
|
||||
The window will contain the following information:
|
||||
|
||||
<ul>
|
||||
<li>Connection tabs -- each tab shows debugging information related to the connection.
|
||||
<li>Smack info tab -- shows information about Smack (e.g. Smack version, installed components, etc.).
|
||||
</ul>
|
||||
|
||||
The connection tab will contain the following information:
|
||||
<ul>
|
||||
<li>All Packets -- shows sent and received packets information parsed by Smack.
|
||||
<li>Raw Sent Packets -- raw XML traffic generated by Smack and sent to the server.
|
||||
<li>Raw Received Packets -- raw XML traffic sent by the server to the client.
|
||||
<li>Ad-hoc message -- allows to send ad-hoc packets of any type.
|
||||
<li>Information -- shows connection state and statistics.
|
||||
</ul>
|
||||
|
||||
<br clear="right">
|
||||
|
||||
<p class="subheader">
|
||||
<a name="lite">Lite Debugger</a>
|
||||
</p>
|
||||
|
||||
<img src="images/debugwindow.gif" width="359" height="399" alt="Lite Debug Window" border="0" align="right">
|
||||
|
||||
When debugging mode is enabled, a debug window will appear when each new connection is created.
|
||||
The window will contain the following information:
|
||||
|
||||
<ul>
|
||||
<li>Client Traffic (red text) -- raw XML traffic generated by Smack and sent to the server.
|
||||
<li>Server Traffic (blue text) -- raw XML traffic sent by the server to the client.
|
||||
<li>Interpreted Packets (green text) -- shows XML packets from the server as parsed by Smack.
|
||||
</ul>
|
||||
|
||||
Right click on any of the panes to bring up a menu with the choices to copy of the contents
|
||||
to the system clipboard or to clear the contents of the pane.
|
||||
|
||||
<br clear="all" /><br><br>
|
||||
|
||||
<div class="footer">
|
||||
Copyright © Jive Software 2002-2005
|
||||
</div>
|
||||
|
||||
</body>
|
||||
</html>
|
137
CopyOftrunk/documentation/extensions/dataforms.html
Normal file
|
@ -0,0 +1,137 @@
|
|||
<html>
|
||||
<head>
|
||||
<title>Data Forms</title>
|
||||
<link rel="stylesheet" type="text/css" href="style.css" />
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<div class="header">Data Forms</div><p>
|
||||
|
||||
Allows to exchange structured data between users and applications for common
|
||||
tasks such as registration and searching using Forms.
|
||||
|
||||
<ul>
|
||||
<li><a href="#gather">Create a Form to fill out</a></li>
|
||||
<li><a href="#fillout">Answer a Form</a></li>
|
||||
</ul>
|
||||
<b>JEP related:</b> <a href="http://www.jabber.org/jeps/jep-0004.html">JEP-4</a>
|
||||
|
||||
<hr>
|
||||
|
||||
<div class="subheader"><a name="gather">Create a Form to fill out</a></div><p>
|
||||
|
||||
<b>Description</b><p>
|
||||
|
||||
An XMPP entity may need to gather data from another XMPP entity. Therefore, the data-gathering
|
||||
entity will need to create a new Form, specify the fields that will conform the Form and finally
|
||||
send the Form to the data-providing entity.</p>
|
||||
|
||||
<b>Usage</b><p>
|
||||
|
||||
In order to create a Form to fill out use the <i><b>Form</b></i>'s constructor passing the constant
|
||||
<b>Form.TYPE_FORM</b> as the parameter. The next step is to create the form fields and add them to
|
||||
the form. In order to create and customize a <i><b>FormField</b></i> use the <i><b>FormField</b></i>'s
|
||||
constructor specifying the variable name of the field as the parameter. Then use <b>setType(String type)</b>
|
||||
to set the field's type (e.g. FormField.TYPE_HIDDEN, FormField.TYPE_TEXT_SINGLE). Once we have the
|
||||
<i><b>Form</b></i> instance and the <i><b>FormFields</b></i> the last step is to send <b>addField(FormField field)</b>
|
||||
for each field that we want to add to the form.</p><p>
|
||||
|
||||
Once the form to fill out is finished we will want to send it in a message. Send <b>getDataFormToSend()</b> to
|
||||
the form and add the answer as an extension to the message to send.</p>
|
||||
|
||||
<b>Examples</b><p>
|
||||
|
||||
In this example we can see how to create and send a form to fill out: <br>
|
||||
<blockquote>
|
||||
<pre> <font color="#3f7f5f">// Create a new form to gather data</font>
|
||||
Form formToSend = new Form(Form.TYPE_FORM);
|
||||
formToSend.setInstructions(
|
||||
"Fill out this form to report your case.\nThe case will be created automatically.");
|
||||
formToSend.setTitle("Case configurations");
|
||||
<font color="#3f7f5f">// Add a hidden variable to the form</font>
|
||||
FormField field = new FormField("hidden_var");
|
||||
field.setType(FormField.TYPE_HIDDEN);
|
||||
field.addValue("Some value for the hidden variable");
|
||||
formToSend.addField(field);
|
||||
<font color="#3f7f5f">// Add a fixed variable to the form</font>
|
||||
field = new FormField();
|
||||
field.addValue("Section 1: Case description");
|
||||
formToSend.addField(field);
|
||||
<font color="#3f7f5f">// Add a text-single variable to the form</font>
|
||||
field = new FormField("name");
|
||||
field.setLabel("Enter a name for the case");
|
||||
field.setType(FormField.TYPE_TEXT_SINGLE);
|
||||
formToSend.addField(field);
|
||||
<font color="#3f7f5f">// Add a text-multi variable to the form</font>
|
||||
field = new FormField("description");
|
||||
field.setLabel("Enter a description");
|
||||
field.setType(FormField.TYPE_TEXT_MULTI);
|
||||
formToSend.addField(field);
|
||||
|
||||
<font color="#3f7f5f">// Create a chat with "user2@host.com"</font>
|
||||
Chat chat = conn1.createChat("user2@host.com" );
|
||||
|
||||
Message msg = chat.createMessage();
|
||||
msg.setBody("To enter a case please fill out this form and send it back to me");
|
||||
<font color="#3f7f5f">// Add the form to fill out to the message to send</font>
|
||||
msg.addExtension(formToSend.getDataFormToSend());
|
||||
|
||||
<font color="#3f7f5f">// Send the message with the form to fill out</font>
|
||||
chat.sendMessage(msg);
|
||||
</pre>
|
||||
</blockquote>
|
||||
|
||||
<hr>
|
||||
|
||||
<div class="subheader"><a name="fillout">Answer a Form</a></div><p>
|
||||
|
||||
<b>Description</b><p>
|
||||
|
||||
Under many situations an XMPP entity could receive a form to fill out. For example, some hosts
|
||||
may require to fill out a form in order to register new users. Smack lets the data-providing entity
|
||||
to complete the form in an easy way and send it back to the data-gathering entity.</p>
|
||||
|
||||
<b>Usage</b><p>
|
||||
|
||||
The form to fill out contains useful information that could be used for rendering the form. But it
|
||||
cannot be used to actually complete it. Instead it's necessary to create a new form based on the original
|
||||
form whose purpose is to hold all the answers.</p><p>
|
||||
|
||||
In order to create a new <i><b>Form</b></i> to complete based on the original <i><b>Form</b></i> just send
|
||||
<b>createAnswerForm()</b> to the original <i><b>Form</b></i>. Once you have a valid form that could be actually
|
||||
completed all you have to do is send <b>setAnswer(String variable, String value)</b> to the form where variable
|
||||
is the variable of the <i><b>FormField</b></i> that you want to answer and value is the String representation
|
||||
of the answer. If the answer consist of several values you could then use <b>setAnswer(String variable, List values)</b>
|
||||
where values is a List of Strings.</p><p>
|
||||
|
||||
Once the form has been completed we will want to send it back in a message. Send <b>getDataFormToSend()</b> to
|
||||
the form and add the answer as an extension to the message to send back.</p>
|
||||
|
||||
<b>Examples</b><p>
|
||||
|
||||
In this example we can see how to retrieve a form to fill out, complete the form and send it back: <br>
|
||||
<blockquote>
|
||||
<pre> <font color="#3f7f5f">// Get the message with the form to fill out</font>
|
||||
Message msg2 = chat2.nextMessage();
|
||||
<font color="#3f7f5f">// Retrieve the form to fill out from the message</font>
|
||||
Form formToRespond = Form.getFormFrom(msg2);
|
||||
<font color="#3f7f5f">// Obtain the form to send with the replies</font>
|
||||
Form completedForm = formToRespond.createAnswerForm();
|
||||
<font color="#3f7f5f">// Add the answers to the form</font>
|
||||
completedForm.setAnswer("name", "Credit card number invalid");
|
||||
completedForm.setAnswer(
|
||||
"description",
|
||||
"The ATM says that my credit card number is invalid. What's going on?");
|
||||
|
||||
msg2 = chat2.createMessage();
|
||||
msg2.setBody("To enter a case please fill out this form and send it back to me");
|
||||
<font color="#3f7f5f">// Add the completed form to the message to send back</font>
|
||||
msg2.addExtension(completedForm.getDataFormToSend());
|
||||
<font color="#3f7f5f">// Send the message with the completed form</font>
|
||||
chat2.sendMessage(msg2);
|
||||
</pre>
|
||||
</blockquote>
|
||||
</body>
|
||||
|
||||
</html>
|
236
CopyOftrunk/documentation/extensions/disco.html
Normal file
|
@ -0,0 +1,236 @@
|
|||
<html>
|
||||
<head>
|
||||
<title>Service Discovery</title>
|
||||
<link rel="stylesheet" type="text/css" href="style.css" />
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<div class="header">Service Discovery</div><p>
|
||||
|
||||
The service discovery extension allows to discover items and information about XMPP
|
||||
entities. Follow these links to learn how to use this extension.
|
||||
|
||||
<ul>
|
||||
<li><a href="#discoregister">Manage XMPP entity features</a></li>
|
||||
<li><a href="#disconodeinfo">Provide node information</a></li>
|
||||
<li><a href="#discoitems">Discover items associated with an XMPP entity</a></li>
|
||||
<li><a href="#discoinfo">Discover information about an XMPP entity</a></li>
|
||||
<li><a href="#discopublish">Publish publicly available items</a></li>
|
||||
</ul>
|
||||
<b>JEP related:</b> <a href="http://www.jabber.org/jeps/jep-0030.html">JEP-30</a>
|
||||
|
||||
<hr>
|
||||
|
||||
<div class="subheader"><a name="discoregister">Manage XMPP entity features</a></div><p>
|
||||
|
||||
<b>Description</b><p>
|
||||
|
||||
Any XMPP entity may receive a discovery request and must answer with its associated items or
|
||||
information. Therefore, your Smack client may receive a discovery request that must respond
|
||||
to (i.e., if your client supports XHTML-IM). This extension automatically responds to a
|
||||
discovery request with the information that you previously configured.</p>
|
||||
|
||||
<b>Usage</b><p>
|
||||
|
||||
In order to configure the supported features by your client you should first obtain the
|
||||
ServiceDiscoveryManager associated with your XMPPConnection. To get your ServiceDiscoveryManager
|
||||
send <b>getInstanceFor(connection)</b> to the class <i><b>ServiceDiscoveryManager</b></i> where
|
||||
connection is your XMPPConnection.<br></p>
|
||||
|
||||
<p>Once you have your ServiceDiscoveryManager you will be able to manage the supported features. To
|
||||
register a new feature send <b>addFeature(feature)</b> to your <i><b>ServiceDiscoveryManager</b></i>
|
||||
where feature is a String that represents the supported feature. To remove a supported feature send
|
||||
<b>removeFeature(feature)</b> to your <i><b>ServiceDiscoveryManager</b></i> where feature is a
|
||||
String that represents the feature to remove.</p>
|
||||
|
||||
<b>Examples</b><p>
|
||||
|
||||
In this example we can see how to add and remove supported features: <br>
|
||||
<blockquote>
|
||||
<pre> <font color="#3f7f5f">// Obtain the ServiceDiscoveryManager associated with my XMPPConnection</font>
|
||||
ServiceDiscoveryManager discoManager = ServiceDiscoveryManager.getInstanceFor(connection);
|
||||
|
||||
<font color="#3f7f5f">// Register that a new feature is supported by this XMPP entity</font>
|
||||
discoManager.addFeature(namespace1);
|
||||
|
||||
<font color="#3f7f5f">// Remove the specified feature from the supported features by this XMPP entity</font>
|
||||
discoManager.removeFeature(namespace2);
|
||||
</pre>
|
||||
</blockquote>
|
||||
|
||||
<hr>
|
||||
|
||||
<div class="subheader"><a name="disconodeinfo">Provide node information</a></div><p>
|
||||
|
||||
<b>Description</b><p>
|
||||
|
||||
Your XMPP entity may receive a discovery request for items non-addressable as a JID such as
|
||||
the MUC rooms where you are joined. In order to answer the correct information it is necessary
|
||||
to configure the information providers associated to the items/nodes within the Smack client.</p>
|
||||
|
||||
<b>Usage</b><p>
|
||||
|
||||
In order to configure the associated nodes within the Smack client you will need to create a
|
||||
NodeInformationProvider and register it with the <i><b>ServiceDiscoveryManager</b></i>. To get
|
||||
your ServiceDiscoveryManager send <b>getInstanceFor(connection)</b> to the class <i><b>ServiceDiscoveryManager</b></i>
|
||||
where connection is your XMPPConnection.<br></p>
|
||||
|
||||
<p>Once you have your ServiceDiscoveryManager you will be able to register information providers
|
||||
for the XMPP entity's nodes. To register a new node information provider send <b>setNodeInformationProvider(String node, NodeInformationProvider listener)</b>
|
||||
to your <i><b>ServiceDiscoveryManager</b></i> where node is the item non-addressable as a JID and
|
||||
listener is the <i><b>NodeInformationProvider</b></i> to register. To unregister a <i><b>NodeInformationProvider</b></i>
|
||||
send <b>removeNodeInformationProvider(String node)</b> to your <i><b>ServiceDiscoveryManager</b></i> where
|
||||
node is the item non-addressable as a JID whose information provider we want to unregister.</p>
|
||||
|
||||
<b>Examples</b><p>
|
||||
|
||||
In this example we can see how to register a NodeInformationProvider with a ServiceDiscoveryManager that will provide
|
||||
information concerning a node named "http://jabber.org/protocol/muc#rooms": <br>
|
||||
<blockquote>
|
||||
<pre> <font color="#3f7f5f">// Set the NodeInformationProvider that will provide information about the</font>
|
||||
<font color="#3f7f5f">// joined rooms whenever a disco request is received </font>
|
||||
ServiceDiscoveryManager.getInstanceFor(connection).setNodeInformationProvider(
|
||||
<font color="#0000FF">"http://jabber.org/protocol/muc#rooms"</font>,
|
||||
new NodeInformationProvider() {
|
||||
public Iterator getNodeItems() {
|
||||
ArrayList answer = new ArrayList();
|
||||
Iterator rooms = MultiUserChat.getJoinedRooms(connection);
|
||||
while (rooms.hasNext()) {
|
||||
answer.add(new DiscoverItems.Item((String)rooms.next()));
|
||||
}
|
||||
return answer.iterator();
|
||||
}
|
||||
});
|
||||
</pre>
|
||||
</blockquote>
|
||||
|
||||
<hr>
|
||||
|
||||
<div class="subheader"><a name="discoitems">Discover items associated with an XMPP entity</a></div><p>
|
||||
|
||||
<b>Description</b><p>
|
||||
|
||||
In order to obtain information about a specific item you have to first discover the items available
|
||||
in an XMPP entity.</p>
|
||||
|
||||
<b>Usage</b><p>
|
||||
|
||||
<p>Once you have your ServiceDiscoveryManager you will be able to discover items associated with
|
||||
an XMPP entity. To discover the items of a given XMPP entity send <b>discoverItems(entityID)</b>
|
||||
to your <i><b>ServiceDiscoveryManager</b></i> where entityID is the ID of the entity. The message
|
||||
<b>discoverItems(entityID)</b> will answer an instance of <i><b>DiscoverItems</b></i> that contains
|
||||
the discovered items.</p>
|
||||
|
||||
<b>Examples</b><p>
|
||||
|
||||
In this example we can see how to discover the items associated with an online catalog service: <br>
|
||||
<blockquote>
|
||||
<pre> <font color="#3f7f5f">// Obtain the ServiceDiscoveryManager associated with my XMPPConnection</font>
|
||||
ServiceDiscoveryManager discoManager = ServiceDiscoveryManager.getInstanceFor(connection);
|
||||
|
||||
<font color="#3f7f5f">// Get the items of a given XMPP entity</font>
|
||||
<font color="#3f7f5f">// This example gets the items associated with online catalog service</font>
|
||||
DiscoverItems discoItems = discoManager.discoverItems("plays.shakespeare.lit");
|
||||
|
||||
<font color="#3f7f5f">// Get the discovered items of the queried XMPP entity</font>
|
||||
Iterator it = discoItems.getItems();
|
||||
<font color="#3f7f5f">// Display the items of the remote XMPP entity</font>
|
||||
while (it.hasNext()) {
|
||||
DiscoverItems.Item item = (DiscoverItems.Item) it.next();
|
||||
System.out.println(item.getEntityID());
|
||||
System.out.println(item.getNode());
|
||||
System.out.println(item.getName());
|
||||
}
|
||||
</pre>
|
||||
</blockquote>
|
||||
|
||||
<hr>
|
||||
|
||||
<div class="subheader"><a name="discoinfo">Discover information about an XMPP entity</a></div><p>
|
||||
|
||||
<b>Description</b><p>
|
||||
|
||||
Once you have discovered the entity ID and name of an item, you may want to find out more
|
||||
about the item. The information desired generally is of two kinds: 1) The item's identity
|
||||
and 2) The features offered by the item.</p>
|
||||
|
||||
<p>This information helps you determine what actions are possible with regard to this
|
||||
item (registration, search, join, etc.) as well as specific feature types of interest, if
|
||||
any (e.g., for the purpose of feature negotiation).</p>
|
||||
|
||||
<b>Usage</b><p>
|
||||
|
||||
<p>Once you have your ServiceDiscoveryManager you will be able to discover information associated with
|
||||
an XMPP entity. To discover the information of a given XMPP entity send <b>discoverInfo(entityID)</b>
|
||||
to your <i><b>ServiceDiscoveryManager</b></i> where entityID is the ID of the entity. The message
|
||||
<b>discoverInfo(entityID)</b> will answer an instance of <i><b>DiscoverInfo</b></i> that contains
|
||||
the discovered information.</p>
|
||||
|
||||
<b>Examples</b><p>
|
||||
|
||||
In this example we can see how to discover the information of a conference room: <br>
|
||||
<blockquote>
|
||||
<pre> <font color="#3f7f5f">// Obtain the ServiceDiscoveryManager associated with my XMPPConnection</font>
|
||||
ServiceDiscoveryManager discoManager = ServiceDiscoveryManager.getInstanceFor(connection);
|
||||
|
||||
<font color="#3f7f5f">// Get the information of a given XMPP entity</font>
|
||||
<font color="#3f7f5f">// This example gets the information of a conference room</font>
|
||||
DiscoverInfo discoInfo = discoManager.discoverInfo("balconyscene@plays.shakespeare.lit");
|
||||
|
||||
<font color="#3f7f5f">// Get the discovered identities of the remote XMPP entity</font>
|
||||
Iterator it = discoInfo.getIdentities();
|
||||
<font color="#3f7f5f">// Display the identities of the remote XMPP entity</font>
|
||||
while (it.hasNext()) {
|
||||
DiscoverInfo.Identity identity = (DiscoverInfo.Identity) it.next();
|
||||
System.out.println(identity.getName());
|
||||
System.out.println(identity.getType());
|
||||
System.out.println(identity.getCategory());
|
||||
}
|
||||
|
||||
<font color="#3f7f5f">// Check if room is password protected</font>
|
||||
discoInfo.containsFeature("muc_passwordprotected");
|
||||
</pre>
|
||||
</blockquote>
|
||||
|
||||
<hr>
|
||||
|
||||
<div class="subheader"><a name="discopublish">Publish publicly available items</a></div><p>
|
||||
|
||||
<b>Description</b><p>
|
||||
|
||||
Publish your entity items to some kind of persistent storage. This enables other entities to query
|
||||
that entity using the disco#items namespace and receive a result even when the entity being queried
|
||||
is not online (or available).</p>
|
||||
|
||||
<b>Usage</b><p>
|
||||
|
||||
<p>Once you have your ServiceDiscoveryManager you will be able to publish items to some kind of
|
||||
persistent storage. To publish the items of a given XMPP entity you have to first create an instance
|
||||
of <i><b>DiscoverItems</b></i> and configure it with the items to publish. Then you will have to
|
||||
send <b>publishItems(String entityID, DiscoverItems discoverItems)</b> to your <i><b>ServiceDiscoveryManager</b></i>
|
||||
where entityID is the address of the XMPP entity that will persist the items and discoverItems contains the items
|
||||
to publish.</p>
|
||||
|
||||
<b>Examples</b><p>
|
||||
|
||||
In this example we can see how to publish new items: <br>
|
||||
<blockquote>
|
||||
<pre> <font color="#3f7f5f">// Obtain the ServiceDiscoveryManager associated with my XMPPConnection</font>
|
||||
ServiceDiscoveryManager discoManager = ServiceDiscoveryManager.getInstanceFor(connection);
|
||||
|
||||
<font color="#3f7f5f">// Create a DiscoverItems with the items to publish</font>
|
||||
DiscoverItems itemsToPublish = new DiscoverItems();
|
||||
DiscoverItems.Item itemToPublish = new DiscoverItems.Item("pubsub.shakespeare.lit");
|
||||
itemToPublish.setName("Avatar");
|
||||
itemToPublish.setNode("romeo/avatar");
|
||||
itemToPublish.setAction(DiscoverItems.Item.UPDATE_ACTION);
|
||||
itemsToPublish.addItem(itemToPublish);
|
||||
|
||||
<font color="#3f7f5f">// Publish the new items by sending them to the server</font>
|
||||
discoManager.publishItems("host", itemsToPublish);
|
||||
</pre>
|
||||
</blockquote>
|
||||
</body>
|
||||
|
||||
</html>
|
15
CopyOftrunk/documentation/extensions/index.html
Normal file
|
@ -0,0 +1,15 @@
|
|||
<html>
|
||||
|
||||
<head>
|
||||
<title>Smack Extensions User Manual</title>
|
||||
<link rel="stylesheet" type="text/css" href="style.css" />
|
||||
</head>
|
||||
|
||||
<frameset cols="200,*">
|
||||
<frame src="toc.html" name="navFrame" target="mainFrame">
|
||||
<frame src="intro.html" name="mainFrame">
|
||||
</frameset>
|
||||
<noframes>
|
||||
<H2>Smack Extensions User Manual</H2>
|
||||
|
||||
<a href="toc.html">Smack Extensions User Manual</a></noframes></html>
|
70
CopyOftrunk/documentation/extensions/intro.html
Normal file
|
@ -0,0 +1,70 @@
|
|||
<html>
|
||||
<head>
|
||||
<title>Smack Extensions User Manual</title>
|
||||
<link rel="stylesheet" type="text/css" href="style.css" />
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div class="header">Smack Extensions Manual</div>
|
||||
<p>The XMPP protocol includes a base protocol and many optional extensions
|
||||
typically documented as "JEP's". Smack provides the org.jivesoftware.smack
|
||||
package for the core XMPP protocol, and the org.jivesoftware.smackx package for
|
||||
many of the protocol extensions.</p>
|
||||
|
||||
<p>This manual provides details about each of the "smackx" extensions, including what
|
||||
it is, how to use it, and some simple example code.<p>
|
||||
|
||||
<div class="subheader">Current Extensions</div><p>
|
||||
|
||||
<table border="0" width="85%" cellspacing="0" cellpadding="3" style="border:1px #bbb solid;">
|
||||
<tr bgcolor="#ddeeff">
|
||||
<td><b>Name</b></td><td><b>JEP #</b></td><td><b>Description</b></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><a href="privatedata.html">Private Data</a></td>
|
||||
<td><a href="http://www.jabber.org/jeps/jep-0049.html">JEP-49</a></td>
|
||||
<td>Manages private data.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><a href="xhtml.html">XHTML Messages</a></td>
|
||||
<td><a href="http://www.jabber.org/jeps/jep-0071.html">JEP-71</a></td>
|
||||
<td>Allows send and receiving formatted messages using XHTML.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><a href="messageevents.html">Message Events</a></td>
|
||||
<td><a href="http://www.jabber.org/jeps/jep-0022.html">JEP-22</a></td>
|
||||
<td>Requests and responds to message events.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><a href="dataforms.html">Data Forms</a></td>
|
||||
<td><a href="http://www.jabber.org/jeps/jep-0004.html">JEP-4</a></td>
|
||||
<td>Allows to gather data using Forms.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><a href="muc.html">Multi User Chat</a></td>
|
||||
<td><a href="http://www.jabber.org/jeps/jep-0045.html">JEP-45</a></td>
|
||||
<td>Allows configuration of, participation in, and administration of individual text-based conference rooms.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><a href="rosterexchange.html">Roster Item Exchange</a></td>
|
||||
<td><a href="http://www.jabber.org/jeps/jep-0093.html">JEP-93</a></td>
|
||||
<td>Allows roster data to be shared between users.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><a href="time.html">Time Exchange</a></td>
|
||||
<td><a href="http://www.jabber.org/jeps/jep-0090.html">JEP-90</a></td>
|
||||
<td>Allows local time information to be shared between users.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><a href="invitation.html">Group Chat Invitations</a></td>
|
||||
<td>N/A</td>
|
||||
<td>Send invitations to other users to join a group chat room.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><a href="disco.html">Service Discovery</a></td>
|
||||
<td><a href="http://www.jabber.org/jeps/jep-0030.html">JEP-30</a></td>
|
||||
<td>Allows to discover services in XMPP entities.</td>
|
||||
</tr>
|
||||
</table>
|
||||
</body>
|
||||
</html>
|
60
CopyOftrunk/documentation/extensions/invitation.html
Normal file
|
@ -0,0 +1,60 @@
|
|||
<html>
|
||||
<head>
|
||||
<title>Group Chat Invitations</title>
|
||||
<link rel="stylesheet" type="text/css" href="style.css" />
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<div class="header">Group Chat Invitations</div><p>
|
||||
|
||||
The group chat invitation packet extension is used to invite other
|
||||
users to a group chat room.
|
||||
|
||||
<ul>
|
||||
<li><a href="#send">Inviting Other Users</a></li>
|
||||
<li><a href="#listen">Listen for Invitations</a></li>
|
||||
</ul>
|
||||
|
||||
<p>
|
||||
<b>JEP related:</b> N/A -- this protocol is outdated now that the Multi-User Chat (MUC) JEP is available
|
||||
(<a href="http://www.jabber.org/jeps/jep-0045.html">JEP-45</a>). However, most
|
||||
existing clients still use this older protocol. Once MUC support becomes more
|
||||
widespread, this API may be deprecated.
|
||||
|
||||
<hr>
|
||||
|
||||
<p><div class="subheader"><a name="send">Inviting Other Users</a></div><p>
|
||||
|
||||
To use the GroupChatInvitation packet extension
|
||||
to invite another user to a group chat room, address a new message to the
|
||||
user and set the room name appropriately, as in the following code example:
|
||||
|
||||
<pre>
|
||||
Message message = new Message(<font color="#0000FF">"user@chat.example.com"</font>);
|
||||
message.setBody(<font color="#0000FF">"Join me for a group chat!"</font>);
|
||||
message.addExtension(new GroupChatInvitation(<font color="#0000FF">"room@chat.example.com"</font>));
|
||||
con.sendPacket(message);
|
||||
</pre>
|
||||
|
||||
The XML generated for the invitation portion of the code above would be:
|
||||
|
||||
<pre>
|
||||
<x xmlns="jabber:x:conference" jid="room@chat.example.com"/>
|
||||
</pre><p>
|
||||
|
||||
<hr>
|
||||
<div class="subheader"><a name="listen">Listening for Invitations</a></div><p>
|
||||
|
||||
To listen for group chat invitations, use a PacketExtensionFilter for the
|
||||
<tt>x</tt> element name and <tt>jabber:x:conference</tt> namespace, as in the
|
||||
following code example:
|
||||
|
||||
<pre>
|
||||
PacketFilter filter = new PacketExtensionFilter(<font color="#0000FF">"x"</font>, <font color="#0000FF">"jabber:x:conference"</font>);
|
||||
<font color="#3f7f5f">// Create a packet collector or packet listeners using the filter...</font>
|
||||
</pre>
|
||||
|
||||
</body>
|
||||
|
||||
</html>
|
244
CopyOftrunk/documentation/extensions/messageevents.html
Normal file
|
@ -0,0 +1,244 @@
|
|||
<html>
|
||||
<head>
|
||||
<title>Message Events</title>
|
||||
<link rel="stylesheet" type="text/css" href="style.css" />
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<div class="header">Message Events</div><p>
|
||||
|
||||
This extension is used to request and respond to events relating to the delivery,
|
||||
display, and composition of messages. There are three stages in this extension:<ol>
|
||||
<li>Request for event notifications,
|
||||
<li>Receive the event notification requests and send event notifications, and
|
||||
<li>Receive the event notifications.</ol>
|
||||
<p>For more information on each stage please follow these links:</p>
|
||||
<ul>
|
||||
<li><a href="#reqevnot">Requesting Event Notifications</a></li>
|
||||
<li><a href="#lstevnotreq">Reacting to Event Notification Requests</a></li>
|
||||
<li><a href="#lstevnot">Reacting to Event Notifications</a></li>
|
||||
</ul>
|
||||
<b>JEP related:</b> <a href="http://www.jabber.org/jeps/jep-0022.html">JEP-22</a>
|
||||
<hr>
|
||||
<div class="subheader"><a name="reqevnot">Requesting Event Notifications</a></div><p>
|
||||
<b>Description</b><p>
|
||||
|
||||
In order to receive event notifications for a given message you first have to specify
|
||||
which events are you interested in. Each message that you send has to request its own event
|
||||
notifications. Therefore, every message that you send as part of a chat should request its own event
|
||||
notifications.</p>
|
||||
|
||||
<b>Usage</b><p>
|
||||
|
||||
The class <i>MessageEventManager</i> provides an easy way for requesting event notifications. All you have to do is specify
|
||||
the message that requires the event notifications and the events that you are interested in.
|
||||
<p>Use the static method <i><b>MessageEventManager.addNotificationsRequests(Message message, boolean offline, boolean
|
||||
delivered, boolean displayed, boolean composing)</b></i> for requesting event notifications.
|
||||
</p>
|
||||
|
||||
<b>Example</b><p>
|
||||
Below you can find an example that logs in a user to the server, creates a message, adds the requests
|
||||
for notifications and sends the message.
|
||||
<blockquote>
|
||||
<pre> <font color="#3f7f5f">// Connect to the server and log in</font>
|
||||
conn1 = new XMPPConnection(host);
|
||||
conn1.login(server_user1, pass1);
|
||||
|
||||
<font color="#3f7f5f">// Create a chat with user2</font>
|
||||
Chat chat1 = conn1.createChat(user2);
|
||||
|
||||
<font color="#3f7f5f">// Create a message to send</font>
|
||||
Message msg = chat1.createMessage();
|
||||
msg.setSubject(<font color="#0000FF">"Any subject you want"</font>);
|
||||
msg.setBody(<font color="#0000FF">"An interesting body comes here..."</font>);
|
||||
<font color="#3f7f5f">// Add to the message all the notifications requests (offline, delivered, displayed,</font>
|
||||
<font color="#3f7f5f">// composing)</font>
|
||||
MessageEventManager.addNotificationsRequests(msg, <font COLOR="#7f0055"><b>true</b></font>, <font COLOR="#7f0055"><b>true</b></font>, <font COLOR="#7f0055"><b>true</b></font>, <font COLOR="#7f0055"><b>true</b></font>);
|
||||
|
||||
<font color="#3f7f5f">// Send the message that contains the notifications request</font>
|
||||
chat1.sendMessage(msg);
|
||||
</pre>
|
||||
</blockquote>
|
||||
|
||||
<hr>
|
||||
|
||||
<div class="subheader"><a name="lstevnotreq">Reacting to Event Notification Requests</a></div><p>
|
||||
|
||||
<b>Description</b><p>
|
||||
|
||||
You can receive notification requests for the following events: delivered, displayed, composing and offline. You
|
||||
<b>must</b> listen for these requests and react accordingly.</p>
|
||||
|
||||
<b>Usage</b><p>
|
||||
|
||||
The general idea is to create a new <i>DefaultMessageEventRequestListener</i> that will listen to the event notifications
|
||||
requests and react with custom logic. Then you will have to add the listener to the
|
||||
<i>MessageEventManager</i> that works on
|
||||
the desired <i>XMPPConnection</i>.
|
||||
<p>Note that <i>DefaultMessageEventRequestListener</i> is a default implementation of the
|
||||
<i>MessageEventRequestListener</i> interface.
|
||||
The class <i>DefaultMessageEventRequestListener</i> automatically sends a delivered notification to the sender of the message
|
||||
if the sender has requested to be notified when the message is delivered. If you decide to create a new class that
|
||||
implements the <i>MessageEventRequestListener</i> interface, please remember to send the delivered notification.</p>
|
||||
<ul>
|
||||
<li>To create a new <i>MessageEventManager</i> use the <i><b>MessageEventManager(XMPPConnection)</b></i> constructor.
|
||||
</li>
|
||||
<li>To create an event notification requests listener create a subclass of <i><b>DefaultMessageEventRequestListener</b></i> or
|
||||
create a class that implements the <i><b>MessageEventRequestListener</b></i> interface.
|
||||
</li>
|
||||
<li>To add a listener to the messageEventManager use the MessageEventManager's message
|
||||
<i><b>addMessageEventRequestListener(MessageEventRequestListener)</b></i>.</li>
|
||||
</ul></p>
|
||||
|
||||
<b>Example</b><p>
|
||||
|
||||
Below you can find an example that connects two users to the server. One user will create a message, add the requests
|
||||
for notifications and will send the message to the other user. The other user will add a
|
||||
<i>DefaultMessageEventRequestListener</i>
|
||||
to a <i>MessageEventManager</i> that will listen and react to the event notification requested by the other user.
|
||||
<blockquote>
|
||||
<pre> <font color="#3f7f5f">// Connect to the server and log in the users</font>
|
||||
conn1 = new XMPPConnection(host);
|
||||
conn1.login(server_user1, pass1);
|
||||
conn2 = new XMPPConnection(host);
|
||||
conn2.login(server_user2, pass2);
|
||||
|
||||
<font color="#3f7f5f">// User2 creates a MessageEventManager</font>
|
||||
MessageEventManager messageEventManager = new MessageEventManager(conn2);
|
||||
<font color="#3f7f5f">// User2 adds the listener that will react to the event notifications requests</font>
|
||||
messageEventManager.addMessageEventRequestListener(new DefaultMessageEventRequestListener() {
|
||||
public void deliveredNotificationRequested(
|
||||
String from,
|
||||
String packetID,
|
||||
MessageEventManager messageEventManager) {
|
||||
super.deliveredNotificationRequested(from, packetID, messageEventManager);
|
||||
<font color="#3f7f5f">// DefaultMessageEventRequestListener automatically responds that the message was delivered when receives this request</font>
|
||||
System.out.println(<font color="#0000FF">"Delivered Notification Requested (" + from + ", " + packetID + ")"</font>);
|
||||
}
|
||||
|
||||
public void displayedNotificationRequested(
|
||||
String from,
|
||||
String packetID,
|
||||
MessageEventManager messageEventManager) {
|
||||
super.displayedNotificationRequested(from, packetID, messageEventManager);
|
||||
<font color="#3f7f5f">// Send to the message's sender that the message was displayed</font>
|
||||
messageEventManager.sendDisplayedNotification(from, packetID);
|
||||
}
|
||||
|
||||
public void composingNotificationRequested(
|
||||
String from,
|
||||
String packetID,
|
||||
MessageEventManager messageEventManager) {
|
||||
super.composingNotificationRequested(from, packetID, messageEventManager);
|
||||
<font color="#3f7f5f">// Send to the message's sender that the message's receiver is composing a reply</font>
|
||||
messageEventManager.sendComposingNotification(from, packetID);
|
||||
}
|
||||
|
||||
public void offlineNotificationRequested(
|
||||
String from,
|
||||
String packetID,
|
||||
MessageEventManager messageEventManager) {
|
||||
super.offlineNotificationRequested(from, packetID, messageEventManager);
|
||||
<font color="#3f7f5f">// The XMPP server should take care of this request. Do nothing.</font>
|
||||
System.out.println(<font color="#0000FF">"Offline Notification Requested (" + from + ", " + packetID + ")"</font>);
|
||||
}
|
||||
});
|
||||
|
||||
<font color="#3f7f5f">// User1 creates a chat with user2</font>
|
||||
Chat chat1 = conn1.createChat(user2);
|
||||
|
||||
<font color="#3f7f5f">// User1 creates a message to send to user2</font>
|
||||
Message msg = chat1.createMessage();
|
||||
msg.setSubject(<font color="#0000FF">"Any subject you want"</font>);
|
||||
msg.setBody(<font color="#0000FF">"An interesting body comes here..."</font>);
|
||||
<font color="#3f7f5f">// User1 adds to the message all the notifications requests (offline, delivered, displayed,</font>
|
||||
<font color="#3f7f5f">// composing)</font>
|
||||
MessageEventManager.addNotificationsRequests(msg, <font COLOR="#7f0055"><b>true</b></font>, <font COLOR="#7f0055"><b>true</b></font>, <font COLOR="#7f0055"><b>true</b></font>, <font COLOR="#7f0055"><b>true</b></font>);
|
||||
|
||||
<font color="#3f7f5f">// User1 sends the message that contains the notifications request</font>
|
||||
chat1.sendMessage(msg);
|
||||
Thread.sleep(500);
|
||||
<font color="#3f7f5f">// User2 sends to the message's sender that the message's receiver cancelled composing a reply</font>
|
||||
messageEventManager.sendCancelledNotification(user1, msg.getPacketID());
|
||||
</pre>
|
||||
</blockquote>
|
||||
|
||||
<hr>
|
||||
|
||||
<div class="subheader"><a name="lstevnot">Reacting to Event Notifications</a></div><p>
|
||||
|
||||
<b>Description</b><p>
|
||||
|
||||
Once you have requested for event notifications you will start to receive notifications of events. You can
|
||||
receive notifications of the following events: delivered, displayed, composing, offline and cancelled. You
|
||||
will probably want to react to some or all of these events.</p>
|
||||
|
||||
<b>Usage</b><p>
|
||||
|
||||
The general idea is to create a new <i>MessageEventNotificationListener</i> that will listen to the event notifications
|
||||
and react with custom logic. Then you will have to add the listener to the <i>MessageEventManager</i> that works on
|
||||
the desired <i>XMPPConnection</i>.
|
||||
<ul>
|
||||
<li>To create a new <i>MessageEventManager</i> use the <i><b>MessageEventManager(XMPPConnection)</b></i> constructor.
|
||||
</li>
|
||||
<li>To create an event notifications listener create a class that implements the <i><b>MessageEventNotificationListener</b></i>
|
||||
interface.
|
||||
</li>
|
||||
<li>To add a listener to the messageEventManager use the MessageEventManager's message
|
||||
<i><b>addMessageEventNotificationListener(MessageEventNotificationListener)</b></i>.</li>
|
||||
</ul></p>
|
||||
|
||||
<b>Example</b><p>
|
||||
Below you can find an example that logs in a user to the server, adds a <i>MessageEventNotificationListener</i>
|
||||
to a <i>MessageEventManager</i> that will listen and react to the event notifications, creates a message, adds
|
||||
the requests for notifications and sends the message.
|
||||
<blockquote>
|
||||
<pre> <font color="#3f7f5f">// Connect to the server and log in</font>
|
||||
conn1 = new XMPPConnection(host);
|
||||
conn1.login(server_user1, pass1);
|
||||
|
||||
<font color="#3f7f5f">// Create a MessageEventManager</font>
|
||||
MessageEventManager messageEventManager = new MessageEventManager(conn1);
|
||||
<font color="#3f7f5f">// Add the listener that will react to the event notifications</font>
|
||||
messageEventManager.addMessageEventNotificationListener(new MessageEventNotificationListener() {
|
||||
public void deliveredNotification(String from, String packetID) {
|
||||
System.out.println(<font color="#0000FF">"The message has been delivered (" + from + ", " + packetID + ")"</font>);
|
||||
}
|
||||
|
||||
public void displayedNotification(String from, String packetID) {
|
||||
System.out.println(<font color="#0000FF">"The message has been displayed (" + from + ", " + packetID + ")"</font>);
|
||||
}
|
||||
|
||||
public void composingNotification(String from, String packetID) {
|
||||
System.out.println(<font color="#0000FF">"The message's receiver is composing a reply (" + from + ", " + packetID + ")"</font>);
|
||||
}
|
||||
|
||||
public void offlineNotification(String from, String packetID) {
|
||||
System.out.println(<font color="#0000FF">"The message's receiver is offline (" + from + ", " + packetID + ")"</font>);
|
||||
}
|
||||
|
||||
public void cancelledNotification(String from, String packetID) {
|
||||
System.out.println(<font color="#0000FF">"The message's receiver cancelled composing a reply (" + from + ", " + packetID + ")"</font>);
|
||||
}
|
||||
});
|
||||
|
||||
<font color="#3f7f5f">// Create a chat with user2</font>
|
||||
Chat chat1 = conn1.createChat(user2);
|
||||
|
||||
<font color="#3f7f5f">// Create a message to send</font>
|
||||
Message msg = chat1.createMessage();
|
||||
msg.setSubject(<font color="#0000FF">"Any subject you want"</font>);
|
||||
msg.setBody(<font color="#0000FF">"An interesting body comes here..."</font>);
|
||||
<font color="#3f7f5f">// Add to the message all the notifications requests (offline, delivered, displayed,</font>
|
||||
<font color="#3f7f5f">// composing)</font>
|
||||
MessageEventManager.addNotificationsRequests(msg, <font COLOR="#7f0055"><b>true</b></font>, <font COLOR="#7f0055"><b>true</b></font>, <font COLOR="#7f0055"><b>true</b></font>, <font COLOR="#7f0055"><b>true</b></font>);
|
||||
|
||||
<font color="#3f7f5f">// Send the message that contains the notifications request</font>
|
||||
chat1.sendMessage(msg);
|
||||
</pre>
|
||||
</blockquote>
|
||||
|
||||
</body>
|
||||
|
||||
</html>
|
619
CopyOftrunk/documentation/extensions/muc.html
Normal file
|
@ -0,0 +1,619 @@
|
|||
<html>
|
||||
<head>
|
||||
<title>Multi User Chat</title>
|
||||
<link rel="stylesheet" type="text/css" href="style.css" />
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<div class="header">Multi User Chat</div><p>
|
||||
|
||||
Allows configuration of, participation in, and administration of individual text-based conference rooms.<p>
|
||||
|
||||
<ul>
|
||||
<li><a href="#create">Create a new Room</a></li>
|
||||
<li><a href="#join">Join a room</a></li>
|
||||
<li><a href="#invite">Manage room invitations</a></li>
|
||||
<li><a href="#discomuc">Discover MUC support</a></li>
|
||||
<li><a href="#discojoin">Discover joined rooms</a></li>
|
||||
<li><a href="#discoroom">Discover room information</a></li>
|
||||
<li><a href="#privchat">Start a private chat</a></li>
|
||||
<li><a href="#subject">Manage changes on room subject</a></li>
|
||||
<li><a href="#role">Manage role modifications</a></li>
|
||||
<li><a href="#afiliation">Manage affiliation modifications</a></li>
|
||||
</ul>
|
||||
<b>JEP related:</b> <a href="http://www.jabber.org/jeps/jep-0045.html">JEP-45</a>
|
||||
|
||||
<hr>
|
||||
|
||||
<div class="subheader"><a name="create">Create a new Room</a></div><p>
|
||||
|
||||
<b>Description</b><p>
|
||||
|
||||
Allowed users may create new rooms. There are two types of rooms that you can create. <b>Instant rooms</b>
|
||||
which are available for immediate access and are automatically created based on some default
|
||||
configuration and <b>Reserved rooms</b> which are manually configured by the room creator before
|
||||
anyone is allowed to enter.</p>
|
||||
|
||||
<b>Usage</b><p>
|
||||
|
||||
In order to create a room you will need to first create an instance of <i><b>MultiUserChat</b></i>. The
|
||||
room name passed to the constructor will be the name of the room to create. The next step is to send
|
||||
<b>create(String nickname)</b> to the <i><b>MultiUserChat</b></i> instance where nickname is the nickname
|
||||
to use when joining the room.</p><p>
|
||||
|
||||
Depending on the type of room that you want to create you will have to use different configuration forms. In
|
||||
order to create an Instant room just send <b>sendConfigurationForm(Form form)</b> where form is an empty form.
|
||||
But if you want to create a Reserved room then you should first get the room's configuration form, complete
|
||||
the form and finally send it back to the server.</p>
|
||||
|
||||
<b>Examples</b><p>
|
||||
|
||||
In this example we can see how to create an instant room: <br>
|
||||
<blockquote>
|
||||
<pre> <font color="#3f7f5f">// Create a MultiUserChat using an XMPPConnection for a room</font>
|
||||
MultiUserChat muc = new MultiUserChat(conn1, <font color="#0000FF">"myroom@conference.jabber.org"</font>);
|
||||
|
||||
<font color="#3f7f5f">// Create the room</font>
|
||||
muc.create(<font color="#0000FF">"testbot"</font>);
|
||||
|
||||
<font color="#3f7f5f">// Send an empty room configuration form which indicates that we want</font>
|
||||
<font color="#3f7f5f">// an instant room</font>
|
||||
muc.sendConfigurationForm(new Form(Form.TYPE_SUBMIT));
|
||||
</pre>
|
||||
</blockquote>
|
||||
|
||||
In this example we can see how to create a reserved room. The form is completed with default values: <br>
|
||||
<blockquote>
|
||||
<pre> <font color="#3f7f5f">// Create a MultiUserChat using an XMPPConnection for a room</font>
|
||||
MultiUserChat muc = new MultiUserChat(conn1, <font color="#0000FF">"myroom@conference.jabber.org"</font>);
|
||||
|
||||
<font color="#3f7f5f">// Create the room</font>
|
||||
muc.create(<font color="#0000FF">"testbot"</font>);
|
||||
|
||||
<font color="#3f7f5f">// Get the the room's configuration form</font>
|
||||
Form form = muc.getConfigurationForm();
|
||||
<font color="#3f7f5f">// Create a new form to submit based on the original form</font>
|
||||
Form submitForm = form.createAnswerForm();
|
||||
<font color="#3f7f5f">// Add default answers to the form to submit</font>
|
||||
for (Iterator fields = form.getFields(); fields.hasNext();) {
|
||||
FormField field = (FormField) fields.next();
|
||||
if (!FormField.TYPE_HIDDEN.equals(field.getType()) && field.getVariable() != null) {
|
||||
<font color="#3f7f5f">// Sets the default value as the answer</font>
|
||||
submitForm.setDefaultAnswer(field.getVariable());
|
||||
}
|
||||
}
|
||||
<font color="#3f7f5f">// Sets the new owner of the room</font>
|
||||
List owners = new ArrayList();
|
||||
owners.add(<font color="#0000FF">"johndoe@jabber.org"</font>);
|
||||
submitForm.setAnswer(<font color="#0000FF">"muc#roomconfig_roomowners"</font>, owners);
|
||||
<font color="#3f7f5f">// Send the completed form (with default values) to the server to configure the room</font>
|
||||
muc.sendConfigurationForm(submitForm);
|
||||
</pre>
|
||||
</blockquote>
|
||||
|
||||
<hr>
|
||||
|
||||
<div class="subheader"><a name="join">Join a room</a></div><p>
|
||||
|
||||
<b>Description</b><p>
|
||||
|
||||
Your usual first step in order to send messages to a room is to join the room. Multi User Chat allows
|
||||
to specify several parameter while joining a room. Basically you can control the amount of history to
|
||||
receive after joining the room as well as provide your nickname within the room and a password if the
|
||||
room is password protected.</p>
|
||||
|
||||
<b>Usage</b><p>
|
||||
|
||||
In order to join a room you will need to first create an instance of <i><b>MultiUserChat</b></i>. The
|
||||
room name passed to the constructor will be the name of the room to join. The next step is to send
|
||||
<b>join(...)</b> to the <i><b>MultiUserChat</b></i> instance. But first you will have to decide which
|
||||
join message to send. If you want to just join the room without a password and without specifying the amount
|
||||
of history to receive then you could use <b>join(String nickname)</b> where nickname if your nickname in
|
||||
the room. In case the room requires a password in order to join you could then use
|
||||
<b>join(String nickname, String password)</b>. And finally, the most complete way to join a room is to send
|
||||
<b>join(String nickname, String password, DiscussionHistory history, long timeout)</b>
|
||||
where nickname is your nickname in the room, , password is your password to join the room, history is
|
||||
an object that specifies the amount of history to receive and timeout is the milliseconds to wait
|
||||
for a response from the server.</p>
|
||||
|
||||
<b>Examples</b><p>
|
||||
|
||||
In this example we can see how to join a room with a given nickname: <br>
|
||||
<blockquote>
|
||||
<pre> <font color="#3f7f5f">// Create a MultiUserChat using an XMPPConnection for a room</font>
|
||||
MultiUserChat muc2 = new MultiUserChat(conn1, <font color="#0000FF">"myroom@conference.jabber.org"</font>);
|
||||
|
||||
<font color="#3f7f5f">// User2 joins the new room</font>
|
||||
<font color="#3f7f5f">// The room service will decide the amount of history to send</font>
|
||||
muc2.join(<font color="#0000FF">"testbot2"</font>);
|
||||
</pre>
|
||||
</blockquote>
|
||||
|
||||
In this example we can see how to join a room with a given nickname and password: <br>
|
||||
<blockquote>
|
||||
<pre> <font color="#3f7f5f">// Create a MultiUserChat using an XMPPConnection for a room</font>
|
||||
MultiUserChat muc2 = new MultiUserChat(conn1, <font color="#0000FF">"myroom@conference.jabber.org"</font>);
|
||||
|
||||
<font color="#3f7f5f">// User2 joins the new room using a password</font>
|
||||
<font color="#3f7f5f">// The room service will decide the amount of history to send</font>
|
||||
muc2.join(<font color="#0000FF">"testbot2"</font>, <font color="#0000FF">"password"</font>);
|
||||
</pre>
|
||||
</blockquote>
|
||||
|
||||
In this example we can see how to join a room with a given nickname specifying the amount of history
|
||||
to receive: <br>
|
||||
<blockquote>
|
||||
<pre> <font color="#3f7f5f">// Create a MultiUserChat using an XMPPConnection for a room</font>
|
||||
MultiUserChat muc2 = new MultiUserChat(conn1, <font color="#0000FF">"myroom@conference.jabber.org"</font>);
|
||||
|
||||
<font color="#3f7f5f">// User2 joins the new room using a password and specifying</font>
|
||||
<font color="#3f7f5f">// the amount of history to receive. In this example we are requesting the last 5 messages.</font>
|
||||
DiscussionHistory history = new DiscussionHistory();
|
||||
history.setMaxStanzas(5);
|
||||
muc2.join(<font color="#0000FF">"testbot2"</font>, <font color="#0000FF">"password"</font>, history, SmackConfiguration.getPacketReplyTimeout());
|
||||
</pre>
|
||||
</blockquote>
|
||||
|
||||
<hr>
|
||||
|
||||
<div class="subheader"><a name="invite">Manage room invitations</a></div><p>
|
||||
|
||||
<b>Description</b><p>
|
||||
|
||||
It can be useful to invite another user to a room in which one is an occupant. Depending on the
|
||||
room's type the invitee could receive a password to use to join the room and/or be added to the
|
||||
member list if the room is of type members-only. Smack allows to send room invitations and let
|
||||
potential invitees to listening for room invitations and inviters to listen for invitees'
|
||||
rejections.</p>
|
||||
|
||||
<b>Usage</b><p>
|
||||
|
||||
In order to invite another user to a room you must be already joined to the room. Once you are
|
||||
joined just send <b>invite(String participant, String reason)</b> to the <i><b>MultiUserChat</b></i>
|
||||
where participant is the user to invite to the room (e.g. hecate@shakespeare.lit) and reason is
|
||||
the reason why the user is being invited.</p><p>
|
||||
|
||||
If potential invitees want to listen for room invitations then the invitee must add an <i><b>InvitationListener</b></i>
|
||||
to the <i><b>MultiUserChat</b></i> class. Since the <i><b>InvitationListener</b></i> is an <i>interface</i>,
|
||||
it is necessary to create a class that implements this <i>interface</i>. If an inviter wants to
|
||||
listen for room invitation rejections, just add an <i><b>InvitationRejectionListener</b></i>
|
||||
to the <i><b>MultiUserChat</b></i>. <i><b>InvitationRejectionListener</b></i> is also an
|
||||
interface so you will need to create a class that implements this interface.</p>
|
||||
|
||||
<b>Examples</b><p>
|
||||
|
||||
In this example we can see how to invite another user to the room and lister for possible rejections: <br>
|
||||
<blockquote>
|
||||
<pre> <font color="#3f7f5f">// User2 joins the room</font>
|
||||
MultiUserChat muc2 = new MultiUserChat(conn2, room);
|
||||
muc2.join(<font color="#0000FF">"testbot2"</font>);
|
||||
|
||||
<font color="#3f7f5f">// User2 listens for invitation rejections</font>
|
||||
muc2.addInvitationRejectionListener(new InvitationRejectionListener() {
|
||||
public void invitationDeclined(String invitee, String reason) {
|
||||
<font color="#3f7f5f">// Do whatever you need here...</font>
|
||||
}
|
||||
});
|
||||
|
||||
<font color="#3f7f5f">// User2 invites user3 to join to the room</font>
|
||||
muc2.invite(<font color="#0000FF">"user3@host.org/Smack"</font>, <font color="#0000FF">"Meet me in this excellent room"</font>);
|
||||
</pre>
|
||||
</blockquote>
|
||||
|
||||
In this example we can see how to listen for room invitations and decline invitations: <br>
|
||||
<blockquote>
|
||||
<pre> <font color="#3f7f5f">// User3 listens for MUC invitations</font>
|
||||
MultiUserChat.addInvitationListener(conn3, new InvitationListener() {
|
||||
public void invitationReceived(XMPPConnection conn, String room, String inviter, String reason, String password) {
|
||||
<font color="#3f7f5f">// Reject the invitation</font>
|
||||
MultiUserChat.decline(conn, room, inviter, <font color="#0000FF">"I'm busy right now"</font>);
|
||||
}
|
||||
});
|
||||
</pre>
|
||||
</blockquote>
|
||||
|
||||
<hr>
|
||||
|
||||
<div class="subheader"><a name="discomuc">Discover MUC support</a></div><p>
|
||||
|
||||
<b>Description</b><p>
|
||||
|
||||
A user may want to discover if one of the user's contacts supports the Multi-User Chat protocol.</p>
|
||||
|
||||
<b>Usage</b><p>
|
||||
|
||||
In order to discover if one of the user's contacts supports MUC just send
|
||||
<b>isServiceEnabled(XMPPConnection connection, String user)</b> to the <i><b>MultiUserChat</b></i>
|
||||
class where user is a fully qualified XMPP ID, e.g. jdoe@example.com. You will receive
|
||||
a boolean indicating whether the user supports MUC or not.</p>
|
||||
|
||||
<b>Examples</b><p>
|
||||
|
||||
In this example we can see how to discover support of MUC: <br>
|
||||
<blockquote>
|
||||
<pre> <font color="#3f7f5f">// Discover whether user3@host.org supports MUC or not</font>
|
||||
boolean supports = MultiUserChat.isServiceEnabled(conn, <font color="#0000FF">"user3@host.org/Smack"</font>);
|
||||
</pre>
|
||||
</blockquote>
|
||||
|
||||
<hr>
|
||||
|
||||
<div class="subheader"><a name="discojoin">Discover joined rooms</a></div><p>
|
||||
|
||||
<b>Description</b><p>
|
||||
|
||||
A user may also want to query a contact regarding which rooms the contact is in.</p>
|
||||
|
||||
<b>Usage</b><p>
|
||||
|
||||
In order to get the rooms where a user is in just send
|
||||
<b>getJoinedRooms(XMPPConnection connection, String user)</b> to the <i><b>MultiUserChat</b></i>
|
||||
class where user is a fully qualified XMPP ID, e.g. jdoe@example.com. You will get an Iterator
|
||||
of Strings as an answer where each String represents a room name.</p>
|
||||
|
||||
<b>Examples</b><p>
|
||||
|
||||
In this example we can see how to get the rooms where a user is in: <br>
|
||||
<blockquote>
|
||||
<pre> <font color="#3f7f5f">// Get the rooms where user3@host.org has joined</font>
|
||||
Iterator joinedRooms = MultiUserChat.getJoinedRooms(conn, <font color="#0000FF">"user3@host.org/Smack"</font>);
|
||||
</pre>
|
||||
</blockquote>
|
||||
|
||||
<hr>
|
||||
|
||||
<div class="subheader"><a name="discoroom">Discover room information</a></div><p>
|
||||
|
||||
<b>Description</b><p>
|
||||
|
||||
A user may need to discover information about a room without having to actually join the room. The server
|
||||
will provide information only for public rooms.</p>
|
||||
|
||||
<b>Usage</b><p>
|
||||
|
||||
In order to discover information about a room just send <b>getRoomInfo(XMPPConnection connection, String room)</b>
|
||||
to the <i><b>MultiUserChat</b></i> class where room is the XMPP ID of the room, e.g.
|
||||
roomName@conference.myserver. You will get a RoomInfo object that contains the discovered room
|
||||
information.</p>
|
||||
|
||||
<b>Examples</b><p>
|
||||
|
||||
In this example we can see how to discover information about a room: <br>
|
||||
<blockquote>
|
||||
<pre> <font color="#3f7f5f">// Discover information about the room roomName@conference.myserver</font>
|
||||
RoomInfo info = MultiUserChat.getRoomInfo(conn, <font color="#0000FF">"roomName@conference.myserver"</font>);
|
||||
System.out.println("Number of occupants:" + info.getOccupantsCount());
|
||||
System.out.println("Room Subject:" + info.getSubject());
|
||||
</pre>
|
||||
</blockquote>
|
||||
|
||||
<hr>
|
||||
|
||||
<div class="subheader"><a name="privchat">Start a private chat</a></div><p>
|
||||
|
||||
<b>Description</b><p>
|
||||
|
||||
A room occupant may want to start a private chat with another room occupant even though they
|
||||
don't know the fully qualified XMPP ID (e.g. jdoe@example.com) of each other.</p>
|
||||
|
||||
<b>Usage</b><p>
|
||||
|
||||
To create a private chat with another room occupant just send <b>createPrivateChat(String participant)</b>
|
||||
to the <i><b>MultiUserChat</b></i> that you used to join the room. The parameter participant is the
|
||||
occupant unique room JID (e.g. 'darkcave@macbeth.shakespeare.lit/Paul'). You will receive
|
||||
a regular <i><b>Chat</b></i> object that you can use to chat with the other room occupant.</p>
|
||||
|
||||
<b>Examples</b><p>
|
||||
|
||||
In this example we can see how to start a private chat with another room occupant: <br>
|
||||
<blockquote>
|
||||
<pre> <font color="#3f7f5f">// Start a private chat with another participant</font>
|
||||
Chat chat = muc2.createPrivateChat(<font color="#0000FF">"myroom@conference.jabber.org/johndoe"</font>);
|
||||
chat.sendMessage(<font color="#0000FF">"Hello there"</font>);
|
||||
</pre>
|
||||
</blockquote>
|
||||
|
||||
<hr>
|
||||
|
||||
<div class="subheader"><a name="subject">Manage changes on room subject</a></div><p>
|
||||
|
||||
<b>Description</b><p>
|
||||
|
||||
A common feature of multi-user chat rooms is the ability to change the subject within the room. As a
|
||||
default, only users with a role of "moderator" are allowed to change the subject in a room. Although
|
||||
some rooms may be configured to allow a mere participant or even a visitor to change the subject.</p><p>
|
||||
|
||||
Every time the room's subject is changed you may want to be notified of the modification. The new subject
|
||||
could be used to display an in-room message.</p>
|
||||
|
||||
<b>Usage</b><p>
|
||||
|
||||
In order to modify the room's subject just send <b>changeSubject(String subject)</b> to the
|
||||
<i><b>MultiUserChat</b></i> that you used to join the room where subject is the new room's subject. On
|
||||
the other hand, if you want to be notified whenever the room's subject is modified you should add a
|
||||
<i><b>SubjectUpdatedListener</b></i> to the <i><b>MultiUserChat</b></i> by sending
|
||||
<b>addSubjectUpdatedListener(SubjectUpdatedListener listener)</b> to the <i><b>MultiUserChat</b></i>.
|
||||
Since the <i><b>SubjectUpdatedListener</b></i> is an <i>interface</i>, it is necessary to create a class
|
||||
that implements this <i>interface</i>.</p>
|
||||
|
||||
<b>Examples</b><p>
|
||||
|
||||
In this example we can see how to change the room's subject and react whenever the room's subject is
|
||||
modified: <br>
|
||||
<blockquote>
|
||||
<pre> <font color="#3f7f5f">// An occupant wants to be notified every time the room's subject is changed</font>
|
||||
muc3.addSubjectUpdatedListener(new SubjectUpdatedListener() {
|
||||
public void subjectUpdated(String subject, String from) {
|
||||
....
|
||||
}
|
||||
});
|
||||
|
||||
<font color="#3f7f5f">// A room's owner changes the room's subject</font>
|
||||
muc2.changeSubject(<font color="#0000FF">"New Subject"</font>);
|
||||
</pre>
|
||||
</blockquote>
|
||||
|
||||
<hr>
|
||||
|
||||
<div class="subheader"><a name="role">Manage role modifications</a></div><p>
|
||||
|
||||
<b>Description</b><p>
|
||||
|
||||
There are four defined roles that an occupant can have:</p>
|
||||
<ol start="" type="">
|
||||
<li>Moderator</li>
|
||||
<li>Participant</li>
|
||||
<li>Visitor</li>
|
||||
<li>None (the absence of a role)</li>
|
||||
</ol><p>
|
||||
|
||||
These roles are temporary in that they do not persist across a user's visits to the room
|
||||
and can change during the course of an occupant's visit to the room.</p><p>
|
||||
|
||||
A moderator is the most powerful occupant within the context of the room, and can to some
|
||||
extent manage other occupants' roles in the room. A participant has fewer privileges than a
|
||||
moderator, although he or she always has the right to speak. A visitor is a more restricted
|
||||
role within the context of a moderated room, since visitors are not allowed to send messages
|
||||
to all occupants.</p><p>
|
||||
|
||||
Roles are granted, revoked, and maintained based on the occupant's room nickname or full
|
||||
JID. Whenever an occupant's role is changed Smack will trigger specific events.</p>
|
||||
|
||||
<b>Usage</b><p>
|
||||
|
||||
In order to grant voice (i.e. make someone a <i>participant</i>) just send the message
|
||||
<b>grantVoice(String nickname)</b> to <i><b>MultiUserChat</b></i>. Use <b>revokeVoice(String nickname)</b>
|
||||
to revoke the occupant's voice (i.e. make the occupant a <i>visitor</i>).</p><p>
|
||||
|
||||
In order to grant moderator privileges to a participant or visitor just send the message
|
||||
<b>grantModerator(String nickname)</b> to <i><b>MultiUserChat</b></i>. Use <b>revokeModerator(String nickname)</b>
|
||||
to revoke the moderator privilege from the occupant thus making the occupant a participant.</p><p>
|
||||
|
||||
Smack allows you to listen for role modification events. If you are interested in listening role modification
|
||||
events of any occupant then use the listener <b><i>ParticipantStatusListener</i></b>. But if you are interested
|
||||
in listening for your own role modification events, use the listener <b><i>UserStatusListener</i></b>. Both listeners
|
||||
should be added to the <i><b>MultiUserChat</b></i> by using
|
||||
<b>addParticipantStatusListener(ParticipantStatusListener listener)</b> or
|
||||
<b>addUserStatusListener(UserStatusListener listener)</b> respectively. These listeners include several notification
|
||||
events but you may be interested in just a few of them. Smack provides default implementations for these listeners
|
||||
avoiding you to implement all the interfaces' methods. The default implementations are <b><i>DefaultUserStatusListener</i></b>
|
||||
and <b><i>DefaultParticipantStatusListener</i></b>. Below you will find the sent messages to the listeners whenever
|
||||
an occupant's role has changed.</p><p>
|
||||
|
||||
These are the triggered events when the role has been upgraded:
|
||||
</p>
|
||||
<table border="1">
|
||||
<tr><td><b>Old</b></td><td><b>New</b></td><td><b>Events</b></td></tr>
|
||||
|
||||
<tr><td>None</td><td>Visitor</td><td>--</td></tr>
|
||||
<tr><td>Visitor</td><td>Participant</td><td>voiceGranted</td></tr>
|
||||
<tr><td>Participant</td><td>Moderator</td><td>moderatorGranted</td></tr>
|
||||
|
||||
<tr><td>None</td><td>Participant</td><td>voiceGranted</td></tr>
|
||||
<tr><td>None</td><td>Moderator</td><td>voiceGranted + moderatorGranted</td></tr>
|
||||
<tr><td>Visitor</td><td>Moderator</td><td>voiceGranted + moderatorGranted</td></tr>
|
||||
</table><p>
|
||||
|
||||
These are the triggered events when the role has been downgraded:
|
||||
</p>
|
||||
<table border="1">
|
||||
<tr><td><b>Old</b></td><td><b>New</b></td><td><b>Events</b></td></tr>
|
||||
|
||||
<tr><td>Moderator</td><td>Participant</td><td>moderatorRevoked</td></tr>
|
||||
<tr><td>Participant</td><td>Visitor</td><td>voiceRevoked</td></tr>
|
||||
<tr><td>Visitor</td><td>None</td><td>kicked</td></tr>
|
||||
|
||||
<tr><td>Moderator</td><td>Visitor</td><td>voiceRevoked + moderatorRevoked</td></tr>
|
||||
<tr><td>Moderator</td><td>None</td><td>kicked</td></tr>
|
||||
<tr><td>Participant</td><td>None</td><td>kicked</td></tr>
|
||||
</table></p>
|
||||
|
||||
<b>Examples</b><p>
|
||||
|
||||
In this example we can see how to grant voice to a visitor and listen for the notification events: <br>
|
||||
<blockquote>
|
||||
<pre> <font color="#3f7f5f">// User1 creates a room</font>
|
||||
muc = new MultiUserChat(conn1, <font color="#0000FF">"myroom@conference.jabber.org"</font>);
|
||||
muc.create(<font color="#0000FF">"testbot"</font>);
|
||||
|
||||
<font color="#3f7f5f">// User1 (which is the room owner) configures the room as a moderated room</font>
|
||||
Form form = muc.getConfigurationForm();
|
||||
Form answerForm = form.createAnswerForm();
|
||||
answerForm.setAnswer(<font color="#0000FF">"muc#roomconfig_moderatedroom"</font>, <font color="#0000FF">"1"</font>);
|
||||
muc.sendConfigurationForm(answerForm);
|
||||
|
||||
<font color="#3f7f5f">// User2 joins the new room (as a visitor)</font>
|
||||
MultiUserChat muc2 = new MultiUserChat(conn2, <font color="#0000FF">"myroom@conference.jabber.org"</font>);
|
||||
muc2.join(<font color="#0000FF">"testbot2"</font>);
|
||||
<font color="#3f7f5f">// User2 will listen for his own "voice" notification events</font>
|
||||
muc2.addUserStatusListener(new DefaultUserStatusListener() {
|
||||
public void voiceGranted() {
|
||||
super.voiceGranted();
|
||||
...
|
||||
}
|
||||
public void voiceRevoked() {
|
||||
super.voiceRevoked();
|
||||
...
|
||||
}
|
||||
});
|
||||
|
||||
<font color="#3f7f5f">// User3 joins the new room (as a visitor)</font>
|
||||
MultiUserChat muc3 = new MultiUserChat(conn3, <font color="#0000FF">"myroom@conference.jabber.org"</font>);
|
||||
muc3.join(<font color="#0000FF">"testbot3"</font>);
|
||||
<font color="#3f7f5f">// User3 will lister for other occupants "voice" notification events</font>
|
||||
muc3.addParticipantStatusListener(new DefaultParticipantStatusListener() {
|
||||
public void voiceGranted(String participant) {
|
||||
super.voiceGranted(participant);
|
||||
...
|
||||
}
|
||||
|
||||
public void voiceRevoked(String participant) {
|
||||
super.voiceRevoked(participant);
|
||||
...
|
||||
}
|
||||
});
|
||||
|
||||
<font color="#3f7f5f">// The room's owner grants voice to user2</font>
|
||||
muc.grantVoice(<font color="#0000FF">"testbot2"</font>);
|
||||
</pre>
|
||||
</blockquote>
|
||||
|
||||
<hr>
|
||||
|
||||
<div class="subheader"><a name="afiliation">Manage affiliation modifications</a></div><p>
|
||||
|
||||
<b>Description</b><p>
|
||||
|
||||
There are five defined affiliations that a user can have in relation to a room:</p>
|
||||
<ol start="" type="">
|
||||
<li>Owner</li>
|
||||
<li>Admin</li>
|
||||
<li>Member</li>
|
||||
<li>Outcast</li>
|
||||
<li>None (the absence of an affiliation)</li>
|
||||
</ol><p>
|
||||
|
||||
These affiliations are semi-permanent in that they persist across a user's visits to the room and
|
||||
are not affected by happenings in the room. Affiliations are granted, revoked, and maintained
|
||||
based on the user's bare JID.</p><p>
|
||||
|
||||
If a user without a defined affiliation enters a room, the user's affiliation is defined as "none";
|
||||
however, this affiliation does not persist across visits.</p><p>
|
||||
|
||||
Owners and admins are by definition immune from certain actions. Specifically, an owner or admin cannot
|
||||
be kicked from a room and cannot be banned from a room. An admin must first lose his or her affiliation
|
||||
(i.e., have an affiliation of "none" or "member") before such actions could be performed
|
||||
on them.</p><p>
|
||||
|
||||
The member affiliation provides a way for a room owner or admin to specify a "whitelist" of users
|
||||
who are allowed to enter a members-only room. When a member enters a members-only room, his or her affiliation
|
||||
does not change, no matter what his or her role is. The member affiliation also provides a way for users to
|
||||
effectively register with an open room and thus be permanently associated with that room in some way (one
|
||||
result may be that the user's nickname is reserved in the room).</p><p>
|
||||
|
||||
An outcast is a user who has been banned from a room and who is not allowed to enter the room. Whenever a
|
||||
user's affiliation is changed Smack will trigger specific events.</p>
|
||||
|
||||
<b>Usage</b><p>
|
||||
|
||||
In order to grant membership to a room, administrator privileges or owner priveliges just send
|
||||
<b>grantMembership(String jid)</b>, <b>grantAdmin(String jid)</b> or <b>grantOwnership(String jid)</b>
|
||||
to <i><b>MultiUserChat</b></i> respectively. Use <b>revokeMembership(String jid)</b>, <b>revokeAdmin(String jid)</b>
|
||||
or <b>revokeOwnership(String jid)</b> to revoke the membership to a room, administrator privileges or
|
||||
owner priveliges respectively.</p><p>
|
||||
|
||||
In order to ban a user from the room just send the message <b>banUser(String jid, String reason)</b> to
|
||||
<i><b>MultiUserChat</b></i>.</p><p>
|
||||
|
||||
Smack allows you to listen for affiliation modification events. If you are interested in listening affiliation modification
|
||||
events of any user then use the listener <b><i>ParticipantStatusListener</i></b>. But if you are interested
|
||||
in listening for your own affiliation modification events, use the listener <b><i>UserStatusListener</i></b>. Both listeners
|
||||
should be added to the <i><b>MultiUserChat</b></i> by using
|
||||
<b>addParticipantStatusListener(ParticipantStatusListener listener)</b> or
|
||||
<b>addUserStatusListener(UserStatusListener listener)</b> respectively. These listeners include several notification
|
||||
events but you may be interested in just a few of them. Smack provides default implementations for these listeners
|
||||
avoiding you to implement all the interfaces' methods. The default implementations are <b><i>DefaultUserStatusListener</i></b>
|
||||
and <b><i>DefaultParticipantStatusListener</i></b>. Below you will find the sent messages to the listeners whenever
|
||||
a user's affiliation has changed.</p><p>
|
||||
|
||||
These are the triggered events when the affiliation has been upgraded:
|
||||
</p>
|
||||
<table border="1">
|
||||
<tr><td><b>Old</b></td><td><b>New</b></td><td><b>Events</b></td></tr>
|
||||
|
||||
<tr><td>None</td><td>Member</td><td>membershipGranted</td></tr>
|
||||
<tr><td>Member</td><td>Admin</td><td>membershipRevoked + adminGranted</td></tr>
|
||||
<tr><td>Admin</td><td>Owner</td><td>adminRevoked + ownershipGranted</td></tr>
|
||||
|
||||
<tr><td>None</td><td>Admin</td><td>adminGranted</td></tr>
|
||||
<tr><td>None</td><td>Owner</td><td>ownershipGranted</td></tr>
|
||||
<tr><td>Member</td><td>Owner</td><td>membershipRevoked + ownershipGranted</td></tr>
|
||||
</table><p>
|
||||
|
||||
These are the triggered events when the affiliation has been downgraded:
|
||||
</p>
|
||||
<table border="1">
|
||||
<tr><td><b>Old</b></td><td><b>New</b></td><td><b>Events</b></td></tr>
|
||||
|
||||
<tr><td>Owner</td><td>Admin</td><td>ownershipRevoked + adminGranted</td></tr>
|
||||
<tr><td>Admin</td><td>Member</td><td>adminRevoked + membershipGranted</td></tr>
|
||||
<tr><td>Member</td><td>None</td><td>membershipRevoked</td></tr>
|
||||
|
||||
<tr><td>Owner</td><td>Member</td><td>ownershipRevoked + membershipGranted</td></tr>
|
||||
<tr><td>Owner</td><td>None</td><td>ownershipRevoked</td></tr>
|
||||
<tr><td>Admin</td><td>None</td><td>adminRevoked</td></tr>
|
||||
<tr><td><i>Anyone</i></td><td>Outcast</td><td>banned</td></tr>
|
||||
</table></p>
|
||||
|
||||
<b>Examples</b><p>
|
||||
|
||||
In this example we can see how to grant admin privileges to a user and listen for the notification events: <br>
|
||||
<blockquote>
|
||||
<pre> <font color="#3f7f5f">// User1 creates a room</font>
|
||||
muc = new MultiUserChat(conn1, <font color="#0000FF">"myroom@conference.jabber.org"</font>);
|
||||
muc.create(<font color="#0000FF">"testbot"</font>);
|
||||
|
||||
<font color="#3f7f5f">// User1 (which is the room owner) configures the room as a moderated room</font>
|
||||
Form form = muc.getConfigurationForm();
|
||||
Form answerForm = form.createAnswerForm();
|
||||
answerForm.setAnswer(<font color="#0000FF">"muc#roomconfig_moderatedroom"</font>, <font color="#0000FF">"1"</font>);
|
||||
muc.sendConfigurationForm(answerForm);
|
||||
|
||||
<font color="#3f7f5f">// User2 joins the new room (as a visitor)</font>
|
||||
MultiUserChat muc2 = new MultiUserChat(conn2, <font color="#0000FF">"myroom@conference.jabber.org"</font>);
|
||||
muc2.join(<font color="#0000FF">"testbot2"</font>);
|
||||
<font color="#3f7f5f">// User2 will listen for his own admin privileges</font>
|
||||
muc2.addUserStatusListener(new DefaultUserStatusListener() {
|
||||
public void membershipRevoked() {
|
||||
super.membershipRevoked();
|
||||
...
|
||||
}
|
||||
public void adminGranted() {
|
||||
super.adminGranted();
|
||||
...
|
||||
}
|
||||
});
|
||||
|
||||
<font color="#3f7f5f">// User3 joins the new room (as a visitor)</font>
|
||||
MultiUserChat muc3 = new MultiUserChat(conn3, <font color="#0000FF">"myroom@conference.jabber.org"</font>);
|
||||
muc3.join(<font color="#0000FF">"testbot3"</font>);
|
||||
<font color="#3f7f5f">// User3 will lister for other users admin privileges</font>
|
||||
muc3.addParticipantStatusListener(new DefaultParticipantStatusListener() {
|
||||
public void membershipRevoked(String participant) {
|
||||
super.membershipRevoked(participant);
|
||||
...
|
||||
}
|
||||
public void adminGranted(String participant) {
|
||||
super.adminGranted(participant);
|
||||
...
|
||||
}
|
||||
});
|
||||
|
||||
<font color="#3f7f5f">// The room's owner grants admin privileges to user2</font>
|
||||
muc.grantAdmin(<font color="#0000FF">"user2@jabber.org"</font>);
|
||||
</pre>
|
||||
</blockquote>
|
||||
</body>
|
||||
|
||||
</html>
|
30
CopyOftrunk/documentation/extensions/privatedata.html
Normal file
|
@ -0,0 +1,30 @@
|
|||
<html>
|
||||
<head>
|
||||
<title>Private Data</title>
|
||||
<link rel="stylesheet" type="text/css" href="style.css" />
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<div class="header">Private Data</div><p>
|
||||
|
||||
Manages private data, which is a mechanism to allow users to store arbitrary XML
|
||||
data on an XMPP server. Each private data chunk is defined by a element name and
|
||||
XML namespace. Example private data:
|
||||
|
||||
<pre>
|
||||
<color xmlns="http://example.com/xmpp/color">
|
||||
<favorite>blue</blue>
|
||||
<leastFavorite>puce</leastFavorite>
|
||||
</color>
|
||||
</pre><p>
|
||||
|
||||
<b>JEP related:</b> <a href="http://www.jabber.org/jeps/jep-0049.html">JEP-49</a>
|
||||
|
||||
<hr>
|
||||
|
||||
<em>More coming soon.</em>
|
||||
|
||||
</body>
|
||||
|
||||
</html>
|
179
CopyOftrunk/documentation/extensions/rosterexchange.html
Normal file
|
@ -0,0 +1,179 @@
|
|||
<html>
|
||||
<head>
|
||||
<title>Roster Item Exchange</title>
|
||||
<link rel="stylesheet" type="text/css" href="style.css" />
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<div class="header">Roster Item Exchange</div><p>
|
||||
This extension is used to send rosters, roster groups and roster entries from one XMPP
|
||||
Entity to another. It also provides an easy way to hook up custom logic when entries
|
||||
are received from other XMPP clients.
|
||||
<p>Follow these links to learn how to send and receive roster items:</p>
|
||||
<ul>
|
||||
<li><a href="#riesendroster">Send a complete roster</a></li>
|
||||
<li><a href="#riesendgroup">Send a roster's group</a></li>
|
||||
<li><a href="#riesendentry">Send a roster's entry</a></li>
|
||||
<li><a href="#riercventry">Receive roster entries</a></li>
|
||||
</ul>
|
||||
<b>JEP related:</b> <a href="http://www.jabber.org/jeps/jep-0093.html">JEP-93</a>
|
||||
|
||||
<hr>
|
||||
|
||||
<div class="subheader"><a name="riesendroster">Send a entire roster</a></div><p>
|
||||
|
||||
<b>Description</b><p>
|
||||
|
||||
Sometimes it is useful to send a whole roster to another user. Smack provides a
|
||||
very easy way to send a complete roster to another XMPP client.</p>
|
||||
|
||||
<b>Usage</b><p>
|
||||
|
||||
Create an instance of <i><b>RosterExchangeManager</b></i> and use the <b>#send(Roster, String)</b>
|
||||
message to send a roster to a given user. The first parameter is the roster to send and
|
||||
the second parameter is the id of the user that will receive the roster entries.</p>
|
||||
|
||||
<b>Example</b><p>
|
||||
|
||||
In this example we can see how user1 sends his roster to user2.
|
||||
<blockquote>
|
||||
<pre> <font color="#3f7f5f">// Connect to the server and log in</font>
|
||||
conn1 = new XMPPConnection(host);
|
||||
conn1.login(server_user1, pass1);
|
||||
|
||||
<font color="#3f7f5f">// Create a new roster exchange manager on conn1</font>
|
||||
RosterExchangeManager rosterExchangeManager = new RosterExchangeManager(conn1);
|
||||
<font color="#3f7f5f">// Send user1's roster to user2</font>
|
||||
rosterExchangeManager.send(conn1.getRoster(), user2);
|
||||
</pre>
|
||||
</blockquote>
|
||||
|
||||
<hr>
|
||||
|
||||
<div class="subheader"><a name="riesendgroup">Send a roster group</a></div><p>
|
||||
|
||||
<b>Description</b><p>
|
||||
|
||||
It is also possible to send a roster group to another XMPP client. A roster group groups
|
||||
a set of roster entries under a name.</p>
|
||||
|
||||
<b>Usage</b><p>
|
||||
|
||||
Create an instance of <i><b>RosterExchangeManager</b></i> and use the <b>#send(RosterGroup, String)</b>
|
||||
message to send a roster group to a given user. The first parameter is the roster group to send and
|
||||
the second parameter is the id of the user that will receive the roster entries.</p>
|
||||
|
||||
<b>Example</b><p>
|
||||
|
||||
In this example we can see how user1 sends his roster groups to user2.
|
||||
<blockquote>
|
||||
<pre> <font color="#3f7f5f">// Connect to the server and log in</font>
|
||||
conn1 = new XMPPConnection(host);
|
||||
conn1.login(server_user1, pass1);
|
||||
|
||||
<font color="#3f7f5f">// Create a new roster exchange manager on conn1</font>
|
||||
RosterExchangeManager rosterExchangeManager = new RosterExchangeManager(conn1);
|
||||
<font color="#3f7f5f">// Send user1's RosterGroups to user2</font>
|
||||
for (Iterator it = conn1.getRoster().getGroups(); it.hasNext(); )
|
||||
rosterExchangeManager.send((RosterGroup)it.next(), user2);
|
||||
</pre>
|
||||
</blockquote>
|
||||
|
||||
<hr>
|
||||
|
||||
<div class="subheader"><a name="riesendentry">Send a roster entry</a></div><p>
|
||||
|
||||
<b>Description</b><p>
|
||||
|
||||
Sometimes you may need to send a single roster entry to another XMPP client. Smack also lets you send
|
||||
items at this granularity level.</p>
|
||||
|
||||
<b>Usage</b><p>
|
||||
|
||||
Create an instance of <i><b>RosterExchangeManager</b></i> and use the <b>#send(RosterEntry, String)</b>
|
||||
message to send a roster entry to a given user. The first parameter is the roster entry to send and
|
||||
the second parameter is the id of the user that will receive the roster entries.</p>
|
||||
|
||||
<b>Example</b><p>
|
||||
|
||||
In this example we can see how user1 sends a roster entry to user2.
|
||||
<blockquote>
|
||||
<pre> <font color="#3f7f5f">// Connect to the server and log in</font>
|
||||
conn1 = new XMPPConnection(host);
|
||||
conn1.login(server_user1, pass1);
|
||||
|
||||
<font color="#3f7f5f">// Create a new roster exchange manager on conn1</font>
|
||||
RosterExchangeManager rosterExchangeManager = new RosterExchangeManager(conn1);
|
||||
<font color="#3f7f5f">// Send a roster entry (any) to user2</font>
|
||||
rosterExchangeManager1.send((RosterEntry)conn1.getRoster().getEntries().next(), user2);
|
||||
</pre>
|
||||
</blockquote>
|
||||
|
||||
<hr>
|
||||
|
||||
<div class="subheader"><a name="riercventry">Receive roster entries</a></div><p>
|
||||
|
||||
<b>Description</b><p>
|
||||
|
||||
Since roster items are sent between XMPP clients, it is necessary to listen to possible roster entries
|
||||
receptions. Smack provides a mechanism that you can use to execute custom logic when roster entries are
|
||||
received.</p>
|
||||
|
||||
<b>Usage</b><p>
|
||||
|
||||
<ol>
|
||||
<li>Create a class that implements the <i><b>RosterExchangeListener</b></i> interface.</li>
|
||||
<li>Implement the method <b>entriesReceived(String, Iterator)</b> that will be called when new entries
|
||||
are received with custom logic.</li>
|
||||
<li>Add the listener to the <i>RosterExchangeManager</i> that works on the desired <i>XMPPConnection</i>.</li>
|
||||
</ol></p>
|
||||
|
||||
<b>Example</b><p>
|
||||
|
||||
In this example we can see how user1 sends a roster entry to user2 and user2 adds the received
|
||||
entries to his roster.
|
||||
<blockquote>
|
||||
<pre> <font color="#3f7f5f">// Connect to the server and log in the users</font>
|
||||
conn1 = new XMPPConnection(host);
|
||||
conn1.login(server_user1, pass1);
|
||||
conn2 = new XMPPConnection(host);
|
||||
conn2.login(server_user2, pass2);
|
||||
final Roster user2_roster = conn2.getRoster();
|
||||
|
||||
<font color="#3f7f5f">// Create a RosterExchangeManager that will help user2 to listen and accept
|
||||
the entries received</font>
|
||||
RosterExchangeManager rosterExchangeManager2 = new RosterExchangeManager(conn2);
|
||||
<font color="#3f7f5f">// Create a RosterExchangeListener that will iterate over the received roster entries</font>
|
||||
RosterExchangeListener rosterExchangeListener = new RosterExchangeListener() {
|
||||
public void entriesReceived(String from, Iterator remoteRosterEntries) {
|
||||
while (remoteRosterEntries.hasNext()) {
|
||||
try {
|
||||
<font color="#3f7f5f">// Get the received entry</font>
|
||||
RemoteRosterEntry remoteRosterEntry = (RemoteRosterEntry) remoteRosterEntries.next();
|
||||
<font color="#3f7f5f">// Display the remote entry on the console</font>
|
||||
System.out.println(remoteRosterEntry);
|
||||
<font color="#3f7f5f">// Add the entry to the user2's roster</font>
|
||||
user2_roster.createEntry(
|
||||
remoteRosterEntry.getUser(),
|
||||
remoteRosterEntry.getName(),
|
||||
remoteRosterEntry.getGroupArrayNames());
|
||||
}
|
||||
catch (XMPPException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
<font color="#3f7f5f">// Add the RosterExchangeListener to the RosterExchangeManager that user2 is using</font>
|
||||
rosterExchangeManager2.addRosterListener(rosterExchangeListener);
|
||||
|
||||
<font color="#3f7f5f">// Create a RosterExchangeManager that will help user1 to send his roster</font>
|
||||
RosterExchangeManager rosterExchangeManager1 = new RosterExchangeManager(conn1);
|
||||
<font color="#3f7f5f">// Send user1's roster to user2</font>
|
||||
rosterExchangeManager1.send(conn1.getRoster(), user2);
|
||||
</pre>
|
||||
</blockquote>
|
||||
</body>
|
||||
|
||||
</html>
|
57
CopyOftrunk/documentation/extensions/style.css
Normal file
|
@ -0,0 +1,57 @@
|
|||
BODY {
|
||||
font-size : 100%;
|
||||
background-color : #fff;
|
||||
}
|
||||
BODY, TD, TH {
|
||||
font-family : tahoma, arial, helvetica;
|
||||
font-size : 0.8em;
|
||||
}
|
||||
PRE, TT, CODE {
|
||||
font-family : courier new, monospaced;
|
||||
font-size : 1.0em;
|
||||
}
|
||||
A:hover {
|
||||
text-decoration : none;
|
||||
}
|
||||
LI {
|
||||
padding-bottom : 4px;
|
||||
}
|
||||
.header {
|
||||
font-size : 1.4em;
|
||||
font-weight : bold;
|
||||
width : 100%;
|
||||
border-bottom : 1px #ccc solid;
|
||||
padding-bottom : 2px;
|
||||
}
|
||||
.subheader {
|
||||
font-size: 1.1em;
|
||||
font-weight : bold;
|
||||
}
|
||||
.footer {
|
||||
font-size : 0.8em;
|
||||
color : #999;
|
||||
text-align : center;
|
||||
width : 100%;
|
||||
border-top : 1px #ccc solid;
|
||||
padding-top : 2px;
|
||||
}
|
||||
.code {
|
||||
border : 1px #ccc solid;
|
||||
padding : 0em 1.0em 0em 1.0em;
|
||||
margin : 4px 0px 4px 0px;
|
||||
}
|
||||
.nav, .nav A {
|
||||
font-family : verdana;
|
||||
font-size : 0.85em;
|
||||
color : #600;
|
||||
text-decoration : none;
|
||||
font-weight : bold;
|
||||
}
|
||||
.nav {
|
||||
width : 100%;
|
||||
border-bottom : 1px #ccc solid;
|
||||
padding : 3px 3px 5px 1px;
|
||||
}
|
||||
.nav A:hover {
|
||||
text-decoration : underline;
|
||||
}
|
22
CopyOftrunk/documentation/extensions/time.html
Normal file
|
@ -0,0 +1,22 @@
|
|||
<html>
|
||||
<head>
|
||||
<title>Time</title>
|
||||
<link rel="stylesheet" type="text/css" href="style.css" />
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<div class="header">Entity Time Exchange</div><p>
|
||||
|
||||
Supports a protocol that XMPP clients use to exchange their respective local
|
||||
times and time zones.<p>
|
||||
|
||||
<b>JEP related:</b> <a href="http://www.jabber.org/jeps/jep-0090.html">JEP-90</a>
|
||||
|
||||
<hr>
|
||||
|
||||
<em>More coming soon.</em>
|
||||
|
||||
</body>
|
||||
|
||||
</html>
|
26
CopyOftrunk/documentation/extensions/toc.html
Normal file
|
@ -0,0 +1,26 @@
|
|||
<html>
|
||||
<head>
|
||||
<title>Smack Extensions User Manual</title>
|
||||
<link rel="stylesheet" type="text/css" href="style.css" />
|
||||
<base target="mainFrame">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<a href="intro.html">Introduction</a><p>
|
||||
|
||||
<div class="subheader">Smack Extensions</div><p>
|
||||
|
||||
<a href="privatedata.html">Private Data</a><br>
|
||||
<a href="xhtml.html">XHTML Messages</a><br>
|
||||
<a href="messageevents.html">Message Events</a><br>
|
||||
<a href="dataforms.html">Data Forms</a><br>
|
||||
<a href="muc.html">Multi User Chat</a><br>
|
||||
<a href="rosterexchange.html">Roster Item Exchange</a><br>
|
||||
<a href="time.html">Time Exchange</a><br>
|
||||
<a href="invitation.html">Group Chat Invitations</a><br>
|
||||
<a href="disco.html">Service Discovery</a><br>
|
||||
</p>
|
||||
|
||||
</body>
|
||||
</html>
|
200
CopyOftrunk/documentation/extensions/xhtml.html
Normal file
|
@ -0,0 +1,200 @@
|
|||
<html>
|
||||
<head>
|
||||
<title>XHTML Support</title>
|
||||
<link rel="stylesheet" type="text/css" href="style.css" />
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<div class="header">XHTML Messages</div><p>
|
||||
|
||||
Provides the ability to send and receive formatted messages using XHTML.
|
||||
|
||||
<p>Follow these links to learn how to compose, send, receive and discover support for
|
||||
XHTML messages:</p>
|
||||
<ul>
|
||||
<li><a href="#xhtmlcompose">Compose an XHTML Message</a></li>
|
||||
<li><a href="#xhtmlsend">Send an XHTML Message</a></li>
|
||||
<li><a href="#xhtmlreceive">Receive an XHTML Message</a></li>
|
||||
<li><a href="#xhtmldiscover">Discover support for XHTML Messages</a></li>
|
||||
</ul>
|
||||
<b>JEP related:</b> <a href="http://www.jabber.org/jeps/jep-0071.html">JEP-71</a>
|
||||
|
||||
<hr>
|
||||
|
||||
<div class="subheader"><a name="xhtmlcompose">Compose an XHTML Message</a></div><p>
|
||||
|
||||
<b>Description</b><p>
|
||||
|
||||
The first step in order to send an XHTML message is to compose it. Smack provides a special
|
||||
class that helps to build valid XHTML messages hiding any low level complexity.
|
||||
For special situations, advanced users may decide not to use the helper class and generate
|
||||
the XHTML by themselves. Even for these situations Smack provides a well defined entry point
|
||||
in order to add the generated XHTML content to a given message.</p>
|
||||
|
||||
<p>
|
||||
Note: not all clients are able to view XHTML formatted messages. Therefore,
|
||||
it's recommended that you include a normal body in that message that is either an
|
||||
unformatted version of the text or a note that XHTML support is required
|
||||
to view the message contents.</p>
|
||||
|
||||
<b>Usage</b><p>
|
||||
|
||||
Create an instance of <i><b>XHTMLText</b></i> specifying the style and language of the body.
|
||||
You can add several XHTML bodies to the message but each body should be for a different language.
|
||||
Once you have an XHTMLText you can start to append tags and text to it. In order to append tags there
|
||||
are several messages that you can use. For each XHTML defined tag there is a message that you can send.
|
||||
In order to add text you can send the message <b>#append(String textToAppend)</b>.</p>
|
||||
|
||||
<p>After you have configured the XHTML text, the last step you have to do is to add the XHTML text
|
||||
to the message you want to send. If you decided to create the XHTML text by yourself, you will have to
|
||||
follow this last step too. In order to add the XHTML text to the message send the message
|
||||
<b>#addBody(Message message, String body)</b> to the <i><b>XHTMLManager</b></i> class where <i>message</i>
|
||||
is the message that will receive the XHTML body and <i>body</i> is the string to add as an XHTML body to
|
||||
the message.</b></p>
|
||||
|
||||
<b>Example</b><p>
|
||||
|
||||
In this example we can see how to compose the following XHTML message: <br>
|
||||
<font color="#0000FF"><body><p style='font-size:large'>Hey John, this is my new <span
|
||||
style='color:green'>green</span><em>!!!!</em></p></body></font>
|
||||
<blockquote>
|
||||
<pre> <font color="#3f7f5f">// Create a message to send</font>
|
||||
Message msg = chat.createMessage();
|
||||
msg.setSubject(<font color="#0000FF">"Any subject you want"</font>);
|
||||
msg.setBody(<font color="#0000FF">"Hey John, this is my new green!!!!"</font>);
|
||||
|
||||
<font color="#3f7f5f">// Create an XHTMLText to send with the message</font>
|
||||
XHTMLText xhtmlText = new XHTMLText(null, null);
|
||||
xhtmlText.appendOpenParagraphTag(<font color="#0000FF">"font-size:large"</font>);
|
||||
xhtmlText.append(<font color="#0000FF">"Hey John, this is my new "</font>);
|
||||
xhtmlText.appendOpenSpanTag(<font color="#0000FF">"color:green"</font>);
|
||||
xhtmlText.append(<font color="#0000FF">"green"</font>);
|
||||
xhtmlText.appendCloseSpanTag();
|
||||
xhtmlText.appendOpenEmTag();
|
||||
xhtmlText.append(<font color="#0000FF">"!!!!"</font>);
|
||||
xhtmlText.appendCloseEmTag();
|
||||
xhtmlText.appendCloseParagraphTag();
|
||||
|
||||
<font color="#3f7f5f">// Add the XHTML text to the message</font>
|
||||
XHTMLManager.addBody(msg, xhtmlText.toString());
|
||||
|
||||
</pre>
|
||||
</blockquote>
|
||||
|
||||
<hr>
|
||||
|
||||
<div class="subheader"><a name="xhtmlsend">Send an XHTML Message</a></div><p>
|
||||
|
||||
<b>Description</b><p>
|
||||
|
||||
After you have composed an XHTML message you will want to send it. Once you have added
|
||||
the XHTML content to the message you want to send you are almost done. The last step is to send
|
||||
the message as you do with any other message.</p>
|
||||
|
||||
<b>Usage</b><p>
|
||||
|
||||
An XHTML message is like any regular message, therefore to send the message you can follow
|
||||
the usual steps you do in order to send a message. For example, to send a message as part
|
||||
of a chat just use the message <b>#send(Message)</b> of <i><b>Chat</b></i> or you can use
|
||||
the message <b>#send(Packet)</b> of <i><b>XMPPConnection</b></i>.</p>
|
||||
|
||||
<b>Example</b><p>
|
||||
|
||||
In this example we can see how to send a message with XHTML content as part of a chat.
|
||||
<blockquote>
|
||||
<pre> <font color="#3f7f5f">// Create a message to send</font>
|
||||
Message msg = chat.createMessage();
|
||||
<font color="#3f7f5f">// Obtain the XHTML text to send from somewhere</font>
|
||||
String xhtmlBody = getXHTMLTextToSend();
|
||||
|
||||
<font color="#3f7f5f">// Add the XHTML text to the message</font>
|
||||
XHTMLManager.addBody(msg, xhtmlBody);
|
||||
|
||||
<font color="#3f7f5f">// Send the message that contains the XHTML</font>
|
||||
chat.sendMessage(msg);
|
||||
</pre>
|
||||
</blockquote>
|
||||
|
||||
<hr>
|
||||
|
||||
<div class="subheader"><a name="xhtmlreceive">Receive an XHTML Message</a></div><p>
|
||||
|
||||
<b>Description</b><p>
|
||||
|
||||
It is also possible to obtain the XHTML content from a received message. Remember
|
||||
that the specification defines that a message may contain several XHTML bodies
|
||||
where each body should be for a different language.</p>
|
||||
|
||||
<b>Usage</b><p>
|
||||
|
||||
To get the XHTML bodies of a given message just send the message <b>#getBodies(Message)</b>
|
||||
to the class <i><b>XHTMLManager</b></i>. The answer of this message will be an
|
||||
<i><b>Iterator</b></i> with the different XHTML bodies of the message or null if none.</p>
|
||||
|
||||
<b>Example</b><p>
|
||||
|
||||
In this example we can see how to create a PacketListener that obtains the XHTML bodies of any received message.
|
||||
<blockquote>
|
||||
<pre> <font color="#3f7f5f">// Create a listener for the chat and display any XHTML content</font>
|
||||
PacketListener packetListener = new PacketListener() {
|
||||
public void processPacket(Packet packet) {
|
||||
Message message = (Message) packet;
|
||||
<font color="#3f7f5f">// Obtain the XHTML bodies of the message</font>
|
||||
Iterator it = XHTMLManager.getBodies(message);
|
||||
if (it != null) {
|
||||
<font color="#3f7f5f">// Display the bodies on the console</font>
|
||||
while (it.hasNext()) {
|
||||
String body = (String) it.next();
|
||||
System.out.println(body);
|
||||
}
|
||||
}
|
||||
};
|
||||
chat.addMessageListener(packetListener);
|
||||
|
||||
</pre>
|
||||
</blockquote>
|
||||
|
||||
<hr>
|
||||
|
||||
<div class="subheader"><a name="xhtmldiscover">Discover support for XHTML Messages</a></div><p>
|
||||
|
||||
<b>Description</b><p>
|
||||
|
||||
Before you start to send XHTML messages to a user you should discover if the user supports XHTML messages.
|
||||
There are two ways to achieve the discovery, explicitly and implicitly. Explicit is when you first try
|
||||
to discover if the user supports XHTML before sending any XHTML message. Implicit is when you send
|
||||
XHTML messages without first discovering if the conversation partner's client supports XHTML and depenging on
|
||||
the answer (normal message or XHTML message) you find out if the user supports XHTML messages or not. This
|
||||
section explains how to explicitly discover for XHTML support.</p>
|
||||
|
||||
<b>Usage</b><p>
|
||||
|
||||
In order to discover if a remote user supports XHTML messages send <b>#isServiceEnabled(XMPPConnection
|
||||
connection, String userID)</b> to the class <i><b>XHTMLManager</b></i> where connection is the connection
|
||||
to use to perform the service discovery and userID is the user to check (A fully qualified xmpp ID,
|
||||
e.g. jdoe@example.com). This message will return true if the specified user handles XHTML messages.</p>
|
||||
|
||||
<b>Example</b><p>
|
||||
|
||||
In this example we can see how to discover if a remote user supports XHTML Messages.
|
||||
<blockquote>
|
||||
<pre> Message msg = chat.createMessage();
|
||||
<font color="#3f7f5f">// Include a normal body in the message</font>
|
||||
msg.setBody(getTextToSend());
|
||||
<font color="#3f7f5f">// Check if the other user supports XHTML messages</font>
|
||||
if (XHTMLManager.isServiceEnabled(connection, chat.getParticipant())) {
|
||||
<font color="#3f7f5f">// Obtain the XHTML text to send from somewhere</font>
|
||||
String xhtmlBody = getXHTMLTextToSend();
|
||||
|
||||
<font color="#3f7f5f">// Include an XHTML body in the message</font>
|
||||
XHTMLManager.addBody(msg, xhtmlBody);
|
||||
}
|
||||
|
||||
<font color="#3f7f5f">// Send the message</font>
|
||||
chat.sendMessage(msg);
|
||||
</pre>
|
||||
</blockquote>
|
||||
</body>
|
||||
|
||||
</html>
|
109
CopyOftrunk/documentation/gettingstarted.html
Normal file
|
@ -0,0 +1,109 @@
|
|||
<html>
|
||||
<head>
|
||||
<title>Smack: Getting Started - Jive Software</title>
|
||||
<link rel="stylesheet" type="text/css" href="style.css" /
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<div class="header">
|
||||
Getting Started With Smack
|
||||
</div>
|
||||
|
||||
<div class="nav">
|
||||
« <a href="index.html">Table of Contents</a>
|
||||
</div>
|
||||
|
||||
<p>
|
||||
This document will introduce you to the Smack API and provide an overview of
|
||||
important classes and concepts.
|
||||
</p>
|
||||
|
||||
<p class="subheader">
|
||||
Requirements
|
||||
</p>
|
||||
|
||||
The only requirement for Smack is JDK 1.2 or later<sup>
|
||||
<a style="text-decoration:none;" href="#ssenote">1</a></sup>.
|
||||
An XML parser is embedded in the smack.jar file and no other third party
|
||||
libraries are required.<p>
|
||||
|
||||
<sup>1</sup> <font size="-1"><i>JDK 1.2 and 1.3 users that wish to use SSL connections must have the
|
||||
<a href="http://java.sun.com/products/jsse/index-103.html">JSSE</a> library in their classpath.</i></font>
|
||||
|
||||
<p class="subheader">
|
||||
Establishing a Connection
|
||||
</p>
|
||||
|
||||
The <tt>XMPPConnection</tt> class is used to create a connection to an
|
||||
XMPP server. To create an SSL connection, use the SSLXMPPConnection class.
|
||||
Below are code examples for making a connection:<p>
|
||||
|
||||
<div class="code">
|
||||
<pre>
|
||||
<font color="gray"><i>// Create a connection to the jabber.org server.</i></font>
|
||||
XMPPConnection conn1 = <font color="navy"><b>new</b></font> XMPPConnection(<font color="green">"jabber.org"</font>);
|
||||
|
||||
<font color="gray"><i>// Create a connection to the jabber.org server on a specific port.</i></font>
|
||||
XMPPConnection conn2 = <font color="navy"><b>new</b></font> XMPPConnection(<font color="green">"jabber.org"</font>, 5222);
|
||||
|
||||
<font color="gray"><i>// Create an SSL connection to jabber.org.</i></font>
|
||||
XMPPConnection connection = <font color="navy"><b>new</b></font> SSLXMPPConnection(<font color="green">"jabber.org"</font>);
|
||||
</pre></div>
|
||||
|
||||
<p>Once you've created a connection, you should login using a username and password
|
||||
with the <tt>XMPPConnection.login(String username, String password)</tt> method.
|
||||
Once you've logged in, you can being chatting with other users by creating
|
||||
new <tt>Chat</tt> or <tt>GroupChat</tt> objects.
|
||||
|
||||
<p class="subheader">
|
||||
Working with the Roster
|
||||
</p>
|
||||
The roster lets you keep track of the availability (presence) of other users. Users
|
||||
can be organized into groups such as "Friends" and "Co-workers", and then you
|
||||
discover whether each user is online or offline.<p>
|
||||
|
||||
Retrieve the roster using the <tt>XMPPConnection.getRoster()</tt> method. The roster
|
||||
class allows you to find all the roster entries, the groups they belong to, and the
|
||||
current presence status of each entry.
|
||||
|
||||
<p class="subheader">
|
||||
Reading and Writing Packets
|
||||
</p>
|
||||
|
||||
Each message to the XMPP server from a client is called a packet and is
|
||||
sent as XML. The <tt>org.jivesoftware.smack.packet</tt> package contains
|
||||
classes that encapsulate the three different basic packet types allowed by
|
||||
XMPP (message, presence, and IQ). Classes such as <tt>Chat</tt> and <tt>GroupChat</tt>
|
||||
provide higher-level constructs that manage creating and sending packets
|
||||
automatically, but you can also create and send packets directly. Below
|
||||
is a code example for changing your presence to let people know you're unavailable
|
||||
and "out fishing":<p>
|
||||
|
||||
<div class="code">
|
||||
<pre>
|
||||
<font color="gray"><i>// Create a new presence. Pass in false to indicate we're unavailable.</i></font>
|
||||
Presence presence = new Presence(Presence.Type.UNAVAILABLE);
|
||||
presence.setStatus(<font color="green">"Gone fishing"</font>);
|
||||
<font color="gray"><i>// Send the packet (assume we have a XMPPConnection instance called "con").</i></font>
|
||||
con.sendPacket(presence);
|
||||
</pre></div>
|
||||
<p>
|
||||
|
||||
Smack provides two ways to read incoming packets: <tt>PacketListener</tt>, and
|
||||
<tt>PacketCollector</tt>. Both use <tt>PacketFilter</tt> instances to determine
|
||||
which packets should be processed. A packet listener is used for event style programming,
|
||||
while a packet collector has a result queue of packets that you can do
|
||||
polling and blocking operations on. So, a packet listener is useful when
|
||||
you want to take some action whenever a packet happens to come in, while a
|
||||
packet collector is useful when you want to wait for a specific packet
|
||||
to arrive. Packet collectors and listeners can be created using an
|
||||
XMPPConnection instance.
|
||||
|
||||
|
||||
<p><div class="footer">
|
||||
Copyright © Jive Software 2002-2005
|
||||
</div>
|
||||
|
||||
</body>
|
||||
</html>
|
BIN
CopyOftrunk/documentation/images/debugwindow.gif
Normal file
After Width: | Height: | Size: 15 KiB |
BIN
CopyOftrunk/documentation/images/enhanceddebugger.png
Normal file
After Width: | Height: | Size: 33 KiB |
BIN
CopyOftrunk/documentation/images/roster.png
Normal file
After Width: | Height: | Size: 18 KiB |
BIN
CopyOftrunk/documentation/images/smacklogo.png
Normal file
After Width: | Height: | Size: 4.4 KiB |
37
CopyOftrunk/documentation/index.html
Normal file
|
@ -0,0 +1,37 @@
|
|||
<html>
|
||||
<head>
|
||||
<title>Smack Documentation - Jive Software</title>
|
||||
<link rel="stylesheet" type="text/css" href="style.css" />
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<table border="0"><tr><td>
|
||||
<img src="images/smacklogo.png" width="100" height="100" alt="Smack" border="0" hspace="10">
|
||||
</td><td>
|
||||
<font size="4"><b>Smack Documentation</b></font>
|
||||
</div></td></tr></table>
|
||||
|
||||
<p>
|
||||
<strong>Contents:</strong>
|
||||
</p>
|
||||
|
||||
<ul>
|
||||
<li><a href="overview.html">Overview</a>
|
||||
<li><a href="gettingstarted.html">Getting Started Guide</a>
|
||||
<li><a href="messaging.html">Messaging Basics</a>
|
||||
<li><a href="roster.html">Roster and Presence</a>
|
||||
<li><a href="processing.html">Processing Incoming Packets</a>
|
||||
<li><a href="providers.html">Provider Architecture</a>
|
||||
<li><a href="properties.html">Packet Properties</a>
|
||||
<li><a href="debugging.html">Debugging with Smack</a>
|
||||
<p>
|
||||
<li><a href="extensions/index.html">Smack Extensions Manual</a>
|
||||
</ul>
|
||||
|
||||
<div class="footer">
|
||||
Copyright © Jive Software 2002-2005
|
||||
</div>
|
||||
|
||||
</body>
|
||||
</html>
|
108
CopyOftrunk/documentation/messaging.html
Normal file
|
@ -0,0 +1,108 @@
|
|||
<html>
|
||||
<head>
|
||||
<title>Smack: Chat - Jive Software</title>
|
||||
<link rel="stylesheet" type="text/css" href="style.css" />
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<div class="header">
|
||||
Messaging using Chat and GroupChat
|
||||
</div>
|
||||
|
||||
<div class="nav">
|
||||
« <a href="index.html">Table of Contents</a>
|
||||
</div>
|
||||
|
||||
<p>
|
||||
Sending messages back and forth is at the core of instant messaging. Two classes
|
||||
aid in sending and receiving messages:
|
||||
<ul>
|
||||
<li> <tt>org.jivesoftware.smack.Chat</tt> -- used to send messages between two people.
|
||||
<li> <tt>org.jivesoftware.smack.GroupChat</tt> -- used to join a chat room to send messages between many people.
|
||||
</ul>
|
||||
|
||||
Both the Chat and GroupChat classes use the <tt>org.jivesoftware.smack.packet.Message</tt> packet
|
||||
class to send messages. In certain circumstances, you may wish to bypass the higher-level
|
||||
Chat and GroupChat classes to send and listen for messages directly.
|
||||
</p>
|
||||
|
||||
<p class="subheader">
|
||||
Chat
|
||||
</p>
|
||||
|
||||
A chat creates a new thread of messages (using a thread ID) between two users. The
|
||||
following code snippet demonstrates how to create a new Chat with a user and then send
|
||||
them a text message:<p>
|
||||
|
||||
<div class="code"><pre>
|
||||
<font color="gray"><i>// Assume we've created an XMPPConnection name "connection".</i></font>
|
||||
Chat newChat = connection.createChat(<font color="green">"jsmith@jivesoftware.com"</font>);
|
||||
newChat.sendMessage(<font color="green">"Howdy!"</font>);
|
||||
</pre></div><p>
|
||||
|
||||
The <tt>Chat.sendMessage(String)</tt> method is a convenience method that creates a Message
|
||||
object, sets the body using the String parameter, then sends the message. In the case
|
||||
that you wish to set additional values on a Message before sending it, use the
|
||||
<tt>Chat.createMessage()</tt> and <tt>Chat.sendMessage(Message)</tt> methods, as in the
|
||||
following code snippet:<p>
|
||||
|
||||
<div class="code"><pre>
|
||||
<font color="gray"><i>// Assume we've created an XMPPConnection name "connection".</i></font>
|
||||
Chat newChat = connection.createChat(<font color="green">"jsmith@jivesoftware.com"</font>);
|
||||
Message newMessage = newChat.createMessage();
|
||||
newMessage.setBody(<font color="green">"Howdy!"</font>);
|
||||
message.setProperty(<font color="green">"favoriteColor"</font>, <font color="green">"red"</font>);
|
||||
newChat.sendMessage(newMessage);
|
||||
</pre></div><p>
|
||||
|
||||
The Chat object allows you to easily listen for replies from the other chat participant.
|
||||
The following code snippet is a parrot-bot -- it echoes back everything the other user types.<p>
|
||||
|
||||
<div class="code"><pre>
|
||||
<font color="gray"><i>// Assume we've created an XMPPConnection name "connection".</i></font>
|
||||
Chat newChat = connection.createChat(<font color="green">"jsmith@jivesoftware.com"</font>);
|
||||
newMessage.setBody(<font color="green">"Hi, I'm an annoying parrot-bot! Type something back to me."</font>);
|
||||
<b>while</b> (<b>true</b>) {
|
||||
<font color="gray"><i>// Wait for the next message the user types to us.</i></font>
|
||||
Message message = newChat.nextMessage();
|
||||
<font color="gray"><i>// Send back the same text the other user sent us.</i></font>
|
||||
newChat.sendMessage(message.getBody());
|
||||
}
|
||||
</pre></div><p>
|
||||
|
||||
The code above uses the <tt>Chat.nextMessage()</tt> method to get the next message, which
|
||||
will wait indefinitely until another message comes in. There are other methods to wait
|
||||
a specific amount of time for a new message, or you can add a listener that will be notified
|
||||
every time a new message arrives.
|
||||
|
||||
<p class="subheader">
|
||||
GroupChat
|
||||
</p>
|
||||
|
||||
A group chat connects to a chat room on a server and allows you to send and receive messages
|
||||
from a group of people. Before you can send or receive messages, you must join the room using
|
||||
a nickname. The following code snippet connects to a chat room and sends a
|
||||
message.<p>
|
||||
|
||||
<div class="code"><pre>
|
||||
<font color="gray"><i>// Assume we've created an XMPPConnection name "connection".</i></font>
|
||||
GroupChat newGroupChat = connection.createGroupChat(<font color="green">"test@jivesoftware.com"</font>);
|
||||
<font color="gray"><i>// Join the group chat using the nickname "jsmith".</i></font>
|
||||
newGroupChat.join(<font color="green">"jsmith"</font>);
|
||||
<font color="gray"><i>// Send a message to all the other people in the chat room.</i></font>
|
||||
newGroupChat.sendMessage(<font color="green">"Howdy!"</font>);
|
||||
</pre></div><p>
|
||||
|
||||
In general, sending and receiving messages in a group chat works very similarly to
|
||||
the <tt>Chat</tt> class. Method are also provided to get the list of the other
|
||||
users in the room.<p>
|
||||
|
||||
<br clear="all" /><br><br>
|
||||
|
||||
<div class="footer">
|
||||
Copyright © Jive Software 2002-2005
|
||||
</div>
|
||||
|
||||
</body>
|
||||
</html>
|
72
CopyOftrunk/documentation/overview.html
Normal file
|
@ -0,0 +1,72 @@
|
|||
<html>
|
||||
<head>
|
||||
<title>Smack: Overview - Jive Software</title>
|
||||
<link rel="stylesheet" type="text/css" href="style.css" />
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<div class="header">
|
||||
Smack Overview
|
||||
</div>
|
||||
|
||||
<div class="nav">
|
||||
« <a href="index.html">Table of Contents</a>
|
||||
</div>
|
||||
|
||||
<p>
|
||||
|
||||
Smack is a library for communicating with XMPP servers to perform
|
||||
instant messaging and chat.<p>
|
||||
|
||||
<p class="subheader">
|
||||
Smack Key Advantages
|
||||
</p>
|
||||
|
||||
<ul>
|
||||
<li>Extremely simple to use, yet powerful API. Sending a text message to a user
|
||||
can be accomplished in three lines of code:
|
||||
|
||||
<div class="code"><pre>
|
||||
XMPPConnection connection = <font color="navy"><b>new</b></font> XMPPConnection(<font color="green">"jabber.org"</font>);
|
||||
connection.login(<font color="green">"mtucker"</font>, <font color="green">"password"</font>);
|
||||
connection.createChat(<font color="green">"jsmith@jivesoftware.com"</font>).sendMessage(<font color="green">"Howdy!"</font>);
|
||||
</pre></div>
|
||||
|
||||
|
||||
<li>Doesn't force you to code at the packet level, as other libraries do. Smack provides
|
||||
intelligent higher level constructs such as the <tt>Chat</tt> and <tt>GroupChat</tt>
|
||||
classes, which let you program more efficiently.
|
||||
|
||||
<li>Does not require that you're familiar with the XMPP XML format, or even that you're familiar with XML.
|
||||
|
||||
<li>Provides easy machine to machine communication. Smack lets you set any number of properties on
|
||||
each message, including properties that are Java objects.
|
||||
|
||||
<li>Open Source under the Apache License, which means you can incorporate Smack into your commercial or
|
||||
non-commercial applications.
|
||||
</ul>
|
||||
|
||||
<p class="subheader">
|
||||
About XMPP
|
||||
</p>
|
||||
|
||||
XMPP (eXtensible Messaging and Presence Protocol) is an open, XML based protocol
|
||||
making it's way through the IETF approval process under the guidance of the
|
||||
Jabber Software Foundation (<a href="http://www.jabber.org">http://www.jabber.org</a>).
|
||||
|
||||
<p class="subheader">
|
||||
How To Use This Documentation
|
||||
</p>
|
||||
|
||||
This documentation assumes that you're already familiar with the main features of XMPP
|
||||
instant messaging. It's also highly recommended that you open the Javadoc API guide and
|
||||
use that as a reference while reading through this documentation.
|
||||
|
||||
<br clear="all" /><br><br>
|
||||
<div class="footer">
|
||||
Copyright © Jive Software 2002-2005
|
||||
</div>
|
||||
|
||||
</body>
|
||||
</html>
|
87
CopyOftrunk/documentation/processing.html
Normal file
|
@ -0,0 +1,87 @@
|
|||
<html>
|
||||
<head>
|
||||
<title>Smack: Processing Incoming Packets - Jive Software</title>
|
||||
<link rel="stylesheet" type="text/css" href="style.css" />
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<div class="header">
|
||||
Processing Incoming Packets
|
||||
</div>
|
||||
|
||||
<div class="nav">
|
||||
« <a href="index.html">Table of Contents</a>
|
||||
</div>
|
||||
|
||||
<p>
|
||||
|
||||
Smack provides a flexible framework for processing incoming packets using two constructs:
|
||||
<ul>
|
||||
<li><tt>org.jivesoftware.smack.PacketCollector</tt> -- a class that lets you
|
||||
synchronously wait for new packets.
|
||||
<li><tt>org.jivesoftware.smack.PacketListener</tt> -- an interface for asynchronously
|
||||
notifying you of incoming packets.
|
||||
</ul>
|
||||
A packet listener is used for event style programming, while a packet collector has a
|
||||
result queue of packets that you can do polling and blocking operations on. So, a packet
|
||||
listener is useful when you want to take some action whenever a packet happens to come in,
|
||||
while a packet collector is useful when you want to wait for a specific packet to come
|
||||
arrive. Packet collectors and listeners can be created using an <tt>XMPPConnection</tt> instance.<p>
|
||||
|
||||
The <tt>org.jivesoftware.smack.filter.PacketFilter</tt> interface determines which
|
||||
specific packets will be delivered to a <tt>PacketCollector</tt> or <tt>PacketListener</tt>.
|
||||
Many pre-defined filters can be found in the <tt>org.jivesoftware.smack.filter</tt> package.
|
||||
|
||||
<p>
|
||||
The following code snippet demonstrates registering both a packet collector and a packet
|
||||
listener:<p>
|
||||
|
||||
<div class="code"><pre>
|
||||
<font color="gray"><i>// Create a packet filter to listen for new messages from a particular</i></font>
|
||||
<font color="gray"><i>// user. We use an AndFilter to combine two other filters.</i></font>
|
||||
PacketFilter filter = new AndFilter(new PacketTypeFilter(<b>Message.class</b>),
|
||||
new FromContainsFilter(<font color="green">"mary@jivesoftware.com"</font>));
|
||||
<font color="gray"><i>// Assume we've created an XMPPConnection name "connection".</i></font>
|
||||
|
||||
<font color="gray"><i>// First, register a packet collector using the filter we created.</i></font>
|
||||
PacketCollector myCollector = connection.createPacketCollector(filter);
|
||||
<font color="gray"><i>// Normally, you'd do something with the collector, like wait for new packets.</i></font>
|
||||
|
||||
<font color="gray"><i>// Next, create a packet listener. We use an anonymous inner class for brevity.</i></font>
|
||||
PacketListener myListener = new PacketListener() {
|
||||
<b>public</b> <b>void</b> processPacket(Packet packet) {
|
||||
<font color="gray"><i>// Do something with the incoming packet here.</i></font>
|
||||
}
|
||||
};
|
||||
<font color="gray"><i>// Register the listener.</i></font>
|
||||
connection.addPacketListener(myListener, filter);
|
||||
</pre></div><p>
|
||||
|
||||
<p class="subheader">
|
||||
Standard Packet Filters
|
||||
</p>
|
||||
|
||||
A rich set of packet filters are included with Smack, or you can create your own filters by coding
|
||||
to the <tt>PacketFilter</tt> interface. The default set of filters includes:
|
||||
<ul>
|
||||
<li> <tt>PacketTypeFilter</tt> -- filters for packets that are a particular Class type.
|
||||
<li> <tt>PacketIDFilter</tt> -- filters for packets with a particular packet ID.
|
||||
<li> <tt>ThreadFilter</tt> -- filters for message packets with a particular thread ID.
|
||||
<li> <tt>ToContainsFilter</tt> -- filters for packets that are sent to a particular address.
|
||||
<li> <tt>FromContainsFilter</tt> -- filters for packets that are sent to a particular address.
|
||||
<li> <tt>PacketExtensionFilter</tt> -- filters for packets that have a particular packet extension.
|
||||
<li> <tt>AndFilter</tt> -- implements the logical AND operation over two filters.
|
||||
<li> <tt>OrFilter</tt> -- implements the logical OR operation over two filters.
|
||||
<li> <tt>NotFilter</tt> -- implements the logical NOT operation on a filter.
|
||||
</ul>
|
||||
|
||||
|
||||
|
||||
<br clear="all" /><br><br>
|
||||
<div class="footer">
|
||||
Copyright © Jive Software 2002-2005
|
||||
</div>
|
||||
|
||||
</body>
|
||||
</html>
|
119
CopyOftrunk/documentation/properties.html
Normal file
|
@ -0,0 +1,119 @@
|
|||
<html>
|
||||
<head>
|
||||
<title>Smack: Packet Properties - Jive Software</title>
|
||||
<link rel="stylesheet" type="text/css" href="style.css" /
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<div class="header">
|
||||
Packet Properties
|
||||
</div>
|
||||
|
||||
<div class="nav">
|
||||
« <a href="index.html">Table of Contents</a>
|
||||
</div>
|
||||
|
||||
<p>
|
||||
Smack provides an easy mechanism for attaching arbitrary properties to packets. Each property
|
||||
has a String name, and a value that is a Java primitive (int, long, float, double, boolean) or
|
||||
any Serializable object (a Java object is Serializable when it implements the Serializable
|
||||
interface).
|
||||
</p>
|
||||
|
||||
<p class="subheader">
|
||||
Using the API
|
||||
</p>
|
||||
|
||||
<p>
|
||||
All major objects have property support, such as Message objects. The following code
|
||||
demonstrates how to set properties:
|
||||
</p>
|
||||
|
||||
<div class="code"><pre>
|
||||
Message message = chat.createMessage();
|
||||
<font color="gray"></i>// Add a Color object as a property.</i></font>
|
||||
message.setProperty(<font color="blue">"favoriteColor"</font>, new Color(0, 0, 255));
|
||||
<font color="gray"></i>// Add an int as a property.</i></font>
|
||||
message.setProperty(<font color="blue">"favoriteNumber"</font>, 4);
|
||||
chat.sendMessage(message);
|
||||
</pre></div>
|
||||
|
||||
<p>
|
||||
Getting those same properties would use the following code:
|
||||
</p>
|
||||
|
||||
<div class="code"><pre>
|
||||
Message message = chat.nextMessage();
|
||||
<font color="gray"></i>// Get a Color object property.</i></font>
|
||||
Color favoriteColor = (Color)message.getProperty(<font color="blue">"favoriteColor"</font>);
|
||||
<font color="gray"></i>// Get an int property. Note that properties are always returned as
|
||||
// Objects, so we must cast the value to an Integer, then convert
|
||||
// it to an int.</i></font>
|
||||
int favoriteNumber = ((Integer)message.getProperty(<font color="blue">"favoriteNumber"</font>)).intValue();
|
||||
</pre></div>
|
||||
|
||||
<p class="subheader">
|
||||
Objects as Properties
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Using objects as property values is a very powerful and easy way to exchange data. However,
|
||||
you should keep the following in mind:
|
||||
</p>
|
||||
|
||||
<ul>
|
||||
<li>Packet extensions are the more standard way to add extra data to XMPP stanzas. Using
|
||||
properties may be more convenient in some cases, however, since Smack will do the
|
||||
work of handling the XML.
|
||||
|
||||
<li>When you send a Java object as a property, only clients running Java will be able to
|
||||
interpret the data. So, consider using a series of primitive values to transfer data
|
||||
instead.
|
||||
|
||||
<li>Objects sent as property values must implement Serialiable. Additionally, both the sender
|
||||
and receiver must have identical versions of the class, or a serialization exception
|
||||
will occur when de-serializing the object.
|
||||
|
||||
<li>Serialized objects can potentially be quite large, which will use more bandwidth and
|
||||
server resources.
|
||||
</ul>
|
||||
|
||||
<p class="subheader">
|
||||
XML Format
|
||||
</p>
|
||||
|
||||
<p>
|
||||
The current XML format used to send property data is not a standard, so will likely not be
|
||||
recognized by clients not using Smack. The XML looks like the following (comments added for
|
||||
clarity):
|
||||
</p>
|
||||
|
||||
<div class="code"><pre>
|
||||
<font color="gray"><i><!-- All properties are in a x block. --></i></font>
|
||||
<properties xmlns="http://www.jivesoftware.com/xmlns/xmpp/properties">
|
||||
<font color="gray"><i><!-- First, a property named "prop1" that's an integer. --></i></font>
|
||||
<property>
|
||||
<name>prop1</name>
|
||||
<value type="integer">123</value>
|
||||
<property>
|
||||
<font color="gray"><i><!-- Next, a Java object that's been serialized and then converted
|
||||
from binary data to base-64 encoded text. --></i></font>
|
||||
<property>
|
||||
<name>blah2</name>
|
||||
<value type="java-object">adf612fna9nab</value>
|
||||
<property>
|
||||
</properties>
|
||||
</pre></div>
|
||||
|
||||
<p>
|
||||
The currently supported types are: <tt>integer</tt>, <tt>long</tt>, <tt>float</tt>,
|
||||
<tt>double</tt>, <tt>boolean</tt>, <tt>string</tt>, and <tt>java-object</tt>.
|
||||
</p>
|
||||
|
||||
<div class="footer">
|
||||
Copyright © Jive Software 2002-2004
|
||||
</div>
|
||||
|
||||
</body>
|
||||
</html>
|
121
CopyOftrunk/documentation/providers.html
Normal file
|
@ -0,0 +1,121 @@
|
|||
<html>
|
||||
<head>
|
||||
<title>Smack: Provider Architecture - Jive Software</title>
|
||||
<link rel="stylesheet" type="text/css" href="style.css" />
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<div class="header">
|
||||
Provider Architecture: Packet Extensions and Custom IQ's
|
||||
</div>
|
||||
|
||||
<div class="nav">
|
||||
« <a href="index.html">Table of Contents</a>
|
||||
</div>
|
||||
|
||||
<p>
|
||||
|
||||
The Smack provider architecture is a system for plugging in
|
||||
custom XML parsing of packet extensions and IQ packets. The
|
||||
standard <a href="extensions/index.html">Smack Extensions</a>
|
||||
are built using the provider architecture. Two types of
|
||||
providers exist:<ul>
|
||||
<li><tt>IQProvider</tt> -- parses IQ requests into Java objects.
|
||||
<li><tt>PacketExtension</tt> -- parses XML sub-documents attached to
|
||||
packets into PacketExtension instances.</ul>
|
||||
|
||||
<p class="subheader">IQProvider</p>
|
||||
|
||||
By default, Smack only knows how to process IQ packets with sub-packets that
|
||||
are in a few namespaces such as:<ul>
|
||||
<li>jabber:iq:auth
|
||||
<li>jabber:iq:roster
|
||||
<li>jabber:iq:register</ul>
|
||||
|
||||
Because many more IQ types are part of XMPP and its extensions, a pluggable IQ parsing
|
||||
mechanism is provided. IQ providers are registered programatically or by creating a
|
||||
smack.providers file in the META-INF directory of your JAR file. The file is an XML
|
||||
document that contains one or more iqProvider entries, as in the following example:
|
||||
|
||||
<pre>
|
||||
<?xml version="1.0"?>
|
||||
<smackProviders>
|
||||
<iqProvider>
|
||||
<elementName>query</elementName>
|
||||
<namespace>jabber:iq:time</namespace>
|
||||
<className>org.jivesoftware.smack.packet.Time</className>
|
||||
</iqProvider>
|
||||
</smackProviders></pre>
|
||||
|
||||
Each IQ provider is associated with an element name and a namespace. In the
|
||||
example above, the element name is <tt>query</tt> and the namespace is
|
||||
<tt>abber:iq:time</tt>. If multiple provider entries attempt to register to
|
||||
handle the same namespace, the first entry loaded from the classpath will
|
||||
take precedence. <p>
|
||||
|
||||
The IQ provider class can either implement the IQProvider
|
||||
interface, or extend the IQ class. In the former case, each IQProvider is
|
||||
responsible for parsing the raw XML stream to create an IQ instance. In
|
||||
the latter case, bean introspection is used to try to automatically set
|
||||
properties of the IQ instance using the values found in the IQ packet XML.
|
||||
For example, an XMPP time packet resembles the following:
|
||||
|
||||
<pre>
|
||||
<iq type='result' to='joe@example.com' from='mary@example.com' id='time_1'>
|
||||
<query xmlns='jabber:iq:time'>
|
||||
<utc>20020910T17:58:35</utc>
|
||||
<tz>MDT</tz>
|
||||
<display>Tue Sep 10 12:58:35 2002</display>
|
||||
</query>
|
||||
</iq></pre>
|
||||
|
||||
In order for this packet to be automatically mapped to the Time object listed in the
|
||||
providers file above, it must have the methods setUtc(String), setTz(String), and
|
||||
setDisplay(String). The introspection service will automatically try to convert the String
|
||||
value from the XML into a boolean, int, long, float, double, or Class depending on the
|
||||
type the IQ instance expects.<p>
|
||||
|
||||
<p class="subheader">PacketExtensionProvider</p>
|
||||
|
||||
Packet extension providers provide a pluggable system for
|
||||
packet extensions, which are child elements in a custom namespace
|
||||
of IQ, message and presence packets.
|
||||
Each extension provider is registered with an element name and namespace
|
||||
in the smack.providers file as in the following example:
|
||||
|
||||
<pre>
|
||||
<?xml version="1.0"?>
|
||||
<smackProviders>
|
||||
<extensionProvider>
|
||||
<elementName>x</elementName>
|
||||
<namespace>jabber:iq:event</namespace>
|
||||
<className>org.jivesoftware.smack.packet.MessageEvent</className>
|
||||
</extensionProvider>
|
||||
</smackProviders></pre>
|
||||
|
||||
If multiple provider entries attempt to register to handle the same element
|
||||
name and namespace, the first entry loaded from the classpath will take
|
||||
precedence.<p>
|
||||
|
||||
Whenever a packet extension is found in a packet, parsing will
|
||||
be passed to the correct provider. Each provider can either implement the
|
||||
PacketExtensionProvider interface or be a standard Java Bean. In the
|
||||
former case, each extension provider is responsible for parsing the raw
|
||||
XML stream to contruct an object. In the latter case, bean introspection
|
||||
is used to try to automatically set the properties of the class using
|
||||
the values in the packet extension sub-element.<p>
|
||||
|
||||
When an extension provider is not registered for an element name and
|
||||
namespace combination, Smack will store all top-level elements of the
|
||||
sub-packet in DefaultPacketExtension object and then attach it to the packet.
|
||||
|
||||
|
||||
<br clear="all" /><br><br>
|
||||
|
||||
<div class="footer">
|
||||
Copyright © Jive Software 2002-2004
|
||||
</div>
|
||||
|
||||
</body>
|
||||
</html>
|
125
CopyOftrunk/documentation/roster.html
Normal file
|
@ -0,0 +1,125 @@
|
|||
<html>
|
||||
<head>
|
||||
<title>Smack: Roster and Presence - Jive Software</title>
|
||||
<link rel="stylesheet" type="text/css" href="style.css" />
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<div class="header">
|
||||
Roster and Presence
|
||||
</div>
|
||||
|
||||
<div class="nav">
|
||||
« <a href="index.html">Table of Contents</a>
|
||||
</div>
|
||||
|
||||
<p>
|
||||
|
||||
The roster lets you keep track of the availability ("presence") of other users.
|
||||
A roster also allows you to organize users into groups such as "Friends" and
|
||||
"Co-workers". Other IM systems refer to the roster as the buddy list, contact list,
|
||||
etc.<p>
|
||||
|
||||
A <tt>Roster</tt> instance is obtained using the <tt>XMPPConnection.getRoster()</tt>
|
||||
method, but only after successfully logging into a server.
|
||||
|
||||
<p class="subheader">Roster Entries</p>
|
||||
|
||||
<p>
|
||||
Every user in a roster is represented by a RosterEntry, which consists of:<ul>
|
||||
<li>An XMPP address (e.g. jsmith@example.com).
|
||||
<li>A name you've assigned to the user (e.g. "Joe").
|
||||
<li>The list of groups in the roster that the entry belongs to. If the roster
|
||||
entry belongs to no groups, it's called an "unfiled entry".
|
||||
</ul>
|
||||
|
||||
The following code snippet prints all entries in the roster:
|
||||
|
||||
<pre>
|
||||
Roster roster = con.getRoster();
|
||||
<b>for</b> (Iterator i=roster.getEntries(); i.hasNext(); ) {
|
||||
System.out.println(i.next());
|
||||
}
|
||||
</pre>
|
||||
|
||||
Methods also exist to get individual entries, the list of unfiled entries, or to get one or
|
||||
all roster groups.
|
||||
|
||||
<p class="subheader">Presence</p>
|
||||
|
||||
<img src="images/roster.png" width="166" height="322" vspace="5" hspace="5" alt="Roster" border="0" align="right">
|
||||
|
||||
<p>Every entry in the roster has presence associated with it. The
|
||||
<tt>Roster.getPresence(String user)</tt> method will return a Presence object with
|
||||
the user's presence or <tt>null</tt> if the user is not online or you are not
|
||||
subscribed to the user's presence. <i>Note:</i> typically, presence
|
||||
subscription is always tied to the user being on the roster, but this is not
|
||||
true in all cases.</p>
|
||||
|
||||
<p>A user either has a presence of online or offline. When a user is online, their
|
||||
presence may contain extended information such as what they are currently doing, whether
|
||||
they wish to be disturbed, etc. See the Presence class for further details.</p>
|
||||
|
||||
<p class="subheader">Listening for Roster and Presence Changes</p>
|
||||
|
||||
<p>The typical use of the roster class is to display a tree view of groups and entries
|
||||
along with the current presence value of each entry. As an example, see the image showing
|
||||
a Roster in the Exodus XMPP client to the right.</p>
|
||||
|
||||
<p>The presence information will likely
|
||||
change often, and it's also possible for the roster entries to change or be deleted.
|
||||
To listen for changing roster and presence data, a RosterListener should be used.
|
||||
The following code snippet registers a RosterListener with the Roster that prints
|
||||
any presence changes in the roster to standard out. A normal client would use
|
||||
similar code to update the roster UI with the changing information.
|
||||
|
||||
<br clear="all">
|
||||
|
||||
<pre>
|
||||
final Roster roster = con.getRoster();
|
||||
roster.addRosterListener(new RosterListener() {
|
||||
<b>public void</b> rosterModified() {
|
||||
<font color="gray"><i>// Ignore event for this example.</i></font>
|
||||
}
|
||||
|
||||
<b>public void</b> presenceChanged(String user) {
|
||||
<font color="gray"><i>// If the presence is unavailable then "null" will be printed,
|
||||
// which is fine for this example.</i></font>
|
||||
System.out.println(<font color="green">"Presence changed: "</font> + roster.getPresence(user));
|
||||
}
|
||||
});
|
||||
</pre>
|
||||
|
||||
<p class="subheader">Adding Entries to the Roster</p>
|
||||
|
||||
<p>Rosters and presence use a permissions-based model where users must give permission before
|
||||
they are added to someone else's roster. This protects a user's privacy by
|
||||
making sure that only approved users are able to view their presence information.
|
||||
Therefore, when you add a new roster entry it will be in a pending state until
|
||||
the other user accepts your request.</p>
|
||||
|
||||
If another user requests a presence subscription so they can add you to their roster,
|
||||
you must accept or reject that request. Smack handles presence subscription requests
|
||||
in one of three ways: <ul>
|
||||
|
||||
<li> Automatically accept all presence subscription requests.
|
||||
<li> Automatically reject all presence subscription requests.
|
||||
<li> Process presence subscription requests manually.
|
||||
</ul>
|
||||
|
||||
The mode can be set using the <tt>Roster.setSubscriptionMode(int subscriptionMode)</tt>
|
||||
method. Simple clients normally use one of the automated subscription modes, while
|
||||
full-featured clients should manually process subscription requests and let the
|
||||
end-user accept or reject each request. If using the manual mode, a PacketListener
|
||||
should be registered that listens for Presence packets that have a type of
|
||||
<tt>Presence.Type.SUBSCRIBE</tt>.
|
||||
|
||||
<br clear="all" /><br><br>
|
||||
|
||||
<div class="footer">
|
||||
Copyright © Jive Software 2002-2004
|
||||
</div>
|
||||
|
||||
</body>
|
||||
</html>
|
56
CopyOftrunk/documentation/style.css
Normal file
|
@ -0,0 +1,56 @@
|
|||
BODY {
|
||||
font-size : 100%;
|
||||
background-color : #fff;
|
||||
}
|
||||
BODY, TD, TH {
|
||||
font-family : tahoma, arial, helvetica;
|
||||
font-size : 0.8em;
|
||||
}
|
||||
PRE, TT, CODE {
|
||||
font-family : courier new, monospaced;
|
||||
font-size : 1.0em;
|
||||
}
|
||||
A:hover {
|
||||
text-decoration : none;
|
||||
}
|
||||
LI {
|
||||
padding-bottom : 4px;
|
||||
}
|
||||
.header {
|
||||
font-size : 1.4em;
|
||||
font-weight : bold;
|
||||
width : 100%;
|
||||
border-bottom : 1px #ccc solid;
|
||||
padding-bottom : 2px;
|
||||
}
|
||||
.subheader {
|
||||
font-weight : bold;
|
||||
}
|
||||
.footer {
|
||||
font-size : 0.8em;
|
||||
color : #999;
|
||||
text-align : center;
|
||||
width : 100%;
|
||||
border-top : 1px #ccc solid;
|
||||
padding-top : 2px;
|
||||
}
|
||||
.code {
|
||||
border : 1px #ccc solid;
|
||||
padding : 0em 1.0em 0em 1.0em;
|
||||
margin : 4px 0px 4px 0px;
|
||||
}
|
||||
.nav, .nav A {
|
||||
font-family : verdana;
|
||||
font-size : 0.85em;
|
||||
color : #600;
|
||||
text-decoration : none;
|
||||
font-weight : bold;
|
||||
}
|
||||
.nav {
|
||||
width : 100%;
|
||||
border-bottom : 1px #ccc solid;
|
||||
padding : 3px 3px 5px 1px;
|
||||
}
|
||||
.nav A:hover {
|
||||
text-decoration : underline;
|
||||
}
|
16
CopyOftrunk/sample/conf/WEB-INF/web.xml
Normal file
|
@ -0,0 +1,16 @@
|
|||
<?xml version="1.0" encoding="ISO-8859-1"?>
|
||||
|
||||
<!-- Servlet 2.3 is required for Jive Forums 3 -->
|
||||
<!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>Smack Client UI</display-name>
|
||||
<description>Smack sample UI</description>
|
||||
|
||||
<!-- Welcome file list -->
|
||||
<welcome-file-list>
|
||||
<welcome-file>login.jsp</welcome-file>
|
||||
</welcome-file-list>
|
||||
|
||||
</web-app>
|
138
CopyOftrunk/sample/web/addContact.jsp
Normal file
|
@ -0,0 +1,138 @@
|
|||
<%--
|
||||
- $RCSfile$
|
||||
- $Revision$
|
||||
- $Date$
|
||||
-
|
||||
- Copyright (C) 2002-2003 Jive Software. All rights reserved.
|
||||
-
|
||||
- The Jive Software License (based on Apache Software License, Version 1.1)
|
||||
- Redistribution and use in source and binary forms, with or without
|
||||
- modification, are permitted provided that the following conditions
|
||||
- are met:
|
||||
-
|
||||
- 1. Redistributions of source code must retain the above copyright
|
||||
- notice, this list of conditions and the following disclaimer.
|
||||
-
|
||||
- 2. Redistributions in binary form must reproduce the above copyright
|
||||
- notice, this list of conditions and the following disclaimer in
|
||||
- the documentation and/or other materials provided with the
|
||||
- distribution.
|
||||
-
|
||||
- 3. The end-user documentation included with the redistribution,
|
||||
- if any, must include the following acknowledgment:
|
||||
- "This product includes software developed by
|
||||
- Jive Software (http://www.jivesoftware.com)."
|
||||
- Alternately, this acknowledgment may appear in the software itself,
|
||||
- if and wherever such third-party acknowledgments normally appear.
|
||||
-
|
||||
- 4. The names "Smack" and "Jive Software" must not be used to
|
||||
- endorse or promote products derived from this software without
|
||||
- prior written permission. For written permission, please
|
||||
- contact webmaster@jivesoftware.com.
|
||||
-
|
||||
- 5. Products derived from this software may not be called "Smack",
|
||||
- nor may "Smack" appear in their name, without prior written
|
||||
- permission of Jive Software.
|
||||
-
|
||||
- THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
|
||||
- WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
- OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
- DISCLAIMED. IN NO EVENT SHALL JIVE SOFTWARE OR
|
||||
- ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
- SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
- LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
|
||||
- USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
- ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
- OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
|
||||
- OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
- SUCH DAMAGE.
|
||||
--%>
|
||||
<%@ page import="java.util.*,
|
||||
org.jivesoftware.smack.*,
|
||||
org.jivesoftware.smack.packet.*,
|
||||
org.jivesoftware.smack.util.*"%>
|
||||
<%@ include file="global.jsp" %>
|
||||
<%
|
||||
// If we don't have a valid connection then proceed to login
|
||||
XMPPConnection conn = (XMPPConnection) session.getAttribute("connection");
|
||||
if (conn == null || !conn.isConnected()) {
|
||||
response.sendRedirect("login.jsp");
|
||||
return;
|
||||
}
|
||||
Roster roster = conn.getRoster();
|
||||
|
||||
// Get parameters
|
||||
String user = getParameter(request, "user");
|
||||
String nickname = getParameter(request, "nickname");
|
||||
String group1 = getParameter(request, "group1");
|
||||
String group2 = getParameter(request, "group2");
|
||||
|
||||
// Create a new entry in the roster that belongs to a certain groups
|
||||
if (user != null) {
|
||||
roster.createEntry(user, nickname, new String[] {group1, group2});
|
||||
response.sendRedirect("viewRoster.jsp");
|
||||
return;
|
||||
}
|
||||
%>
|
||||
<html>
|
||||
<head>
|
||||
<title>Add Contact</title>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
||||
<link href="css/general.css" rel="stylesheet" type="text/css">
|
||||
</head>
|
||||
<body>
|
||||
<table width="100%" border="0">
|
||||
<tr>
|
||||
<td><span id="bigBlack">Add contact to roster</span></td>
|
||||
<td align="right"><a href="viewRoster.jsp"><img src="images/address_book.png" alt="View roster" border="0"></a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="2"> </td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="2"><table width="100%" border="0">
|
||||
<tr>
|
||||
<td width="20%"> </td>
|
||||
<td width="60%"> <table cellSpacing=0 borderColorDark=#E0E0E0 cellPadding=0 width=100% align=center borderColorLight=#000000 border=1>
|
||||
<tr bgcolor="#AAAAAA">
|
||||
<td class=text id=bigWhite height=16 align="center"> <b>Contact
|
||||
Information</b> </td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center"> <table width="100%" border="0">
|
||||
<form method="post" action="addContact.jsp">
|
||||
<tr>
|
||||
<td class=text id=black height=16>Username:</td>
|
||||
<td><input type="text" name="user"> <span class=text id=black height=16>(e.g.
|
||||
johndoe@jabber.org)</span></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class=text id=black height=16>Nickname:</td>
|
||||
<td><input type="text" name="nickname"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class=text id=black height=16>Group 1:</td>
|
||||
<td><input type="text" name="group1" value="<%= (group1!=null)?group1:"" %>"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class=text id=black height=16>Group 2:</td>
|
||||
<td><input type="text" name="group2"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td> </td>
|
||||
<td> </td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan=2 align="center"> <input type="submit" value="Add Contact"></td>
|
||||
</tr>
|
||||
</form>
|
||||
</table></td>
|
||||
</tr>
|
||||
</table></td>
|
||||
<td width="20%"> </td>
|
||||
</tr>
|
||||
</table></td>
|
||||
</tr>
|
||||
</table>
|
||||
</body>
|
||||
</html>
|
60
CopyOftrunk/sample/web/chat.jsp
Normal file
|
@ -0,0 +1,60 @@
|
|||
<%--
|
||||
- $$RCSfile$$
|
||||
- $$Revision$$
|
||||
- $$Date$$
|
||||
-
|
||||
- Copyright (C) 2002-2003 Jive Software. All rights reserved.
|
||||
-
|
||||
- The Jive Software License (based on Apache Software License, Version 1.1)
|
||||
- Redistribution and use in source and binary forms, with or without
|
||||
- modification, are permitted provided that the following conditions
|
||||
- are met:
|
||||
-
|
||||
- 1. Redistributions of source code must retain the above copyright
|
||||
- notice, this list of conditions and the following disclaimer.
|
||||
-
|
||||
- 2. Redistributions in binary form must reproduce the above copyright
|
||||
- notice, this list of conditions and the following disclaimer in
|
||||
- the documentation and/or other materials provided with the
|
||||
- distribution.
|
||||
-
|
||||
- 3. The end-user documentation included with the redistribution,
|
||||
- if any, must include the following acknowledgment:
|
||||
- "This product includes software developed by
|
||||
- Jive Software (http://www.jivesoftware.com)."
|
||||
- Alternately, this acknowledgment may appear in the software itself,
|
||||
- if and wherever such third-party acknowledgments normally appear.
|
||||
-
|
||||
- 4. The names "Smack" and "Jive Software" must not be used to
|
||||
- endorse or promote products derived from this software without
|
||||
- prior written permission. For written permission, please
|
||||
- contact webmaster@jivesoftware.com.
|
||||
-
|
||||
- 5. Products derived from this software may not be called "Smack",
|
||||
- nor may "Smack" appear in their name, without prior written
|
||||
- permission of Jive Software.
|
||||
-
|
||||
- THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
|
||||
- WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
- OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
- DISCLAIMED. IN NO EVENT SHALL JIVE SOFTWARE OR
|
||||
- ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
- SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
- LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
|
||||
- USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
- ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
- OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
|
||||
- OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
- SUCH DAMAGE.
|
||||
--%>
|
||||
<html>
|
||||
<head>
|
||||
<title>Chat with contact</title>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
||||
<link href="css/general.css" rel="stylesheet" type="text/css">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
Not implemented yet! <a href="viewRoster.jsp"><img src="images/address_book.png" alt="View roster" border="0"></a>
|
||||
</body>
|
||||
</html>
|
36
CopyOftrunk/sample/web/css/general.css
Normal file
|
@ -0,0 +1,36 @@
|
|||
BODY
|
||||
{
|
||||
FONT-FAMILY: Verdana, Geneva, Arial, Helvetica, sans-serif;
|
||||
FONT-SIZE: 10px;
|
||||
margin-left: 0px;
|
||||
margin-right: 0px;
|
||||
margin-bottom: 0px;
|
||||
margin-top: 0px;
|
||||
background-color: #FFFFFF;
|
||||
}
|
||||
.text {
|
||||
FONT-FAMILY: Verdana, Geneva, Arial, Helvetica, sans-serif;
|
||||
FONT-SIZE: 10px;
|
||||
}
|
||||
input,textarea,select
|
||||
{
|
||||
font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;
|
||||
font-size: 10px;
|
||||
}
|
||||
#black {
|
||||
color: #000000;
|
||||
font-weight: BOLD;
|
||||
}
|
||||
#white {
|
||||
color: FFFFFF;
|
||||
font-weight: BOLD;
|
||||
}
|
||||
#bigWhite {
|
||||
color: FFFFFF;
|
||||
font-weight: BOLD;
|
||||
font-size: 14px;
|
||||
}
|
||||
#bigBlack {
|
||||
font-weight: BOLD;
|
||||
font-size: 18px;
|
||||
}
|
66
CopyOftrunk/sample/web/global.jsp
Normal file
|
@ -0,0 +1,66 @@
|
|||
<%--
|
||||
- $$RCSfile$$
|
||||
- $$Revision$$
|
||||
- $$Date$$
|
||||
-
|
||||
- Copyright (C) 2002-2003 Jive Software. All rights reserved.
|
||||
-
|
||||
- The Jive Software License (based on Apache Software License, Version 1.1)
|
||||
- Redistribution and use in source and binary forms, with or without
|
||||
- modification, are permitted provided that the following conditions
|
||||
- are met:
|
||||
-
|
||||
- 1. Redistributions of source code must retain the above copyright
|
||||
- notice, this list of conditions and the following disclaimer.
|
||||
-
|
||||
- 2. Redistributions in binary form must reproduce the above copyright
|
||||
- notice, this list of conditions and the following disclaimer in
|
||||
- the documentation and/or other materials provided with the
|
||||
- distribution.
|
||||
-
|
||||
- 3. The end-user documentation included with the redistribution,
|
||||
- if any, must include the following acknowledgment:
|
||||
- "This product includes software developed by
|
||||
- Jive Software (http://www.jivesoftware.com)."
|
||||
- Alternately, this acknowledgment may appear in the software itself,
|
||||
- if and wherever such third-party acknowledgments normally appear.
|
||||
-
|
||||
- 4. The names "Smack" and "Jive Software" must not be used to
|
||||
- endorse or promote products derived from this software without
|
||||
- prior written permission. For written permission, please
|
||||
- contact webmaster@jivesoftware.com.
|
||||
-
|
||||
- 5. Products derived from this software may not be called "Smack",
|
||||
- nor may "Smack" appear in their name, without prior written
|
||||
- permission of Jive Software.
|
||||
-
|
||||
- THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
|
||||
- WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
- OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
- DISCLAIMED. IN NO EVENT SHALL JIVE SOFTWARE OR
|
||||
- ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
- SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
- LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
|
||||
- USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
- ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
- OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
|
||||
- OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
- SUCH DAMAGE.
|
||||
--%>
|
||||
<%!
|
||||
public static String getParameter(HttpServletRequest request, String name)
|
||||
{
|
||||
String temp = request.getParameter(name);
|
||||
if (temp != null) {
|
||||
if (temp.equals("")) {
|
||||
return null;
|
||||
}
|
||||
else {
|
||||
return temp;
|
||||
}
|
||||
}
|
||||
else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
%>
|
BIN
CopyOftrunk/sample/web/images/address_book.png
Normal file
After Width: | Height: | Size: 1.2 KiB |