Author: ngn
Date: Tue Sep  8 20:27:30 2009
New Revision: 812677

URL: http://svn.apache.org/viewvc?rev=812677&view=rev
Log:
Implement discussion history (still lacking support for "seconds" and "since" 
in the history element) (VYSPER-109)

Added:
    
mina/sandbox/vysper/trunk/server/extensions/xep0045-muc/src/main/java/org/apache/vysper/xmpp/modules/extension/xep0045_muc/model/Delay.java
    
mina/sandbox/vysper/trunk/server/extensions/xep0045-muc/src/main/java/org/apache/vysper/xmpp/modules/extension/xep0045_muc/model/DiscussionHistory.java
    
mina/sandbox/vysper/trunk/server/extensions/xep0045-muc/src/main/java/org/apache/vysper/xmpp/modules/extension/xep0045_muc/model/DiscussionMessage.java
    
mina/sandbox/vysper/trunk/server/extensions/xep0045-muc/src/main/java/org/apache/vysper/xmpp/modules/extension/xep0045_muc/model/History.java
    
mina/sandbox/vysper/trunk/server/extensions/xep0045-muc/src/test/java/org/apache/vysper/xmpp/modules/extension/xep0045_muc/model/DiscussionHistoryTestCase.java
    
mina/sandbox/vysper/trunk/server/extensions/xep0045-muc/src/test/java/org/apache/vysper/xmpp/modules/extension/xep0045_muc/model/DiscussionMessageTestCase.java
Removed:
    
mina/sandbox/vysper/trunk/server/extensions/xep0045-muc/src/test/java/org/apache/vysper/xmpp/modules/extension/xep0045_muc/AbstractServerInfoDiscoTestCase.java
    
mina/sandbox/vysper/trunk/server/extensions/xep0045-muc/src/test/java/org/apache/vysper/xmpp/modules/extension/xep0045_muc/MUCServerInfoDiscoTestCase.java
Modified:
    
mina/sandbox/vysper/trunk/server/extensions/xep0045-muc/src/main/java/org/apache/vysper/xmpp/modules/extension/xep0045_muc/ServerMain.java
    
mina/sandbox/vysper/trunk/server/extensions/xep0045-muc/src/main/java/org/apache/vysper/xmpp/modules/extension/xep0045_muc/handler/MUCMessageHandler.java
    
mina/sandbox/vysper/trunk/server/extensions/xep0045-muc/src/main/java/org/apache/vysper/xmpp/modules/extension/xep0045_muc/handler/MUCPresenceHandler.java
    
mina/sandbox/vysper/trunk/server/extensions/xep0045-muc/src/main/java/org/apache/vysper/xmpp/modules/extension/xep0045_muc/model/Room.java
    
mina/sandbox/vysper/trunk/server/extensions/xep0045-muc/src/test/java/org/apache/vysper/xmpp/modules/extension/xep0045_muc/handler/MUCPresenceHandlerEnterRoomTestCase.java

Modified: 
mina/sandbox/vysper/trunk/server/extensions/xep0045-muc/src/main/java/org/apache/vysper/xmpp/modules/extension/xep0045_muc/ServerMain.java
URL: 
http://svn.apache.org/viewvc/mina/sandbox/vysper/trunk/server/extensions/xep0045-muc/src/main/java/org/apache/vysper/xmpp/modules/extension/xep0045_muc/ServerMain.java?rev=812677&r1=812676&r2=812677&view=diff
==============================================================================
--- 
mina/sandbox/vysper/trunk/server/extensions/xep0045-muc/src/main/java/org/apache/vysper/xmpp/modules/extension/xep0045_muc/ServerMain.java
 (original)
+++ 
mina/sandbox/vysper/trunk/server/extensions/xep0045-muc/src/main/java/org/apache/vysper/xmpp/modules/extension/xep0045_muc/ServerMain.java
 Tue Sep  8 20:27:30 2009
@@ -68,7 +68,7 @@
         //server.addEndpoint(new StanzaSessionFactory());
         server.setStorageProviderRegistry(providerRegistry);
 
-        server.setTLSCertificateInfo(new 
File("src/main/resources/bogus_mina_tls.cert"), "boguspw");
+        server.setTLSCertificateInfo(new 
File("src/main/config/bogus_mina_tls.cert"), "boguspw");
 
         try {
             server.start();
@@ -83,8 +83,6 @@
         server.addModule(new XmppPingModule());
         server.addModule(new PrivateDataModule());
         
-        Conference conference = new Conference("Test conference");
-        server.addModule(new MUCModule("chat.vysper.org", conference));
-
+        server.addModule(new MUCModule());
     }
 }

Modified: 
mina/sandbox/vysper/trunk/server/extensions/xep0045-muc/src/main/java/org/apache/vysper/xmpp/modules/extension/xep0045_muc/handler/MUCMessageHandler.java
URL: 
http://svn.apache.org/viewvc/mina/sandbox/vysper/trunk/server/extensions/xep0045-muc/src/main/java/org/apache/vysper/xmpp/modules/extension/xep0045_muc/handler/MUCMessageHandler.java?rev=812677&r1=812676&r2=812677&view=diff
==============================================================================
--- 
mina/sandbox/vysper/trunk/server/extensions/xep0045-muc/src/main/java/org/apache/vysper/xmpp/modules/extension/xep0045_muc/handler/MUCMessageHandler.java
 (original)
