diff --git a/source/org/jivesoftware/smackx/XHTMLManager.java b/source/org/jivesoftware/smackx/XHTMLManager.java new file mode 100644 index 000000000..eee45c568 --- /dev/null +++ b/source/org/jivesoftware/smackx/XHTMLManager.java @@ -0,0 +1,113 @@ +/** + * $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. + * ==================================================================== + */ + +package org.jivesoftware.smackx; + +import java.util.Iterator; + +import org.jivesoftware.smack.packet.Message; +import org.jivesoftware.smackx.packet.XHTMLExtension; + +/** + * Manages XHTML formatted texts within messages. A XHTMLManager provides a high level access to + * get and set XHTML bodies to messages, enable and disable XHTML support and check if remote XMPP + * clients support XHTML. + * + * @author Gaston Dombiak + */ +public class XHTMLManager { + + /** + * Returns an Iterator for the XHTML bodies in the message. Returns null if + * the message does not contain an XHTML extension. + * + * @param message an XHTML message + * @return an Iterator for the bodies in the message or null if none. + */ + public static Iterator getBodies(Message message) { + XHTMLExtension xhtmlExtension = + (XHTMLExtension) message.getExtension("html", "http://jabber.org/protocol/xhtml-im"); + if (xhtmlExtension != null) + return xhtmlExtension.getBodies(); + else + return null; + } + + /** + * Adds an XHTML body to the message. + * + * @param message the message that will receive the XHTML body + * @param body the string to add as an XHTML body to the message + */ + public static void addBody(Message message, String body) { + XHTMLExtension xhtmlExtension = + (XHTMLExtension) message.getExtension("html", "http://jabber.org/protocol/xhtml-im"); + if (xhtmlExtension == null) { + // Create an XHTMLExtension and add it to the message + xhtmlExtension = new XHTMLExtension(); + message.addExtension(xhtmlExtension); + } + // Add the required bodies to the message + xhtmlExtension.addBody(body); + } + + /** + * Returns true if the message contains an XHTML extension. + * + * @param message the message to check if contains an XHTML extentsion or not + * @return a boolean indicating whether the message is an XHTML message + */ + public static boolean isXHTMLMessage(Message message) { + return message.getExtension("html", "http://jabber.org/protocol/xhtml-im") != null; + } + +} diff --git a/source/org/jivesoftware/smackx/XHTMLText.java b/source/org/jivesoftware/smackx/XHTMLText.java new file mode 100644 index 000000000..68eceac69 --- /dev/null +++ b/source/org/jivesoftware/smackx/XHTMLText.java @@ -0,0 +1,459 @@ +/** + * $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. + * ==================================================================== + */ + +package org.jivesoftware.smackx; + +/** + * An XHTMLText represents formatted text. This class also helps to build valid + * XHTML tags. + * + * @author Gaston Dombiak + */ +public class XHTMLText { + + private StringBuffer text = new StringBuffer(30); + + /** + * Creates a new XHTMLText with body tag params. + * + * @param style the XHTML style of the body + * @param lang the language of the body + */ + public XHTMLText(String style, String lang) { + appendOpenBodyTag(style, lang); + } + + /** + * Appends a tag that indicates that an anchor section begins. + * + * @param href indicates the URL being linked to + * @param style the XHTML style of the anchor + */ + public void appendOpenAnchorTag(String href, String style) { + StringBuffer sb = new StringBuffer(""); + text.append(sb.toString()); + } + + /** + * Appends a tag that indicates that an anchor section ends. + * + */ + public void appendCloseAnchorTag() { + text.append(""); + } + + /** + * Appends a tag that indicates that a blockquote section begins. + * + * @param style the XHTML style of the blockquote + */ + public void appendOpenBlockQuoteTag(String style) { + StringBuffer sb = new StringBuffer(""); + text.append(sb.toString()); + } + + /** + * Appends a tag that indicates that a blockquote section ends. + * + */ + public void appendCloseBlockQuoteTag() { + text.append(""); + } + + /** + * Appends a tag that indicates that a body section begins. + * + * @param style the XHTML style of the body + * @param lang the language of the body + */ + private void appendOpenBodyTag(String style, String lang) { + StringBuffer sb = new StringBuffer(""); + text.append(sb.toString()); + } + + /** + * Appends a tag that indicates that a body section ends. + * + */ + private String closeBodyTag() { + return ""; + } + + /** + * Appends a tag that inserts a single carriage return. + * + */ + public void appendBrTag() { + text.append("
"); + } + + /** + * Appends a tag that indicates a reference to work, such as a book, report or web site. + * + */ + public void appendOpenCiteTag() { + text.append(""); + } + + /** + * Appends a tag that indicates text that is the code for a program. + * + */ + public void appendOpenCodeTag() { + text.append(""); + } + + /** + * Appends a tag that indicates end of text that is the code for a program. + * + */ + public void appendCloseCodeTag() { + text.append(""); + } + + /** + * Appends a tag that indicates emphasis. + * + */ + public void appendOpenEmTag() { + text.append(""); + } + + /** + * Appends a tag that indicates end of emphasis. + * + */ + public void appendCloseEmTag() { + text.append(""); + } + + /** + * Appends a tag that indicates a header, a title of a section of the message. + * + * @param level the level of the Header. It should be a value between 1 and 3 + * @param style the XHTML style of the blockquote + */ + public void appendOpenHeaderTag(int level, String style) { + if (level > 3 || level < 1) { + return; + } + StringBuffer sb = new StringBuffer(""); + text.append(sb.toString()); + } + + /** + * Appends a tag that indicates that a header section ends. + * + * @param level the level of the Header. It should be a value between 1 and 3 + */ + public void appendCloseHeaderTag(int level) { + if (level > 3 || level < 1) { + return; + } + StringBuffer sb = new StringBuffer(""); + text.append(sb.toString()); + } + + /** + * Appends a tag that indicates an image. + * + * @param align how text should flow around the picture + * @param alt the text to show if you don't show the picture + * @param height how tall is the picture + * @param src where to get the picture + * @param width how wide is the picture + */ + public void appendImageTag(String align, String alt, String height, String src, String width) { + StringBuffer sb = new StringBuffer(""); + text.append(sb.toString()); + } + + /** + * Appends a tag that indicates the start of a new line item within a list. + * + * @param style the style of the line item + */ + public void appendLineItemTag(String style) { + StringBuffer sb = new StringBuffer(""); + text.append(sb.toString()); + } + + /** + * Appends a tag that creates an ordered list. "Ordered" means that the order of the items + * in the list is important. To show this, browsers automatically number the list. + * + * @param style the style of the ordered list + */ + public void appendOpenOrderedListTag(String style) { + StringBuffer sb = new StringBuffer(""); + text.append(sb.toString()); + } + + /** + * Appends a tag that indicates that an ordered list section ends. + * + */ + public void appendCloseOrderedListTag() { + text.append(""); + } + + /** + * Appends a tag that creates an unordered list. The unordered part means that the items + * in the list are not in any particular order. + * + * @param style the style of the unordered list + */ + public void appendOpenUnorderedListTag(String style) { + StringBuffer sb = new StringBuffer(""); + text.append(sb.toString()); + } + + /** + * Appends a tag that indicates that an unordered list section ends. + * + */ + public void appendCloseUnorderedListTag() { + text.append(""); + } + + /** + * Appends a tag that indicates the start of a new paragraph. This is usually rendered + * with two carriage returns, producing a single blank line in between the two paragraphs. + * + * @param style the style of the paragraph + */ + public void appendOpenParagraphTag(String style) { + StringBuffer sb = new StringBuffer(""); + text.append(sb.toString()); + } + + /** + * Appends a tag that indicates the end of a new paragraph. This is usually rendered + * with two carriage returns, producing a single blank line in between the two paragraphs. + * + */ + public void appendCloseParagraphTag() { + text.append("

"); + } + + /** + * Appends a tag that indicates that an inlined quote section begins. + * + * @param style the style of the inlined quote + */ + public void appendOpenInlinedQuoteTag(String style) { + StringBuffer sb = new StringBuffer(""); + text.append(sb.toString()); + } + + /** + * Appends a tag that indicates that an inlined quote section ends. + * + */ + public void appendCloseInlinedQuoteTag() { + text.append(""); + } + + /** + * Appends a tag that allows to set the fonts for a span of text. + * + * @param style the style for a span of text + */ + public void appendOpenSpanTag(String style) { + StringBuffer sb = new StringBuffer(""); + text.append(sb.toString()); + } + + /** + * Appends a tag that indicates that a span section ends. + * + */ + public void appendCloseSpanTag() { + text.append(""); + } + + /** + * Appends a tag that indicates text which should be more forceful than surrounding text. + * + */ + public void appendOpenStrongTag() { + text.append(""); + } + + /** + * Appends a tag that indicates that a strong section ends. + * + */ + public void appendCloseStrongTag() { + text.append(""); + } + + /** + * Appends a given text to the XHTMLText. + * + * @param textToAppend the text to append + */ + public void append(String textToAppend) { + text.append(textToAppend); + } + + /** + * Returns the text of the XHTMLText. + * + * Note: Automatically adds the closing body tag. + * + * @return the text of the XHTMLText + */ + public String toString() { + return text.toString().concat(closeBodyTag()); + } + +} diff --git a/source/org/jivesoftware/smackx/packet/XHTMLExtension.java b/source/org/jivesoftware/smackx/packet/XHTMLExtension.java new file mode 100644 index 000000000..e2d840cb7 --- /dev/null +++ b/source/org/jivesoftware/smackx/packet/XHTMLExtension.java @@ -0,0 +1,155 @@ +/** + * $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. + * ==================================================================== + */ + +package org.jivesoftware.smackx.packet; + +import java.util.*; + +import org.jivesoftware.smack.packet.PacketExtension; + +/** + * An XHTML sub-packet, which is used by XMPP clients to exchange formatted text. The XHTML + * extension is only a subset of XHTML 1.0.

+ * + * The following link summarizes the requirements of XHTML IM: + * Valid tags.

+ * + * Warning: this is an non-standard protocol documented by + * JEP-71. Because this is a + * non-standard protocol, it is subject to change. + * + * @author Gaston Dombiak + */ +public class XHTMLExtension implements PacketExtension { + + private List bodies = new ArrayList(); + + /** + * Returns the XML element name of the extension sub-packet root element. + * Always returns "html" + * + * @return the XML element name of the packet extension. + */ + public String getElementName() { + return "html"; + } + + /** + * Returns the XML namespace of the extension sub-packet root element. + * According the specification the namespace is always "http://jabber.org/protocol/xhtml-im" + * + * @return the XML namespace of the packet extension. + */ + public String getNamespace() { + return "http://jabber.org/protocol/xhtml-im"; + } + + /** + * Returns the XML representation of a XHTML extension according the specification. + * + * Usually the XML representation will be inside of a Message XML representation like + * in the following example: + *

+     * <message id="MlIpV-4" to="gato1@gato.home" from="gato3@gato.home/Smack">
+     *     <subject>Any subject you want</subject>
+     *     <body>This message contains something interesting.</body>
+     *     <html xmlns="http://jabber.org/protocol/xhtml-im">
+     *         <body><p style='font-size:large'>This message contains something <em>interesting</em>.</p></body>
+     *     </html>
+     * </message>
+     * 
+ * + */ + public String toXML() { + StringBuffer buf = new StringBuffer(); + buf.append("<").append(getElementName()).append(" xmlns=\"").append(getNamespace()).append( + "\">"); + // Loop through all the bodies and append them to the string buffer + for (Iterator i = getBodies(); i.hasNext();) { + buf.append((String) i.next()); + } + buf.append(""); + return buf.toString(); + } + + /** + * Returns an Iterator for the bodies in the packet. + * + * @return an Iterator for the bodies in the packet. + */ + public Iterator getBodies() { + synchronized (bodies) { + return Collections.unmodifiableList(new ArrayList(bodies)).iterator(); + } + } + + /** + * Adds a body to the packet. + * + * @param body the body to add. + */ + public void addBody(String body) { + synchronized (bodies) { + bodies.add(body); + } + } + + /** + * Returns a count of the bodies in the XHTML packet. + * + * @return the number of bodies in the XHTML packet. + */ + public int getBodiesCount() { + return bodies.size(); + } + +} diff --git a/source/org/jivesoftware/smackx/provider/XHTMLExtensionProvider.java b/source/org/jivesoftware/smackx/provider/XHTMLExtensionProvider.java new file mode 100644 index 000000000..9d8e6c351 --- /dev/null +++ b/source/org/jivesoftware/smackx/provider/XHTMLExtensionProvider.java @@ -0,0 +1,110 @@ +/** + * $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. + * ==================================================================== + */ + +package org.jivesoftware.smackx.provider; + +import org.jivesoftware.smack.packet.PacketExtension; +import org.jivesoftware.smack.provider.PacketExtensionProvider; +import org.jivesoftware.smackx.packet.XHTMLExtension; +import org.xmlpull.v1.XmlPullParser; + +/** + * The XHTMLExtensionProvider parses XHTML packets. + * + * @author Gaston Dombiak + */ +public class XHTMLExtensionProvider implements PacketExtensionProvider { + + /** + * Creates a new XHTMLExtensionProvider. + * ProviderManager requires that every PacketExtensionProvider has a public, no-argument constructor + */ + public XHTMLExtensionProvider() { + } + + /** + * Parses a XHTMLExtension packet (extension sub-packet). + * + * @param parser the XML parser, positioned at the starting element of the extension. + * @return a PacketExtension. + * @throws Exception if a parsing error occurs. + */ + public PacketExtension parseExtension(XmlPullParser parser) + throws Exception { + XHTMLExtension xhtmlExtension = new XHTMLExtension(); + boolean done = false; + StringBuffer buffer = null; + while (!done) { + int eventType = parser.next(); + if (eventType == XmlPullParser.START_TAG) { + if (parser.getName().equals("body")) + buffer = new StringBuffer(); + buffer.append(parser.getText()); + } else if (eventType == XmlPullParser.TEXT) { + if (buffer != null) buffer.append(parser.getText()); + } else if (eventType == XmlPullParser.END_TAG) { + if (parser.getName().equals("body")) { + buffer.append(parser.getText()); + xhtmlExtension.addBody(buffer.toString()); + } + else if (parser.getName().equals(xhtmlExtension.getElementName())) { + done = true; + } + else + buffer.append(parser.getText()); + } + } + + return xhtmlExtension; + } + +} diff --git a/test/org/jivesoftware/smackx/XHTMLManagerTest.java b/test/org/jivesoftware/smackx/XHTMLManagerTest.java new file mode 100644 index 000000000..07a36659d --- /dev/null +++ b/test/org/jivesoftware/smackx/XHTMLManagerTest.java @@ -0,0 +1,355 @@ +/** + * $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. + * ==================================================================== + */ + +package org.jivesoftware.smackx; + +import java.util.Iterator; + +import org.jivesoftware.smack.*; +import org.jivesoftware.smack.packet.*; + +import junit.framework.TestCase; + +/** + * Test the XHTML extension using the high level API + * + * @author Gaston Dombiak + */ +public class XHTMLManagerTest extends TestCase { + + private int bodiesSent; + private int bodiesReceived; + + /** + * Constructor for XHTMLManagerTest. + * @param name + */ + public XHTMLManagerTest(String name) { + super(name); + } + + /** + * High level API test. + * This is a simple test to use with a XMPP client and check if the client receives the message + * 1. User_1 will send a message with formatted text (XHTML) to user_2 + */ + public void testSendSimpleXHTMLMessage() { + String host = "localhost"; + String server_user1 = "gato3"; + String user1 = "gato3@localhost"; + String pass1 = "gato3"; + + String user2 = "gato4@localhost"; + + XMPPConnection conn1 = null; + + try { + // Connect to the server + conn1 = new XMPPConnection(host); + // User1 logs in + conn1.login(server_user1, pass1); + + // User1 creates a chat with user2 + Chat chat1 = conn1.createChat(user2); + + // User1 creates a message to send to user2 + Message msg = chat1.createMessage(); + msg.setSubject("Any subject you want"); + msg.setBody("Hey John, this is my new green!!!!"); + + // Create an XHTMLText to send with the message + XHTMLText xhtmlText = new XHTMLText(null, null); + xhtmlText.appendOpenParagraphTag("font-size:large"); + xhtmlText.append("Hey John, this is my new "); + xhtmlText.appendOpenSpanTag("color:green"); + xhtmlText.append("green"); + xhtmlText.appendCloseSpanTag(); + xhtmlText.appendOpenEmTag(); + xhtmlText.append("!!!!"); + xhtmlText.appendCloseEmTag(); + xhtmlText.appendCloseParagraphTag(); + // Add the XHTML text to the message + XHTMLManager.addBody(msg, xhtmlText.toString()); + + // User1 sends the message that contains the XHTML to user2 + try { + chat1.sendMessage(msg); + Thread.sleep(250); + } catch (Exception e) { + fail("An error occured sending the message with XHTML"); + } + } catch (Exception e) { + fail(e.toString()); + } finally { + if (conn1 != null) + conn1.close(); + } + } + + /** + * High level API test. + * 1. User_1 will send a message with XHTML to user_2 + * 2. User_2 will receive the message and iterate over the XHTML bodies to check if everything + * is fine + * 3. User_1 will wait several seconds for an ACK from user_2, if none is received then + * something is wrong + */ + public void testSendSimpleXHTMLMessageAndDisplayReceivedXHTMLMessage() { + String host = "localhost"; + String server_user1 = "gato3"; + String user1 = "gato3@localhost"; + String pass1 = "gato3"; + + String server_user2 = "gato4"; + String user2 = "gato4@localhost"; + String pass2 = "gato4"; + + XMPPConnection conn1 = null; + XMPPConnection conn2 = null; + + try { + // Connect to the server and log in the users + conn1 = new XMPPConnection(host); + conn1.login(server_user1, pass1); + // Wait a few milliseconds between each login + Thread.sleep(250); + conn2 = new XMPPConnection(host); + conn2.login(server_user2, pass2); + + // Create a chat for each connection + Chat chat1 = conn1.createChat(user2); + final Chat chat2 = new Chat(conn2, user1, chat1.getChatID()); + + // Create a listener for the chat that will check if the received message includes + // an XHTML extension. Answer an ACK if everything is ok + PacketListener packetListener = new PacketListener() { + public void processPacket(Packet packet) { + Message message = (Message) packet; + assertTrue( + "The received message is not an XHTML Message", + XHTMLManager.isXHTMLMessage(message)); + try { + assertTrue( + "Message without XHTML bodies", + XHTMLManager.getBodies(message).hasNext()); + for (Iterator it = XHTMLManager.getBodies(message); it.hasNext();) { + String body = (String) it.next(); + System.out.println(body); + } + } catch (ClassCastException e) { + fail("ClassCastException - Most probable cause is that smack providers is misconfigured"); + } + try { + chat2.sendMessage("ok"); + } catch (Exception e) { + fail("An error occured sending ack " + e.getMessage()); + } + } + }; + chat2.addMessageListener(packetListener); + + // User1 creates a message to send to user2 + Message msg = chat1.createMessage(); + msg.setSubject("Any subject you want"); + msg.setBody("Hey John, this is my new green!!!!"); + + // Create an XHTMLText to send with the message + XHTMLText xhtmlText = new XHTMLText(null, null); + xhtmlText.appendOpenParagraphTag("font-size:large"); + xhtmlText.append("Hey John, this is my new "); + xhtmlText.appendOpenSpanTag("color:green"); + xhtmlText.append("green"); + xhtmlText.appendCloseSpanTag(); + xhtmlText.appendOpenEmTag(); + xhtmlText.append("!!!!"); + xhtmlText.appendCloseEmTag(); + xhtmlText.appendCloseParagraphTag(); + // Add the XHTML text to the message + XHTMLManager.addBody(msg, xhtmlText.toString()); + + // User1 sends the message that contains the XHTML to user2 + try { + chat1.sendMessage(msg); + } catch (Exception e) { + fail("An error occured sending the message with XHTML"); + } + // Wait for 2 seconds for a reply + msg = chat1.nextMessage(1000); + assertNotNull("No reply received", msg); + } catch (Exception e) { + fail(e.toString()); + } finally { + if (conn1 != null) + conn1.close(); + if (conn2 != null) + conn2.close(); + } + } + + /** + * Low level API test. Test a message with two XHTML bodies and several XHTML tags. + * 1. User_1 will send a message with XHTML to user_2 + * 2. User_2 will receive the message and iterate over the XHTML bodies to check if everything + * is fine + * 3. User_1 will wait several seconds for an ACK from user_2, if none is received then + * something is wrong + */ + public void testSendComplexXHTMLMessageAndDisplayReceivedXHTMLMessage() { + String host = "localhost"; + String server_user1 = "gato3"; + String user1 = "gato3@localhost"; + String pass1 = "gato3"; + + String server_user2 = "gato4"; + String user2 = "gato4@localhost"; + String pass2 = "gato4"; + + XMPPConnection conn1 = null; + XMPPConnection conn2 = null; + + try { + // Connect to the server and log in the users + conn1 = new XMPPConnection(host); + conn1.login(server_user1, pass1); + // Wait a few milliseconds between each login + Thread.sleep(250); + conn2 = new XMPPConnection(host); + conn2.login(server_user2, pass2); + + // Create a chat for each connection + Chat chat1 = conn1.createChat(user2); + final Chat chat2 = new Chat(conn2, user1, chat1.getChatID()); + + // Create a listener for the chat that will check if the received message includes + // an XHTML extension. Answer an ACK if everything is ok + PacketListener packetListener = new PacketListener() { + public void processPacket(Packet packet) { + int received = 0; + Message message = (Message) packet; + assertTrue( + "The received message is not an XHTML Message", + XHTMLManager.isXHTMLMessage(message)); + try { + assertTrue( + "Message without XHTML bodies", + XHTMLManager.getBodies(message).hasNext()); + for (Iterator it = XHTMLManager.getBodies(message); it.hasNext();) { + received++; + String body = (String) it.next(); + System.out.println(body); + } + bodiesReceived = received; + } catch (ClassCastException e) { + fail("ClassCastException - Most probable cause is that smack providers is misconfigured"); + } + } + }; + chat2.addMessageListener(packetListener); + + // User1 creates a message to send to user2 + Message msg = chat1.createMessage(); + msg.setSubject("Any subject you want"); + msg.setBody("awesome! As Emerson once said: A foolish consistency is the hobgoblin of little minds."); + + // Create an XHTMLText to send with the message (in Spanish) + XHTMLText xhtmlText = new XHTMLText(null, "es-ES"); + xhtmlText.appendOpenHeaderTag(1, null); + xhtmlText.append("impresionante!"); + xhtmlText.appendCloseHeaderTag(1); + xhtmlText.appendOpenParagraphTag(null); + xhtmlText.append("Como Emerson dijo una vez:"); + xhtmlText.appendCloseParagraphTag(); + xhtmlText.appendOpenBlockQuoteTag(null); + xhtmlText.appendOpenParagraphTag(null); + xhtmlText.append("Una consistencia ridícula es el espantajo de mentes pequeñas."); + xhtmlText.appendCloseParagraphTag(); + xhtmlText.appendCloseBlockQuoteTag(); + // Add the XHTML text to the message + XHTMLManager.addBody(msg, xhtmlText.toString()); + + // Create an XHTMLText to send with the message (in English) + xhtmlText = new XHTMLText(null, "en-US"); + xhtmlText.appendOpenHeaderTag(1, null); + xhtmlText.append("awesome!"); + xhtmlText.appendCloseHeaderTag(1); + xhtmlText.appendOpenParagraphTag(null); + xhtmlText.append("As Emerson once said:"); + xhtmlText.appendCloseParagraphTag(); + xhtmlText.appendOpenBlockQuoteTag(null); + xhtmlText.appendOpenParagraphTag(null); + xhtmlText.append("A foolish consistency is the hobgoblin of little minds."); + xhtmlText.appendCloseParagraphTag(); + xhtmlText.appendCloseBlockQuoteTag(); + // Add the XHTML text to the message + XHTMLManager.addBody(msg, xhtmlText.toString()); + + // User1 sends the message that contains the XHTML to user2 + try { + bodiesSent = 2; + bodiesReceived = 0; + chat1.sendMessage(msg); + } catch (Exception e) { + fail("An error occured sending the message with XHTML"); + } + // Wait half second so that the complete test can run + Thread.sleep(500); + assertEquals("Number of sent and received XHTMP bodies does not match", bodiesSent, bodiesReceived); + } catch (Exception e) { + fail(e.toString()); + } finally { + if (conn1 != null) + conn1.close(); + if (conn2 != null) + conn2.close(); + } + } +} diff --git a/test/org/jivesoftware/smackx/packet/XHTMLExtensionTest.java b/test/org/jivesoftware/smackx/packet/XHTMLExtensionTest.java new file mode 100644 index 000000000..500006bd8 --- /dev/null +++ b/test/org/jivesoftware/smackx/packet/XHTMLExtensionTest.java @@ -0,0 +1,329 @@ +/** + * $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. + * ==================================================================== + */ + +package org.jivesoftware.smackx.packet; + +import java.util.*; + +import org.jivesoftware.smack.*; +import org.jivesoftware.smack.filter.*; +import org.jivesoftware.smack.packet.*; + +import junit.framework.TestCase; + +/** + * Test the XHTML extension using the low level API + * + * @author Gaston Dombiak + */ +public class XHTMLExtensionTest extends TestCase { + + private int bodiesSent; + private int bodiesReceived; + + /** + * Constructor for XHTMLExtensionTest. + * @param name + */ + public XHTMLExtensionTest(String name) { + super(name); + } + + /** + * Low level API test. + * This is a simple test to use with a XMPP client and check if the client receives the message + * 1. User_1 will send a message with formatted text (XHTML) to user_2 + */ + public void testSendSimpleXHTMLMessage() { + String host = "localhost"; + String server_user1 = "gato3"; + String user1 = "gato3@localhost"; + String pass1 = "gato3"; + + String user2 = "gato4@localhost"; + + XMPPConnection conn1 = null; + + try { + // Connect to the server + conn1 = new XMPPConnection(host); + // User1 logs in + conn1.login(server_user1, pass1); + + // User1 creates a chat with user2 + Chat chat1 = conn1.createChat(user2); + + // User1 creates a message to send to user2 + Message msg = chat1.createMessage(); + msg.setSubject("Any subject you want"); + msg.setBody("Hey John, this is my new green!!!!"); + // Create a XHTMLExtension Package and add it to the message + XHTMLExtension xhtmlExtension = new XHTMLExtension(); + xhtmlExtension.addBody( + "

Hey John, this is my new green!!!!

"); + msg.addExtension(xhtmlExtension); + + // User1 sends the message that contains the XHTML to user2 + try { + chat1.sendMessage(msg); + Thread.sleep(250); + } catch (Exception e) { + fail("An error occured sending the message with XHTML"); + } + } catch (Exception e) { + fail(e.toString()); + } finally { + if (conn1 != null) + conn1.close(); + } + } + + /** + * Low level API test. + * 1. User_1 will send a message with XHTML to user_2 + * 2. User_2 will receive the message and iterate over the XHTML bodies to check if everything + * is fine + * 3. User_1 will wait several seconds for an ACK from user_2, if none is received then + * something is wrong + */ + public void testSendSimpleXHTMLMessageAndDisplayReceivedXHTMLMessage() { + String host = "localhost"; + String server_user1 = "gato3"; + String user1 = "gato3@localhost"; + String pass1 = "gato3"; + + String server_user2 = "gato4"; + String user2 = "gato4@localhost"; + String pass2 = "gato4"; + + XMPPConnection conn1 = null; + XMPPConnection conn2 = null; + + try { + // Connect to the server and log in the users + conn1 = new XMPPConnection(host); + conn1.login(server_user1, pass1); + // Wait a few milliseconds between each login + Thread.sleep(250); + conn2 = new XMPPConnection(host); + conn2.login(server_user2, pass2); + + // Create a chat for each connection + Chat chat1 = conn1.createChat(user2); + final Chat chat2 = new Chat(conn2, user1, chat1.getChatID()); + + // Create a Listener that listens for Messages with the extension + //"http://jabber.org/protocol/xhtml-im" + // This listener will listen on the conn2 and answer an ACK if everything is ok + PacketFilter packetFilter = + new PacketExtensionFilter("html", "http://jabber.org/protocol/xhtml-im"); + PacketListener packetListener = new PacketListener() { + public void processPacket(Packet packet) { + Message message = (Message) packet; + assertNotNull("Body is null", message.getBody()); + try { + XHTMLExtension xhtmlExtension = + (XHTMLExtension) message.getExtension( + "html", + "http://jabber.org/protocol/xhtml-im"); + assertNotNull( + "Message without extension \"http://jabber.org/protocol/xhtml-im\"", + xhtmlExtension); + assertTrue( + "Message without XHTML bodies", + xhtmlExtension.getBodiesCount() > 0); + for (Iterator it = xhtmlExtension.getBodies(); it.hasNext();) { + String body = (String) it.next(); + System.out.println(body); + } + } catch (ClassCastException e) { + fail("ClassCastException - Most probable cause is that smack providers is misconfigured"); + } + try { + chat2.sendMessage("ok"); + } catch (Exception e) { + fail("An error occured sending ack " + e.getMessage()); + } + } + }; + conn2.addPacketListener(packetListener, packetFilter); + + // User1 creates a message to send to user2 + Message msg = chat1.createMessage(); + msg.setSubject("Any subject you want"); + msg.setBody("Hey John, this is my new green!!!!"); + // Create a XHTMLExtension Package and add it to the message + XHTMLExtension xhtmlExtension = new XHTMLExtension(); + xhtmlExtension.addBody( + "

Hey John, this is my new green!!!!

"); + msg.addExtension(xhtmlExtension); + + // User1 sends the message that contains the XHTML to user2 + try { + chat1.sendMessage(msg); + } catch (Exception e) { + fail("An error occured sending the message with XHTML"); + } + // Wait for 2 seconds for a reply + msg = chat1.nextMessage(1000); + assertNotNull("No reply received", msg); + } catch (Exception e) { + fail(e.toString()); + } finally { + if (conn1 != null) + conn1.close(); + if (conn2 != null) + conn2.close(); + } + } + + /** + * Low level API test. Test a message with two XHTML bodies and several XHTML tags. + * 1. User_1 will send a message with XHTML to user_2 + * 2. User_2 will receive the message and iterate over the XHTML bodies to check if everything + * is fine + * 3. User_1 will wait several seconds for an ACK from user_2, if none is received then + * something is wrong + */ + public void testSendComplexXHTMLMessageAndDisplayReceivedXHTMLMessage() { + String host = "localhost"; + String server_user1 = "gato3"; + String user1 = "gato3@localhost"; + String pass1 = "gato3"; + + String server_user2 = "gato4"; + String user2 = "gato4@localhost"; + String pass2 = "gato4"; + + XMPPConnection conn1 = null; + XMPPConnection conn2 = null; + + try { + // Connect to the server and log in the users + conn1 = new XMPPConnection(host); + conn1.login(server_user1, pass1); + // Wait a few milliseconds between each login + Thread.sleep(250); + conn2 = new XMPPConnection(host); + conn2.login(server_user2, pass2); + + // Create a chat for each connection + Chat chat1 = conn1.createChat(user2); + final Chat chat2 = new Chat(conn2, user1, chat1.getChatID()); + + // Create a Listener that listens for Messages with the extension + //"http://jabber.org/protocol/xhtml-im" + // This listener will listen on the conn2 and answer an ACK if everything is ok + PacketFilter packetFilter = + new PacketExtensionFilter("html", "http://jabber.org/protocol/xhtml-im"); + PacketListener packetListener = new PacketListener() { + public void processPacket(Packet packet) { + int received = 0; + Message message = (Message) packet; + assertNotNull("Body is null", message.getBody()); + try { + XHTMLExtension xhtmlExtension = + (XHTMLExtension) message.getExtension( + "html", + "http://jabber.org/protocol/xhtml-im"); + assertNotNull( + "Message without extension \"http://jabber.org/protocol/xhtml-im\"", + xhtmlExtension); + assertTrue( + "Message without XHTML bodies", + xhtmlExtension.getBodiesCount() > 0); + for (Iterator it = xhtmlExtension.getBodies(); it.hasNext();) { + received++; + System.out.println((String) it.next()); + } + bodiesReceived = received; + } catch (ClassCastException e) { + fail("ClassCastException - Most probable cause is that smack providers is misconfigured"); + } + } + }; + conn2.addPacketListener(packetListener, packetFilter); + + // User1 creates a message to send to user2 + Message msg = chat1.createMessage(); + msg.setSubject("Any subject you want"); + msg.setBody("awesome! As Emerson once said: A foolish consistency is the hobgoblin of little minds."); + // Create an XHTMLExtension and add it to the message + XHTMLExtension xhtmlExtension = new XHTMLExtension(); + xhtmlExtension.addBody( + "

impresionante!

Como Emerson dijo una vez:

Una consistencia ridícula es el espantajo de mentes pequeñas.

"); + xhtmlExtension.addBody( + "

awesome!

As Emerson once said:

A foolish consistency is the hobgoblin of little minds.

"); + msg.addExtension(xhtmlExtension); + + // User1 sends the message that contains the XHTML to user2 + try { + bodiesSent = xhtmlExtension.getBodiesCount(); + bodiesReceived = 0; + chat1.sendMessage(msg); + } catch (Exception e) { + fail("An error occured sending the message with XHTML"); + } + // Wait half second so that the complete test can run + Thread.sleep(500); + assertEquals("Number of sent and received XHTMP bodies does not match", bodiesSent, bodiesReceived); + } catch (Exception e) { + fail(e.toString()); + } finally { + if (conn1 != null) + conn1.close(); + if (conn2 != null) + conn2.close(); + } + } + +}