+++ 
mina/sandbox/vysper/trunk/server/extensions/xep0045-muc/src/main/java/org/apache/vysper/xmpp/modules/extension/xep0045_muc/handler/MUCMessageHandler.java
 Tue Sep  8 20:27:30 2009
@@ -116,7 +116,11 @@
                             relayStanza(occupent.getJid(), 
                                     StanzaBuilder.createClone(stanza, true, 
replaceAttributes).getFinalStanza(),
                                     serverRuntimeContext);
+                            
                         }
+                        
+                        // add to discussion history
+                        room.getHistory().append(stanza, sendingOccupant);
                     } else {
                         return createMessageErrorStanza(room.getJID(), from, 
stanza.getID(), StanzaErrorType.MODIFY, StanzaErrorCondition.FORBIDDEN, stanza);
                     }

Modified: 
mina/sandbox/vysper/trunk/server/extensions/xep0045-muc/src/main/java/org/apache/vysper/xmpp/modules/extension/xep0045_muc/handler/MUCPresenceHandler.java
URL: 
http://svn.apache.org/viewvc/mina/sandbox/vysper/trunk/server/extensions/xep0045-muc/src/main/java/org/apache/vysper/xmpp/modules/extension/xep0045_muc/handler/MUCPresenceHandler.java?rev=812677&r1=812676&r2=812677&view=diff
==============================================================================
--- 
mina/sandbox/vysper/trunk/server/extensions/xep0045-muc/src/main/java/org/apache/vysper/xmpp/modules/extension/xep0045_muc/handler/MUCPresenceHandler.java
 (original)
+++ 
mina/sandbox/vysper/trunk/server/extensions/xep0045-muc/src/main/java/org/apache/vysper/xmpp/modules/extension/xep0045_muc/handler/MUCPresenceHandler.java
 Tue Sep  8 20:27:30 2009
@@ -31,6 +31,8 @@
 import org.apache.vysper.xmpp.modules.core.base.handler.DefaultPresenceHandler;
 import 
org.apache.vysper.xmpp.modules.extension.xep0045_muc.handler.Status.StatusCode;
 import org.apache.vysper.xmpp.modules.extension.xep0045_muc.model.Conference;
+import 
org.apache.vysper.xmpp.modules.extension.xep0045_muc.model.DiscussionHistory;
+import org.apache.vysper.xmpp.modules.extension.xep0045_muc.model.History;
 import org.apache.vysper.xmpp.modules.extension.xep0045_muc.model.Occupant;
 import org.apache.vysper.xmpp.modules.extension.xep0045_muc.model.Role;
 import org.apache.vysper.xmpp.modules.extension.xep0045_muc.model.Room;
@@ -203,6 +205,11 @@
                 sendNewOccupantPresenceToExisting(newOccupant, occupant, room, 
serverRuntimeContext);
             }
             
+            // send discussion history to user
+            boolean includeJid = room.isRoomType(RoomType.NonAnonymous);
+            List<Stanza> history = 
room.getHistory().createStanzas(newOccupant, includeJid, 
History.fromStanza(stanza));
+            relayStanzas(newOccupantJid, history, serverRuntimeContext);
+            
             logger.debug("{} successfully entered room {}", newOccupantJid, 
roomJid);
         }
         return null;
@@ -401,6 +408,12 @@
 
         relayStanza(existingOccupant.getJid(), builder.getFinalStanza(), 
serverRuntimeContext);
     }
+
+    protected void relayStanzas(Entity receiver, List<Stanza> stanzas, 
ServerRuntimeContext serverRuntimeContext) {
+        for(Stanza stanza : stanzas) {
+            relayStanza(receiver, stanza, serverRuntimeContext);
+        }
+    }
     
     protected void relayStanza(Entity receiver, Stanza stanza, 
ServerRuntimeContext serverRuntimeContext) {
         try {

Added: 
mina/sandbox/vysper/trunk/server/extensions/xep0045-muc/src/main/java/org/apache/vysper/xmpp/modules/extension/xep0045_muc/model/Delay.java
URL: 
http://svn.apache.org/viewvc/mina/sandbox/vysper/trunk/server/extensions/xep0045-muc/src/main/java/org/apache/vysper/xmpp/modules/extension/xep0045_muc/model/Delay.java?rev=812677&view=auto
==============================================================================
--- 
mina/sandbox/vysper/trunk/server/extensions/xep0045-muc/src/main/java/org/apache/vysper/xmpp/modules/extension/xep0045_muc/model/Delay.java
 (added)
+++ 
mina/sandbox/vysper/trunk/server/extensions/xep0045-muc/src/main/java/org/apache/vysper/xmpp/modules/extension/xep0045_muc/model/Delay.java
 Tue Sep  8 20:27:30 2009
@@ -0,0 +1,45 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ *
+ */
+package org.apache.vysper.xmpp.modules.extension.xep0045_muc.model;
+
+import java.util.Arrays;
+import java.util.Date;
+import java.util.List;
+
+import org.apache.vysper.xmpp.addressing.Entity;
+import org.apache.vysper.xmpp.datetime.DateTimeProfile;
+import org.apache.vysper.xmpp.protocol.NamespaceURIs;
+import org.apache.vysper.xmpp.xmlfragment.Attribute;
+import org.apache.vysper.xmpp.xmlfragment.NamespaceAttribute;
+import org.apache.vysper.xmpp.xmlfragment.XMLElement;
+import org.apache.vysper.xmpp.xmlfragment.XMLFragment;
+
+public class Delay extends XMLElement {
+
+    public Delay(Entity from, Date timestamp) {
+        super("delay", null, Arrays.asList(
+            new NamespaceAttribute(NamespaceURIs.URN_XMPP_DELAY),
+            new Attribute("from", from.getFullQualifiedName()),
+            new Attribute("stamp", 
DateTimeProfile.getInstance().getDateTimeInUTC(timestamp))
+            ), (List<XMLFragment>)null);
+    }
+
+    
+}

Added: 
mina/sandbox/vysper/trunk/server/extensions/xep0045-muc/src/main/java/org/apache/vysper/xmpp/modules/extension/xep0045_muc/model/DiscussionHistory.java
URL: 
http://svn.apache.org/viewvc/mina/sandbox/vysper/trunk/server/extensions/xep0045-muc/src/main/java/org/apache/vysper/xmpp/modules/extension/xep0045_muc/model/DiscussionHistory.java?rev=812677&view=auto
==============================================================================
--- 
mina/sandbox/vysper/trunk/server/extensions/xep0045-muc/src/main/java/org/apache/vysper/xmpp/modules/extension/xep0045_muc/model/DiscussionHistory.java
 (added)
+++ 
mina/sandbox/vysper/trunk/server/extensions/xep0045-muc/src/main/java/org/apache/vysper/xmpp/modules/extension/xep0045_muc/model/DiscussionHistory.java
 Tue Sep  8 20:27:30 2009
@@ -0,0 +1,116 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ *
+ */
+package org.apache.vysper.xmpp.modules.extension.xep0045_muc.model;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import org.apache.vysper.xmpp.stanza.Stanza;
+import org.apache.vysper.xmpp.xmlfragment.Renderer;
+
+
+/**
+ * The discussion history for a room
+ *
+ * @author The Apache MINA Project ([email protected])
+ */
+public class DiscussionHistory {
+
+    public static final int DEFAULT_HISTORY_SIZE = 20;
+    
+    private int maxItems = DEFAULT_HISTORY_SIZE;
+    private DiscussionMessage subjectMessage;
+    private List<DiscussionMessage> items = new ArrayList<DiscussionMessage>();
+    
+    public void append(Stanza stanza, Occupant sender) {
+        synchronized (items) {
+            DiscussionMessage discMsg = new DiscussionMessage(stanza, sender);
+            
+            if(discMsg.hasSubject() && !discMsg.hasBody()) {
+                subjectMessage = discMsg;
+            } else {
+                items.add(discMsg);
+            }
+
+            // check if size is over limits
+            if(getSize() > maxItems) {
+                items.remove(0);
+            }
+        }
+    }
+    
+    private int getSize() {
+        int size = items.size();
+        if(subjectMessage != null) size++;
+        return size;
+    }
+    
+    public List<Stanza> createStanzas(Occupant receiver, boolean includeJid, 
+            History history) {
+        
+        int maxstanzas = history != null && history.getMaxStanzas() != null ? 
history.getMaxStanzas() : -1;
+        int maxchars = history != null && history.getMaxChars() != null ? 
history.getMaxChars() : -1;
+        int seconds = history != null && history.getSeconds() != null ? 
history.getSeconds() : -1;
+        
+        List<Stanza> stanzas = new ArrayList<Stanza>();
+        
+        if(maxchars == 0 || maxstanzas == 0 || seconds == 0) {
+            // quick return for no-stanza requests
+        } else {
+            int counter = 0;
+            int totalChars = 0;
+            
+            List<DiscussionMessage> itemsWithSubject = new 
ArrayList<DiscussionMessage>(items);
+            // add subject if one is provided
+            if(subjectMessage != null) {
+                itemsWithSubject.add(subjectMessage);
+            }
+            
+            
+            // now add all messages, as long as the predicated are fulfilled
+            // first, do this in reverse order so that older messages are 
filtered out
+            for(int i = itemsWithSubject.size() - 1; i > -1; i--) {
+                DiscussionMessage item = itemsWithSubject.get(i);
+                Stanza stanza = item.createStanza(receiver, includeJid); 
+                counter++;
+
+                // only count chars if needed
+                if(maxchars != -1) {
+                    totalChars += new Renderer(stanza).getComplete().length();
+                    
+                    if(totalChars > maxchars) {
+                        break;
+                    }
+                }
+                
+                // checks after this line will include the last stanza
+                stanzas.add(stanza);
+                if(maxstanzas != -1 && counter == maxstanzas) {
+                    // max number of stanzas reached, return
+                    break;
+                }
+            }
+        }
+        // reverse list so that the oldest message is first
+        Collections.reverse(stanzas);
+        return stanzas;
+    }
+}

Added: 
mina/sandbox/vysper/trunk/server/extensions/xep0045-muc/src/main/java/org/apache/vysper/xmpp/modules/extension/xep0045_muc/model/DiscussionMessage.java
URL: 
http://svn.apache.org/viewvc/mina/sandbox/vysper/trunk/server/extensions/xep0045-muc/src/main/java/org/apache/vysper/xmpp/modules/extension/xep0045_muc/model/DiscussionMessage.java?rev=812677&view=auto
==============================================================================
--- 
mina/sandbox/vysper/trunk/server/extensions/xep0045-muc/src/main/java/org/apache/vysper/xmpp/modules/extension/xep0045_muc/model/DiscussionMessage.java
 (added)
+++ 
mina/sandbox/vysper/trunk/server/extensions/xep0045-muc/src/main/java/org/apache/vysper/xmpp/modules/extension/xep0045_muc/model/DiscussionMessage.java
 Tue Sep  8 20:27:30 2009
@@ -0,0 +1,89 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ *
+ */
+package org.apache.vysper.xmpp.modules.extension.xep0045_muc.model;
+
+import java.util.Date;
+
+import org.apache.vysper.xmpp.addressing.Entity;
+import org.apache.vysper.xmpp.addressing.EntityImpl;
+import org.apache.vysper.xmpp.stanza.Stanza;
+import org.apache.vysper.xmpp.stanza.StanzaBuilder;
+
+public class DiscussionMessage {
+
+    private Stanza message;
+    private String fromNick;
+    private Date timestamp;
+    
+    public DiscussionMessage(Stanza stanza, Occupant from) {
+        this(stanza, from, new Date());
+    }
+
+    public DiscussionMessage(Stanza stanza, Occupant from, Date date) {
+        this.message = stanza;
+        this.fromNick = from.getName();
+        
+        this.timestamp = (Date) date.clone();
+    }
+    
+    public Date getTimestamp() {
+        return timestamp;
+    }
+
+    public String getNick() {
+        return fromNick;
+    }
+    
+    public Stanza createStanza(Occupant receiver, boolean includeJid) {
+
+//        <message
+//            from='[email protected]/secondwitch'
+//            to='[email protected]/broom'
+//            type='groupchat'>
+//          <body>Thrice and once the hedge-pig whined.</body>
+//          <delay xmlns='urn:xmpp:delay'
+//             from='[email protected]/laptop'
+//             stamp='2002-10-13T23:58:43Z'/>
+//        </message>
+        
+        Entity roomJid = message.getTo();
+        StanzaBuilder builder = StanzaBuilder.createForward(message, new 
EntityImpl(roomJid, fromNick), receiver.getJid());
+
+        Entity delayFrom;
+        if(includeJid) {
+            delayFrom = message.getFrom();
+        } else {
+            delayFrom = new EntityImpl(roomJid, fromNick);
+        }
+        Delay delay = new Delay(delayFrom, timestamp);
+        builder.addPreparedElement(delay);
+        
+        return builder.getFinalStanza();
+    }
+    
+    public boolean hasSubject() {
+        return !message.getInnerElementsNamed("subject").isEmpty();
+    }
+
+    public boolean hasBody() {
+        return !message.getInnerElementsNamed("body").isEmpty();
+    }
+
+}

Added: 
mina/sandbox/vysper/trunk/server/extensions/xep0045-muc/src/main/java/org/apache/vysper/xmpp/modules/extension/xep0045_muc/model/History.java
URL: 
http://svn.apache.org/viewvc/mina/sandbox/vysper/trunk/server/extensions/xep0045-muc/src/main/java/org/apache/vysper/xmpp/modules/extension/xep0045_muc/model/History.java?rev=812677&view=auto
==============================================================================
--- 
mina/sandbox/vysper/trunk/server/extensions/xep0045-muc/src/main/java/org/apache/vysper/xmpp/modules/extension/xep0045_muc/model/History.java
 (added)
+++ 
mina/sandbox/vysper/trunk/server/extensions/xep0045-muc/src/main/java/org/apache/vysper/xmpp/modules/extension/xep0045_muc/model/History.java
 Tue Sep  8 20:27:30 2009
@@ -0,0 +1,103 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ *
+ */
+package org.apache.vysper.xmpp.modules.extension.xep0045_muc.model;
+
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+
+import org.apache.vysper.xmpp.datetime.DateTimeProfile;
+import org.apache.vysper.xmpp.protocol.NamespaceURIs;
+import org.apache.vysper.xmpp.stanza.Stanza;
+import org.apache.vysper.xmpp.xmlfragment.Attribute;
+import org.apache.vysper.xmpp.xmlfragment.XMLElement;
+import org.apache.vysper.xmpp.xmlfragment.XMLFragment;
+import org.apache.vysper.xmpp.xmlfragment.XMLSemanticError;
+
+public class History extends XMLElement {
+
+    
+    
+    private static final String ELEMENT_HISTORY = "history";
+    private static final String ATTRIBUTE_SINCE = "since";
+    private static final String ATTRIBUTE_SECONDS = "seconds";
+    private static final String ATTRIBUTE_MAXCHARS = "maxchars";
+    private static final String ATTRIBUTE_MAXSTANZAS = "maxstanzas";
+
+    public static History fromStanza(Stanza stanza) {
+        // history is in a x element in the MUC namespace
+        try {
+            XMLElement xElm = stanza.getSingleInnerElementsNamed("x", 
NamespaceURIs.XEP0045_MUC);
+            if(xElm != null) {
+                XMLElement historyElm = 
xElm.getSingleInnerElementsNamed("history");
+                if(historyElm != null) {
+                    return new History(historyElm);
+                }
+            }
+            
+            // history element not found
+            return null;
+        } catch (XMLSemanticError e) {
+            throw new IllegalArgumentException("Invalid stanza", e);
+        }
+    }
+    
+    public History(XMLElement elm) {
+        super(ELEMENT_HISTORY, null, elm.getAttributes(), 
(List<XMLFragment>)null);
+    }
+    
+    public History(Integer maxstanzas, Integer maxchars, Integer seconds, Date 
since) {
+        super(ELEMENT_HISTORY, null, createAttributes(maxstanzas, maxchars, 
seconds, since), (List<XMLFragment>)null);
+    }
+
+    private static List<Attribute> createAttributes(Integer maxstanzas, 
Integer maxchars, Integer seconds, Date since) {
+        List<Attribute> attributes = new ArrayList<Attribute>();
+        if(maxstanzas != null) attributes.add(new 
Attribute(ATTRIBUTE_MAXSTANZAS, maxstanzas.toString()));
+        if(maxchars != null) attributes.add(new Attribute(ATTRIBUTE_MAXCHARS, 
maxchars.toString()));
+        if(seconds != null) attributes.add(new Attribute(ATTRIBUTE_SECONDS, 
seconds.toString()));
+        if(since != null) attributes.add(new Attribute(ATTRIBUTE_SINCE, 
DateTimeProfile.getInstance().getDateTimeInUTC(since)));
+        return attributes;
+    }
+    
+    private Integer getAttributeIntValue(String name) {
+        String value = getAttributeValue(name);
+        if(value != null && value.trim().length() > 0) {
+            return Integer.valueOf(value);
+        } else {
+            return null;
+        }
+    }
+    
+    public Integer getMaxStanzas() {
+        return getAttributeIntValue(ATTRIBUTE_MAXSTANZAS);
+    }
+
+    public Integer getMaxChars() {
+        return getAttributeIntValue(ATTRIBUTE_MAXCHARS);
+    }
+
+    public Integer getSeconds() {
+        return getAttributeIntValue(ATTRIBUTE_SECONDS);
+    }
+
+    // TODO implement
+//    public Integer getSince() {
+//    }
+}

Modified: 
mina/sandbox/vysper/trunk/server/extensions/xep0045-muc/src/main/java/org/apache/vysper/xmpp/modules/extension/xep0045_muc/model/Room.java
URL: 
http://svn.apache.org/viewvc/mina/sandbox/vysper/trunk/server/extensions/xep0045-muc/src/main/java/org/apache/vysper/xmpp/modules/extension/xep0045_muc/model/Room.java?rev=812677&r1=812676&r2=812677&view=diff
==============================================================================
--- 
mina/sandbox/vysper/trunk/server/extensions/xep0045-muc/src/main/java/org/apache/vysper/xmpp/modules/extension/xep0045_muc/model/Room.java
 (original)
+++ 
mina/sandbox/vysper/trunk/server/extensions/xep0045-muc/src/main/java/org/apache/vysper/xmpp/modules/extension/xep0045_muc/model/Room.java
 Tue Sep  8 20:27:30 2009
@@ -54,6 +54,7 @@
     private Entity jid;
     private String name;
     private String password;
+    private DiscussionHistory history = new DiscussionHistory();
     
     // keep in a map to allow for quick access
     private Map<Entity, Occupant> occupants = new ConcurrentHashMap<Entity, 
Occupant>();
@@ -188,4 +189,8 @@
         this.password = password;
     }
     
+    public DiscussionHistory getHistory() {
+        return history;
+    }
+    
 }

Modified: 
mina/sandbox/vysper/trunk/server/extensions/xep0045-muc/src/test/java/org/apache/vysper/xmpp/modules/extension/xep0045_muc/handler/MUCPresenceHandlerEnterRoomTestCase.java
URL: 
http://svn.apache.org/viewvc/mina/sandbox/vysper/trunk/server/extensions/xep0045-muc/src/test/java/org/apache/vysper/xmpp/modules/extension/xep0045_muc/handler/MUCPresenceHandlerEnterRoomTestCase.java?rev=812677&r1=812676&r2=812677&view=diff
==============================================================================
--- 
mina/sandbox/vysper/trunk/server/extensions/xep0045-muc/src/test/java/org/apache/vysper/xmpp/modules/extension/xep0045_muc/handler/MUCPresenceHandlerEnterRoomTestCase.java
 (original)
+++ 
mina/sandbox/vysper/trunk/server/extensions/xep0045-muc/src/test/java/org/apache/vysper/xmpp/modules/extension/xep0045_muc/handler/MUCPresenceHandlerEnterRoomTestCase.java
 Tue Sep  8 20:27:30 2009
@@ -4,7 +4,10 @@
 import java.util.List;
 
 import org.apache.vysper.xmpp.addressing.Entity;
+import org.apache.vysper.xmpp.modules.extension.xep0045_muc.model.Affiliation;
+import org.apache.vysper.xmpp.modules.extension.xep0045_muc.model.History;
 import org.apache.vysper.xmpp.modules.extension.xep0045_muc.model.Occupant;
+import org.apache.vysper.xmpp.modules.extension.xep0045_muc.model.Role;
 import org.apache.vysper.xmpp.modules.extension.xep0045_muc.model.Room;
 import org.apache.vysper.xmpp.modules.extension.xep0045_muc.model.RoomType;
 import org.apache.vysper.xmpp.protocol.NamespaceURIs;
@@ -13,6 +16,8 @@
 import org.apache.vysper.xmpp.protocol.StanzaHandler;
 import org.apache.vysper.xmpp.server.SessionContext;
 import org.apache.vysper.xmpp.server.TestSessionContext;
+import org.apache.vysper.xmpp.stanza.MessageStanza;
+import org.apache.vysper.xmpp.stanza.MessageStanzaType;
 import org.apache.vysper.xmpp.stanza.PresenceStanza;
 import org.apache.vysper.xmpp.stanza.Stanza;
 import org.apache.vysper.xmpp.stanza.StanzaBuilder;
@@ -26,10 +31,10 @@
 public class MUCPresenceHandlerEnterRoomTestCase extends 
AbstractMUCHandlerTestCase {
 
     private Stanza enterRoom(Entity occupantJid, Entity roomJid) throws 
ProtocolException {
-        return enterRoom(occupantJid, roomJid, null);
+        return enterRoom(occupantJid, roomJid, null, null);
     }
     
-    private Stanza enterRoom(Entity occupantJid, Entity roomJid, String 
password) throws ProtocolException {
+    private Stanza enterRoom(Entity occupantJid, Entity roomJid, String 
password, History history) throws ProtocolException {
         SessionContext userSessionContext;
         if(occupantJid.equals(OCCUPANT1_JID)) {
             userSessionContext = sessionContext;
@@ -42,6 +47,9 @@
         if(password != null) {
             
stanzaBuilder.startInnerElement("password").addText(password).endInnerElement();
         }
+        if(history != null) {
+            stanzaBuilder.addPreparedElement(history);
+        }
         
         stanzaBuilder.endInnerElement();
         Stanza presenceStanza = stanzaBuilder.getFinalStanza();
@@ -115,7 +123,7 @@
         room.setPassword("secret");
 
         // no error should be returned
-        assertNull(enterRoom(OCCUPANT1_JID, ROOM2_JID_WITH_NICK, "secret"));
+        assertNull(enterRoom(OCCUPANT1_JID, ROOM2_JID_WITH_NICK, "secret", 
null));
         assertEquals(1, room.getOccupants().size());
     }
     
@@ -183,4 +191,41 @@
         assertEquals("110", statusElements.get(1).getAttributeValue("code"));
         
     }
+
+    public void testDiscussionHistory() throws Exception {
+        // add some messages
+        Room room = conference.findOrCreateRoom(ROOM1_JID, "Room 1");
+        
room.getHistory().append(StanzaBuilder.createMessageStanza(OCCUPANT2_JID, 
ROOM1_JID, MessageStanzaType.GROUPCHAT, null, "Body").getFinalStanza(), 
+                new Occupant(OCCUPANT2_JID, "nick2", Affiliation.None, 
Role.Participant));
+        
room.getHistory().append(StanzaBuilder.createMessageStanza(OCCUPANT2_JID, 
ROOM1_JID, MessageStanzaType.GROUPCHAT, null, "Body2").getFinalStanza(), 
+                new Occupant(OCCUPANT2_JID, "nick2", Affiliation.None, 
Role.Participant));
+        
room.getHistory().append(StanzaBuilder.createMessageStanza(OCCUPANT2_JID, 
ROOM1_JID, MessageStanzaType.GROUPCHAT, null, "Body3").getFinalStanza(), 
+                new Occupant(OCCUPANT2_JID, "nick2", Affiliation.None, 
Role.Participant));
+        
+        // now, let user 1 enter room
+        enterRoom(OCCUPANT1_JID, ROOM1_JID_WITH_NICK, null, new History(2, 
null, null, null));
+
+        Stanza stanza = occupant1Queue.getNext();
+        // first stanza should be room presence
+        assertNotNull(stanza);
+        assertEquals("presence", stanza.getName());
+        
+        stanza = occupant1Queue.getNext();
+        // here we get the message history
+        assertNotNull(stanza);
+        assertEquals("message", stanza.getName());
+        MessageStanza msgStanza = (MessageStanza) 
MessageStanza.getWrapper(stanza);
+        assertEquals("Body2", msgStanza.getBody(null));
+
+        stanza = occupant1Queue.getNext();
+        // first stanza should be room presence
+        assertNotNull(stanza);
+        assertEquals("message", stanza.getName());
+        msgStanza = (MessageStanza) MessageStanza.getWrapper(stanza);
+        assertEquals("Body3", msgStanza.getBody(null));
+        
+        // we only requested two messages
+        assertNull(occupant1Queue.getNext());
+}
+
 }

Added: 
mina/sandbox/vysper/trunk/server/extensions/xep0045-muc/src/test/java/org/apache/vysper/xmpp/modules/extension/xep0045_muc/model/DiscussionHistoryTestCase.java
URL: 
http://svn.apache.org/viewvc/mina/sandbox/vysper/trunk/server/extensions/xep0045-muc/src/test/java/org/apache/vysper/xmpp/modules/extension/xep0045_muc/model/DiscussionHistoryTestCase.java?rev=812677&view=auto
==============================================================================
--- 
mina/sandbox/vysper/trunk/server/extensions/xep0045-muc/src/test/java/org/apache/vysper/xmpp/modules/extension/xep0045_muc/model/DiscussionHistoryTestCase.java
 (added)
+++ 
mina/sandbox/vysper/trunk/server/extensions/xep0045-muc/src/test/java/org/apache/vysper/xmpp/modules/extension/xep0045_muc/model/DiscussionHistoryTestCase.java
 Tue Sep  8 20:27:30 2009
@@ -0,0 +1,136 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ *
+ */
+package org.apache.vysper.xmpp.modules.extension.xep0045_muc.model;
+
+import java.util.List;
+
+import junit.framework.TestCase;
+
+import org.apache.vysper.TestUtil;
+import org.apache.vysper.xmpp.addressing.Entity;
+import org.apache.vysper.xmpp.addressing.EntityImpl;
+import org.apache.vysper.xmpp.stanza.MessageStanza;
+import org.apache.vysper.xmpp.stanza.MessageStanzaType;
+import org.apache.vysper.xmpp.stanza.Stanza;
+import org.apache.vysper.xmpp.stanza.StanzaBuilder;
+import org.apache.vysper.xmpp.xmlfragment.Renderer;
+
+/**
+ * 
+ * @author The Apache MINA Project ([email protected])
+ */
+public class DiscussionHistoryTestCase extends TestCase {
+
+    private static final String NICK = "nick";
+    private static final String BODY = "Body";
+    private static final String SUBJECT = "Subject";
+    
+    private static final Entity FROM = 
TestUtil.parseUnchecked("[email protected]/res");
+    private static final Entity RECEIVER = 
TestUtil.parseUnchecked("[email protected]/res");
+    private static final Entity ROOM_JID = 
TestUtil.parseUnchecked("[email protected]");
+
+    private static final Occupant FROM_OCCUPANT = new Occupant(FROM, NICK, 
Affiliation.None, Role.Visitor);
+    private static final Occupant RECEIVER_OCCUPANT = new Occupant(RECEIVER, 
"nick2", Affiliation.None, Role.Visitor);
+    private DiscussionHistory history;
+
+    
+    @Override
+    protected void setUp() throws Exception {
+        history = new DiscussionHistory();
+        
+        // add some messages to the history, one more than is handled
+        for(int i = 0; i<DiscussionHistory.DEFAULT_HISTORY_SIZE + 1; i++) {
+            history.append(
+                    StanzaBuilder.createMessageStanza(FROM, ROOM_JID, 
MessageStanzaType.GROUPCHAT, null, BODY).getFinalStanza(),
+                    FROM_OCCUPANT);
+        }
+        
+        // add a subject message
+        history.append(
+                StanzaBuilder.createMessageStanza(FROM, ROOM_JID, 
MessageStanzaType.GROUPCHAT, null, null).
+                
startInnerElement("subject").addText(SUBJECT).endInnerElement().getFinalStanza(),
+                FROM_OCCUPANT);
+    }
+
+    public void testGetAllStanzas() throws Exception {
+        List<Stanza> stanzas = history.createStanzas(RECEIVER_OCCUPANT, true, 
new History(null, null, null, null));
+        
+        assertStanzas(stanzas, DiscussionHistory.DEFAULT_HISTORY_SIZE);
+    }
+
+    public void testGetAllStanzasNullHistory() throws Exception {
+        List<Stanza> stanzas = history.createStanzas(RECEIVER_OCCUPANT, true, 
null);
+        
+        assertStanzas(stanzas, DiscussionHistory.DEFAULT_HISTORY_SIZE);
+    }
+
+    
+    public void testThreeStanzas() throws Exception {
+        List<Stanza> stanzas = history.createStanzas(RECEIVER_OCCUPANT, true, 
new History(3, null, null, null));
+        assertStanzas(stanzas, 3);
+    }
+    
+    public void testZeroStanzas() throws Exception {
+        List<Stanza> stanzas = history.createStanzas(RECEIVER_OCCUPANT, true, 
new History(0, null, null, null));
+        
+        assertStanzas(stanzas, 0);
+    }
+
+    public void test500CharStanzas() throws Exception {
+        List<Stanza> stanzas = history.createStanzas(RECEIVER_OCCUPANT, true, 
new History(null, 500, null, null));
+        
+        // 2 stanzas should fit in 500 chars
+        assertStanzas(stanzas, 2);
+    }
+
+    public void test0CharStanzas() throws Exception {
+        List<Stanza> stanzas = history.createStanzas(RECEIVER_OCCUPANT, true, 
new History(null, 0, null, null));
+        
+        assertStanzas(stanzas, 0);
+    }
+
+    
+    private void assertStanzas(List<Stanza> stanzas, int expectedSize) throws 
Exception {
+        assertEquals(expectedSize, stanzas.size());
+
+        if(expectedSize > 0) {
+            
+            for(int i = 1; i<expectedSize - 1; i++) {
+                Stanza stanza = stanzas.get(i);
+                assertStanza(stanza, BODY, null);
+            }
+
+            // first check subject message
+            assertStanza(stanzas.get(expectedSize - 1), null, SUBJECT);
+        }
+    }
+    
+    private void assertStanza(Stanza stanza, String expectedBody, String 
expectedSubject) throws Exception {
+        assertNotNull(stanza);
+        MessageStanza msgStanza = (MessageStanza) 
MessageStanza.getWrapper(stanza);
+        
+        assertEquals(new EntityImpl(ROOM_JID, NICK), msgStanza.getFrom());
+        assertEquals(RECEIVER, msgStanza.getTo());
+        assertEquals("groupchat", msgStanza.getType());
+        assertEquals(expectedBody, msgStanza.getBody(null));
+        assertEquals(expectedSubject, msgStanza.getSubject(null));
+        assertEquals(1, msgStanza.getInnerElementsNamed("delay").size());
+    }
+}

Added: 
mina/sandbox/vysper/trunk/server/extensions/xep0045-muc/src/test/java/org/apache/vysper/xmpp/modules/extension/xep0045_muc/model/DiscussionMessageTestCase.java
URL: 
http://svn.apache.org/viewvc/mina/sandbox/vysper/trunk/server/extensions/xep0045-muc/src/test/java/org/apache/vysper/xmpp/modules/extension/xep0045_muc/model/DiscussionMessageTestCase.java?rev=812677&view=auto
==============================================================================
--- 
mina/sandbox/vysper/trunk/server/extensions/xep0045-muc/src/test/java/org/apache/vysper/xmpp/modules/extension/xep0045_muc/model/DiscussionMessageTestCase.java
 (added)
+++ 
mina/sandbox/vysper/trunk/server/extensions/xep0045-muc/src/test/java/org/apache/vysper/xmpp/modules/extension/xep0045_muc/model/DiscussionMessageTestCase.java
 Tue Sep  8 20:27:30 2009
@@ -0,0 +1,94 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ *
+ */
+package org.apache.vysper.xmpp.modules.extension.xep0045_muc.model;
+
+import java.util.Date;
+
+import junit.framework.TestCase;
+
+import org.apache.vysper.TestUtil;
+import org.apache.vysper.xmpp.addressing.Entity;
+import org.apache.vysper.xmpp.addressing.EntityImpl;
+import org.apache.vysper.xmpp.datetime.DateTimeProfile;
+import org.apache.vysper.xmpp.stanza.MessageStanza;
+import org.apache.vysper.xmpp.stanza.MessageStanzaType;
+import org.apache.vysper.xmpp.stanza.Stanza;
+import org.apache.vysper.xmpp.stanza.StanzaBuilder;
+import org.apache.vysper.xmpp.xmlfragment.XMLElement;
+
+/**
+ * 
+ * @author The Apache MINA Project ([email protected])
+ */
+public class DiscussionMessageTestCase extends TestCase {
+
+    private static final String NICK = "nick";
+    private static final String BODY = "Body";
+    private static final String SUBJECT = "Subject";
+    private static final Date TIMESTAMP = new Date();
+
+    
+    private static final Entity FROM = 
TestUtil.parseUnchecked("[email protected]/res");
+    private static final Entity ROOM_JID = 
TestUtil.parseUnchecked("[email protected]");
+
+    private static final Occupant FROM_OCCUPANT = new Occupant(FROM, NICK, 
Affiliation.None, Role.Visitor);
+    
+    public void testSubjectMessage() {
+        StanzaBuilder builder = StanzaBuilder.createMessageStanza(FROM, 
ROOM_JID, null, null);
+        
builder.startInnerElement("subject").addText(SUBJECT).endInnerElement();
+        
+        DiscussionMessage item = new 
DiscussionMessage(builder.getFinalStanza(), FROM_OCCUPANT, TIMESTAMP);
+        assertEquals(NICK, item.getNick());
+        assertEquals(TIMESTAMP, item.getTimestamp());
+        assertFalse(item.hasBody());
+        assertTrue(item.hasSubject());
+    }
+    
+    
+    public void testBodyMessage() {
+        StanzaBuilder builder = StanzaBuilder.createMessageStanza(FROM, 
ROOM_JID, null, BODY);
+        
+        DiscussionMessage item = new 
DiscussionMessage(builder.getFinalStanza(), FROM_OCCUPANT, TIMESTAMP);
+        assertEquals(NICK, item.getNick());
+        assertEquals(TIMESTAMP, item.getTimestamp());
+        assertTrue(item.hasBody());
+        assertFalse(item.hasSubject());
+    }
+
+    public void testCreateStanza() throws Exception {
+        StanzaBuilder builder = StanzaBuilder.createMessageStanza(FROM, 
ROOM_JID, MessageStanzaType.GROUPCHAT, null, BODY);
+        Stanza inStanza = builder.getFinalStanza();
+        DiscussionMessage item = new DiscussionMessage(inStanza, 
FROM_OCCUPANT, TIMESTAMP);
+        
+        Entity to = TestUtil.parseUnchecked("[email protected]/res");
+        Occupant toOccupant = new Occupant(to, "nick 2", Affiliation.None, 
Role.Visitor);
+        MessageStanza outStanza = (MessageStanza) 
MessageStanza.getWrapper(item.createStanza(toOccupant, true));
+        
+        assertEquals(to, outStanza.getTo());
+        assertEquals(new EntityImpl(ROOM_JID, NICK), outStanza.getFrom());
+        assertEquals("groupchat", outStanza.getType());
+        assertEquals(BODY, outStanza.getBody(null));
+        
+        XMLElement delayElm = outStanza.getInnerElements().get(1);
+        assertEquals(FROM.getFullQualifiedName(), 
delayElm.getAttributeValue("from"));
+        
assertEquals(DateTimeProfile.getInstance().getDateTimeInUTC(TIMESTAMP), 
delayElm.getAttributeValue("stamp"));
+        
+    }
+}


Reply via email to