You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@labs.apache.org by be...@apache.org on 2007/05/31 00:07:44 UTC

svn commit: r542950 [3/4] - in /labs/vysper: ./ lib/ src/ src/main/ src/main/config/ src/main/java/ src/main/java/org/ src/main/java/org/apache/ src/main/java/org/apache/vysper/ src/main/java/org/apache/vysper/xmpp/ src/main/java/org/apache/vysper/xmpp...

Added: labs/vysper/src/main/java/org/apache/vysper/xmpp/protocol/worker/StartedProtocolWorker.java
URL: http://svn.apache.org/viewvc/labs/vysper/src/main/java/org/apache/vysper/xmpp/protocol/worker/StartedProtocolWorker.java?view=auto&rev=542950
==============================================================================
--- labs/vysper/src/main/java/org/apache/vysper/xmpp/protocol/worker/StartedProtocolWorker.java (added)
+++ labs/vysper/src/main/java/org/apache/vysper/xmpp/protocol/worker/StartedProtocolWorker.java Wed May 30 15:07:38 2007
@@ -0,0 +1,40 @@
+/***********************************************************************
+ * Copyright (c) 2006-2007 The Apache Software Foundation.             *
+ * All rights reserved.                                                *
+ * ------------------------------------------------------------------- *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you *
+ * may not use this file except in compliance with the License. You    *
+ * may obtain a copy of the License at:                                *
+ *                                                                     *
+ *     http://www.apache.org/licenses/LICENSE-2.0                      *
+ *                                                                     *
+ * Unless required by applicable law or agreed to in writing, software *
+ * distributed under the License is distributed on an "AS IS" BASIS,   *
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or     *
+ * implied.  See the License for the specific language governing       *
+ * permissions and limitations under the License.                      *
+ ***********************************************************************/
+
+package org.apache.vysper.xmpp.protocol.worker;
+
+import org.apache.vysper.xmpp.protocol.ResponseWriter;
+import org.apache.vysper.xmpp.protocol.SessionStateHolder;
+import org.apache.vysper.xmpp.protocol.StanzaHandler;
+import org.apache.vysper.xmpp.server.SessionContext;
+import org.apache.vysper.xmpp.server.SessionState;
+import org.apache.vysper.xmpp.stanza.Stanza;
+
+/**
+ */
+public class StartedProtocolWorker extends AbstractStateAwareProtocolWorker {
+
+    public SessionState getHandledState() {
+        return SessionState.STARTED;
+    }
+
+    protected boolean checkState(SessionContext sessionContext, SessionStateHolder sessionStateHolder, Stanza stanza, StanzaHandler stanzaHandler, ResponseWriter responseWriter) {
+        // TODO allow authenticating dictionary
+        responseWriter.writeStreamNotOpenedError(sessionContext); // TODO remove this temporary solution
+        return false;
+    }
+}
\ No newline at end of file

Added: labs/vysper/src/main/java/org/apache/vysper/xmpp/protocol/worker/UnconnectedProtocolWorker.java
URL: http://svn.apache.org/viewvc/labs/vysper/src/main/java/org/apache/vysper/xmpp/protocol/worker/UnconnectedProtocolWorker.java?view=auto&rev=542950
==============================================================================
--- labs/vysper/src/main/java/org/apache/vysper/xmpp/protocol/worker/UnconnectedProtocolWorker.java (added)
+++ labs/vysper/src/main/java/org/apache/vysper/xmpp/protocol/worker/UnconnectedProtocolWorker.java Wed May 30 15:07:38 2007
@@ -0,0 +1,39 @@
+/***********************************************************************
+ * Copyright (c) 2006-2007 The Apache Software Foundation.             *
+ * All rights reserved.                                                *
+ * ------------------------------------------------------------------- *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you *
+ * may not use this file except in compliance with the License. You    *
+ * may obtain a copy of the License at:                                *
+ *                                                                     *
+ *     http://www.apache.org/licenses/LICENSE-2.0                      *
+ *                                                                     *
+ * Unless required by applicable law or agreed to in writing, software *
+ * distributed under the License is distributed on an "AS IS" BASIS,   *
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or     *
+ * implied.  See the License for the specific language governing       *
+ * permissions and limitations under the License.                      *
+ ***********************************************************************/
+
+package org.apache.vysper.xmpp.protocol.worker;
+
+import org.apache.vysper.xmpp.protocol.ResponseWriter;
+import org.apache.vysper.xmpp.protocol.SessionStateHolder;
+import org.apache.vysper.xmpp.protocol.StanzaHandler;
+import org.apache.vysper.xmpp.server.SessionContext;
+import org.apache.vysper.xmpp.server.SessionState;
+import org.apache.vysper.xmpp.stanza.Stanza;
+
+/**
+ */
+public class UnconnectedProtocolWorker extends AbstractStateAwareProtocolWorker {
+
+    public SessionState getHandledState() {
+        return SessionState.UNCONNECTED;
+    }
+
+    protected boolean checkState(SessionContext sessionContext, SessionStateHolder sessionStateHolder, Stanza stanza, StanzaHandler stanzaHandler, ResponseWriter responseWriter) {
+        // TODO
+        return true;
+    }
+}
\ No newline at end of file

Added: labs/vysper/src/main/java/org/apache/vysper/xmpp/server/DefaultServerRuntimeContext.java
URL: http://svn.apache.org/viewvc/labs/vysper/src/main/java/org/apache/vysper/xmpp/server/DefaultServerRuntimeContext.java?view=auto&rev=542950
==============================================================================
--- labs/vysper/src/main/java/org/apache/vysper/xmpp/server/DefaultServerRuntimeContext.java (added)
+++ labs/vysper/src/main/java/org/apache/vysper/xmpp/server/DefaultServerRuntimeContext.java Wed May 30 15:07:38 2007
@@ -0,0 +1,71 @@
+/***********************************************************************
+ * Copyright (c) 2006-2007 The Apache Software Foundation.             *
+ * All rights reserved.                                                *
+ * ------------------------------------------------------------------- *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you *
+ * may not use this file except in compliance with the License. You    *
+ * may obtain a copy of the License at:                                *
+ *                                                                     *
+ *     http://www.apache.org/licenses/LICENSE-2.0                      *
+ *                                                                     *
+ * Unless required by applicable law or agreed to in writing, software *
+ * distributed under the License is distributed on an "AS IS" BASIS,   *
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or     *
+ * implied.  See the License for the specific language governing       *
+ * permissions and limitations under the License.                      *
+ ***********************************************************************/
+
+package org.apache.vysper.xmpp.server;
+
+import org.apache.vysper.xmpp.protocol.NamespaceHandlerDictionary;
+import org.apache.vysper.xmpp.protocol.StanzaHandler;
+import org.apache.vysper.xmpp.protocol.StanzaHandlerLookup;
+import org.apache.vysper.xmpp.stanza.Stanza;
+import org.apache.vysper.xmpp.addressing.Entity;
+import org.apache.vysper.xmpp.delivery.StanzaRelay;
+
+import java.util.concurrent.atomic.AtomicInteger;
+
+/**
+ */
+public class DefaultServerRuntimeContext implements ServerRuntimeContext {
+
+    private StanzaHandlerLookup stanzaHandlerLookup = new StanzaHandlerLookup();
+    private AtomicInteger sessionIdCounter = new AtomicInteger(1);
+    private Entity serverEntity;
+    private StanzaRelay stanzaRelay;
+
+    public DefaultServerRuntimeContext(Entity serverEntity, StanzaRelay stanzaRelay) {
+        this.serverEntity = serverEntity;
+        this.stanzaRelay = stanzaRelay;
+    }
+
+    public StanzaHandler getHandler(Stanza stanza) {
+        return stanzaHandlerLookup.getHandler(stanza);
+    }
+
+    public String getNextSessionId() {
+        // TODO session ID must be truely random
+        return "vysperSession" + sessionIdCounter.getAndIncrement();
+    }
+
+    public Entity getServerEnitity() {
+        return serverEntity;
+    }
+
+    public String getDefaultXMLLang() {
+        return "en_US"; // TODO must be configurable as of RFC3920
+    }
+
+    public StanzaRelay getStanzaRelay() {
+        return stanzaRelay;
+    }
+
+    protected void handlerFoundWorker(NamespaceHandlerDictionary namespaceHandlerDictionary, StanzaHandler stanzaHandler) {
+        // do nothing, leave for override
+    }
+
+    public void addDictionary(NamespaceHandlerDictionary namespaceHandlerDictionary) {
+        stanzaHandlerLookup.addDictionary(namespaceHandlerDictionary);
+    }
+}

Added: labs/vysper/src/main/java/org/apache/vysper/xmpp/server/DefaultSessionContext.java
URL: http://svn.apache.org/viewvc/labs/vysper/src/main/java/org/apache/vysper/xmpp/server/DefaultSessionContext.java?view=auto&rev=542950
==============================================================================
--- labs/vysper/src/main/java/org/apache/vysper/xmpp/server/DefaultSessionContext.java (added)
+++ labs/vysper/src/main/java/org/apache/vysper/xmpp/server/DefaultSessionContext.java Wed May 30 15:07:38 2007
@@ -0,0 +1,105 @@
+/***********************************************************************
+ * Copyright (c) 2006-2007 The Apache Software Foundation.             *
+ * All rights reserved.                                                *
+ * ------------------------------------------------------------------- *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you *
+ * may not use this file except in compliance with the License. You    *
+ * may obtain a copy of the License at:                                *
+ *                                                                     *
+ *     http://www.apache.org/licenses/LICENSE-2.0                      *
+ *                                                                     *
+ * Unless required by applicable law or agreed to in writing, software *
+ * distributed under the License is distributed on an "AS IS" BASIS,   *
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or     *
+ * implied.  See the License for the specific language governing       *
+ * permissions and limitations under the License.                      *
+ ***********************************************************************/
+
+package org.apache.vysper.xmpp.server;
+
+import org.apache.vysper.xmpp.addressing.Entity;
+import org.apache.vysper.xmpp.writer.StanzaWriter;
+import org.apache.vysper.xmpp.protocol.SessionStateHolder;
+
+/**
+ * provides default session context behavior
+ */
+public class DefaultSessionContext implements SessionContext {
+
+    protected ServerRuntimeContext serverRuntimeContext;
+    protected String sessionId;
+    protected String xmlLang;
+    protected StanzaWriter stanzaWriter;
+    protected SessionStateHolder sessionStateHolder;
+    protected Entity serverEntity;
+    private Entity initiatingEntity;
+    private boolean serverToServer = false;
+
+    public DefaultSessionContext(ServerRuntimeContext serverRuntimeContext, SessionStateHolder sessionStateHolder) {
+        this.serverRuntimeContext = serverRuntimeContext;
+        sessionId = serverRuntimeContext.getNextSessionId();
+        serverEntity = serverRuntimeContext.getServerEnitity();
+        xmlLang = serverRuntimeContext.getDefaultXMLLang();
+        this.sessionStateHolder = sessionStateHolder;
+    }
+
+    public ServerRuntimeContext getServerRuntimeContext() {
+        return serverRuntimeContext;
+    }
+
+    public boolean isRemotelyInitiatedSession() {
+        return true;
+    }
+
+    public Entity getInitiatingEntity() {
+        return initiatingEntity;
+    }
+
+    public void setInitiatingEntity(Entity entity) {
+        this.initiatingEntity = entity;
+    }
+
+    public boolean isServerToServer() {
+        return serverToServer;
+    }
+
+    public void setServerToServer() {
+        serverToServer = true;
+    }
+
+    public void setClientToServer() {
+        serverToServer = false;
+    }
+
+    public SessionState getState() {
+        return sessionStateHolder.getState();
+    }
+
+    public String getSessionId() {
+        return sessionId;
+    }
+
+    public String getXMLLang() {
+        return xmlLang;
+    }
+
+    public void setXMLLang(String languageCode) {
+        // TODO think about disallow changing the xmlLang a second time after from default to client value
+        xmlLang = languageCode;
+    }
+
+    public StanzaWriter getResponseWriter() {
+        return stanzaWriter;
+    }
+
+    public void endSession() {
+        stanzaWriter.close();
+        stanzaWriter = null;
+        sessionStateHolder.setState(SessionState.CLOSED);
+        // TODO close underlying transport (TCP socket)
+    }
+
+    public Entity getServerJID() {
+        return serverEntity;
+    }
+}

Added: labs/vysper/src/main/java/org/apache/vysper/xmpp/server/ServerRuntimeContext.java
URL: http://svn.apache.org/viewvc/labs/vysper/src/main/java/org/apache/vysper/xmpp/server/ServerRuntimeContext.java?view=auto&rev=542950
==============================================================================
--- labs/vysper/src/main/java/org/apache/vysper/xmpp/server/ServerRuntimeContext.java (added)
+++ labs/vysper/src/main/java/org/apache/vysper/xmpp/server/ServerRuntimeContext.java Wed May 30 15:07:38 2007
@@ -0,0 +1,38 @@
+/***********************************************************************
+ * Copyright (c) 2006-2007 The Apache Software Foundation.             *
+ * All rights reserved.                                                *
+ * ------------------------------------------------------------------- *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you *
+ * may not use this file except in compliance with the License. You    *
+ * may obtain a copy of the License at:                                *
+ *                                                                     *
+ *     http://www.apache.org/licenses/LICENSE-2.0                      *
+ *                                                                     *
+ * Unless required by applicable law or agreed to in writing, software *
+ * distributed under the License is distributed on an "AS IS" BASIS,   *
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or     *
+ * implied.  See the License for the specific language governing       *
+ * permissions and limitations under the License.                      *
+ ***********************************************************************/
+
+package org.apache.vysper.xmpp.server;
+
+import org.apache.vysper.xmpp.protocol.StanzaHandler;
+import org.apache.vysper.xmpp.stanza.Stanza;
+import org.apache.vysper.xmpp.addressing.Entity;
+import org.apache.vysper.xmpp.delivery.StanzaRelay;
+
+/**
+ * provides each session with server-global data
+ */
+public interface ServerRuntimeContext {
+    StanzaHandler getHandler(Stanza stanza);
+
+    String getNextSessionId();
+
+    Entity getServerEnitity();
+
+    String getDefaultXMLLang();
+
+    StanzaRelay getStanzaRelay();
+}

Added: labs/vysper/src/main/java/org/apache/vysper/xmpp/server/SessionContext.java
URL: http://svn.apache.org/viewvc/labs/vysper/src/main/java/org/apache/vysper/xmpp/server/SessionContext.java?view=auto&rev=542950
==============================================================================
--- labs/vysper/src/main/java/org/apache/vysper/xmpp/server/SessionContext.java (added)
+++ labs/vysper/src/main/java/org/apache/vysper/xmpp/server/SessionContext.java Wed May 30 15:07:38 2007
@@ -0,0 +1,60 @@
+/***********************************************************************
+ * Copyright (c) 2006-2007 The Apache Software Foundation.             *
+ * All rights reserved.                                                *
+ * ------------------------------------------------------------------- *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you *
+ * may not use this file except in compliance with the License. You    *
+ * may obtain a copy of the License at:                                *
+ *                                                                     *
+ *     http://www.apache.org/licenses/LICENSE-2.0                      *
+ *                                                                     *
+ * Unless required by applicable law or agreed to in writing, software *
+ * distributed under the License is distributed on an "AS IS" BASIS,   *
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or     *
+ * implied.  See the License for the specific language governing       *
+ * permissions and limitations under the License.                      *
+ ***********************************************************************/
+
+package org.apache.vysper.xmpp.server;
+
+import org.apache.vysper.xmpp.writer.StanzaWriter;
+import org.apache.vysper.xmpp.addressing.Entity;
+
+/**
+ * provides the session with its context data
+ */
+public interface SessionContext {
+    ServerRuntimeContext getServerRuntimeContext();
+
+    /**
+     * FALSE iff _this_ server has initiated the connection (to another server),
+     * and _not_ the remote side (client/server) initiated the session.
+     * for common client/server connections this returns TRUE.
+     * @return
+     */
+    boolean isRemotelyInitiatedSession();
+    Entity getInitiatingEntity();
+    void setInitiatingEntity(Entity entity);
+
+    /**
+     * if this session is handling server-to-server communication
+     * (namespace "jabber:server"
+     * @return
+     */
+    boolean isServerToServer();
+    void setServerToServer();
+    void setClientToServer();
+
+    SessionState getState();
+
+    String getSessionId();
+
+    String getXMLLang();
+    void setXMLLang(String languageCode);
+
+    StanzaWriter getResponseWriter();
+
+    void endSession();
+
+    Entity getServerJID();
+}

Added: labs/vysper/src/main/java/org/apache/vysper/xmpp/server/SessionState.java
URL: http://svn.apache.org/viewvc/labs/vysper/src/main/java/org/apache/vysper/xmpp/server/SessionState.java?view=auto&rev=542950
==============================================================================
--- labs/vysper/src/main/java/org/apache/vysper/xmpp/server/SessionState.java (added)
+++ labs/vysper/src/main/java/org/apache/vysper/xmpp/server/SessionState.java Wed May 30 15:07:38 2007
@@ -0,0 +1,63 @@
+/***********************************************************************
+ * Copyright (c) 2006-2007 The Apache Software Foundation.             *
+ * All rights reserved.                                                *
+ * ------------------------------------------------------------------- *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you *
+ * may not use this file except in compliance with the License. You    *
+ * may obtain a copy of the License at:                                *
+ *                                                                     *
+ *     http://www.apache.org/licenses/LICENSE-2.0                      *
+ *                                                                     *
+ * Unless required by applicable law or agreed to in writing, software *
+ * distributed under the License is distributed on an "AS IS" BASIS,   *
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or     *
+ * implied.  See the License for the specific language governing       *
+ * permissions and limitations under the License.                      *
+ ***********************************************************************/
+
+package org.apache.vysper.xmpp.server;
+
+/**
+ */
+public enum SessionState {
+
+    /**
+     * 
+     */
+    UNCONNECTED,
+
+    /**
+     * stream opened but no start stanza processed
+     */
+    INITIATED,
+
+    /**
+     * plain start stanza processed, but not secured
+     */
+    STARTED,
+
+    /**
+     * STARTTLS processed, but not finished
+     */
+    ENCRYPTION_STARTED,
+
+    /**
+     * secure start stanza processed, but not authenticated
+     */
+    ENCRYPTED,
+
+    /**
+     * authenticated
+     */
+    AUTHENTICATED,
+
+    /**
+     * end stanza processed
+     */
+    ENDED,
+
+    /**
+     * underlying stream closed
+     */
+    CLOSED
+}

Added: labs/vysper/src/main/java/org/apache/vysper/xmpp/server/XMPPVersion.java
URL: http://svn.apache.org/viewvc/labs/vysper/src/main/java/org/apache/vysper/xmpp/server/XMPPVersion.java?view=auto&rev=542950
==============================================================================
--- labs/vysper/src/main/java/org/apache/vysper/xmpp/server/XMPPVersion.java (added)
+++ labs/vysper/src/main/java/org/apache/vysper/xmpp/server/XMPPVersion.java Wed May 30 15:07:38 2007
@@ -0,0 +1,104 @@
+/***********************************************************************
+ * Copyright (c) 2006-2007 The Apache Software Foundation.             *
+ * All rights reserved.                                                *
+ * ------------------------------------------------------------------- *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you *
+ * may not use this file except in compliance with the License. You    *
+ * may obtain a copy of the License at:                                *
+ *                                                                     *
+ *     http://www.apache.org/licenses/LICENSE-2.0                      *
+ *                                                                     *
+ * Unless required by applicable law or agreed to in writing, software *
+ * distributed under the License is distributed on an "AS IS" BASIS,   *
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or     *
+ * implied.  See the License for the specific language governing       *
+ * permissions and limitations under the License.                      *
+ ***********************************************************************/
+
+package org.apache.vysper.xmpp.server;
+
+/**
+ */
+public class XMPPVersion {
+
+    public static final XMPPVersion VERSION_1_0 = new XMPPVersion(1, 0);
+
+    private int major = 1;
+    private int minor = 0;
+    private static final String STRING_ZERO = "0";
+    private static final String STRING_UNO = "1";
+    private static final String STRING_DOT = ".";
+
+    public XMPPVersion() {
+        // default values
+    }
+
+    public XMPPVersion(int major, int minor) {
+        if (major < 0) throw new IllegalArgumentException("major must at least be 0");
+        this.major = major;
+        if (minor < 0) throw new IllegalArgumentException("minor must at least be 0");
+        this.minor = minor;
+    }
+
+    public XMPPVersion(String version) {
+        String[] parts = version.split("\\.");
+        if (parts == null || parts.length != 2) {
+            throw new IllegalArgumentException("XMPP version must be of format 'x.y'");
+        }
+        major = convertToInt(parts[0]);
+        if (major < 0) throw new IllegalArgumentException("major must at least be 0");
+        minor = convertToInt(parts[1]);
+        if (minor < 0) throw new IllegalArgumentException("minor must at least be 0");
+    }
+
+    private int convertToInt(String part) {
+        if (part == null || part.length() == 0) throw new IllegalArgumentException("version part is empty");
+        if (STRING_ZERO.equals(part)) return 0;
+        if (STRING_UNO.equals(part)) return 1;
+
+        part = part.trim();
+        if (part.startsWith("+") || part.startsWith("-")) throw new IllegalArgumentException("version part must contain only numbers");
+        if (part.startsWith(STRING_ZERO)) return convertToInt(part.substring(1)); // ignore leading zeros
+        return Integer.parseInt(part);
+    }
+
+    public int getMajor() {
+        return major;
+    }
+
+    public int getMinor() {
+        return minor;
+    }
+
+    public String toString() {
+        return "" + major + STRING_DOT + minor;
+    }
+
+    public boolean isUnknownVersion() {
+        return major == 0 && minor == 0;
+    }
+
+    public static XMPPVersion getCommonDenomitator(XMPPVersion v1, XMPPVersion v2) {
+        if (v1.getMajor() != v2.getMajor()) return v1.getMajor() < v2.getMajor() ? v1 : v2;
+        return v1.getMinor() < v2.getMinor() ? v1 : v2;
+    }
+
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (o == null || getClass() != o.getClass()) return false;
+
+        final XMPPVersion that = (XMPPVersion) o;
+
+        if (major != that.major) return false;
+        if (minor != that.minor) return false;
+
+        return true;
+    }
+
+    public int hashCode() {
+        int result;
+        result = major;
+        result = 29 * result + minor;
+        return result;
+    }
+}

Added: labs/vysper/src/main/java/org/apache/vysper/xmpp/server/response/ServerErrorResponses.java
URL: http://svn.apache.org/viewvc/labs/vysper/src/main/java/org/apache/vysper/xmpp/server/response/ServerErrorResponses.java?view=auto&rev=542950
==============================================================================
--- labs/vysper/src/main/java/org/apache/vysper/xmpp/server/response/ServerErrorResponses.java (added)
+++ labs/vysper/src/main/java/org/apache/vysper/xmpp/server/response/ServerErrorResponses.java Wed May 30 15:07:38 2007
@@ -0,0 +1,137 @@
+/***********************************************************************
+ * Copyright (c) 2006-2007 The Apache Software Foundation.             *
+ * All rights reserved.                                                *
+ * ------------------------------------------------------------------- *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you *
+ * may not use this file except in compliance with the License. You    *
+ * may obtain a copy of the License at:                                *
+ *                                                                     *
+ *     http://www.apache.org/licenses/LICENSE-2.0                      *
+ *                                                                     *
+ * Unless required by applicable law or agreed to in writing, software *
+ * distributed under the License is distributed on an "AS IS" BASIS,   *
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or     *
+ * implied.  See the License for the specific language governing       *
+ * permissions and limitations under the License.                      *
+ ***********************************************************************/
+
+package org.apache.vysper.xmpp.server.response;
+
+import org.apache.vysper.xmpp.applicationdomains.base.StanzaErrorCondition;
+import org.apache.vysper.xmpp.applicationdomains.base.StanzaErrorType;
+import org.apache.vysper.xmpp.protocol.NamespaceURIs;
+import org.apache.vysper.xmpp.protocol.StreamErrorCondition;
+import org.apache.vysper.xmpp.stanza.Stanza;
+import org.apache.vysper.xmpp.stanza.StanzaBuilder;
+import org.apache.vysper.xmpp.stanza.XMPPCoreStanza;
+import org.apache.vysper.xmpp.xmlfragment.XMLElement;
+
+/**
+ */
+public class ServerErrorResponses
+{
+    private static ServerErrorResponses serverErrorResponsesInstance = null;
+
+    public static ServerErrorResponses getInstance() {
+        if (serverErrorResponsesInstance == null) {
+            serverErrorResponsesInstance = new ServerErrorResponses();
+        }
+        return serverErrorResponsesInstance;
+    }
+
+    protected ServerErrorResponses() {
+        // empty
+    }
+
+    public Stanza getError(StreamErrorCondition definedErrorCondition, String languageCode, String descriptiveText, XMLElement applicationSpecificError) {
+
+        /*
+           <stream:jabber>
+             <defined-condition xmlns='urn:ietf:params:xml:ns:xmpp-streams'/>
+             <text xmlns='urn:ietf:params:xml:ns:xmpp-streams'
+                   xml:lang='langcode'>
+               OPTIONAL descriptive text
+             </text>
+             [OPTIONAL application-specific condition element]
+           </stream:jabber>
+        */
+
+        if (languageCode == null) languageCode = "en_US";
+        StanzaBuilder stanzaBuilder = new StanzaBuilder("error");
+
+        stanzaBuilder.startInnerElement(definedErrorCondition.value())
+            .addNamespaceAttribute(NamespaceURIs.URN_IETF_PARAMS_XML_NS_XMPP_STREAMS)
+            .endInnerElement();
+
+        if (descriptiveText != null) {
+            stanzaBuilder.startInnerElement("text")
+                .addNamespaceAttribute(NamespaceURIs.URN_IETF_PARAMS_XML_NS_XMPP_STREAMS)
+                .addAttribute("xml:lang", languageCode)
+                .addText(descriptiveText)
+                .endInnerElement();
+        }
+
+        if (applicationSpecificError != null) {
+            stanzaBuilder.addPreparedElement(applicationSpecificError);
+        }
+
+        return stanzaBuilder.getFinalStanza();
+    }
+
+    /**
+     * TODO move to a more general error handling
+     * @param stanza
+     * @param type
+     * @param errorCondition - corresponds to one of the defined stanza error conditions
+     * @param errorText - is optional together with errorLang, both together might be NULL
+     * @param errorLang - must be present, if errorText is not NULL
+     * @param errorConditionElement - optional application specific error condition element
+     * @return error response stanza
+     */
+    public Stanza getErrorResponse(XMPPCoreStanza stanza, StanzaErrorType type, StanzaErrorCondition errorCondition,
+                                   String errorText, String errorLang,
+                                   XMLElement errorConditionElement) {
+
+        if ("error".equals(stanza.getType())) {
+            return ServerErrorResponses.getInstance().getError(StreamErrorCondition.UNSUPPORTED_STANZA_TYPE, errorLang,
+                                                               "cannot respond to IQ stanza of type error with the same", null);
+        }
+
+        StanzaBuilder responseBuilder = new StanzaBuilder(stanza.getName(), stanza.getNamespace());
+
+        String id = stanza.getID();
+        if (id != null) responseBuilder.addAttribute("id", id);
+
+        responseBuilder.addAttribute("type", "error");
+
+        fillErrorStanza(stanza, type, errorCondition, errorText, errorLang, errorConditionElement, responseBuilder);
+
+        return responseBuilder.getFinalStanza();
+    }
+
+    private void fillErrorStanza(XMPPCoreStanza stanza, StanzaErrorType type, StanzaErrorCondition errorCondition, String errorText, String errorLang, XMLElement errorConditionElement, StanzaBuilder responseBuilder) {
+        // inline incoming stanza as of RFC 3920 9.3.1
+        responseBuilder.addPreparedElement(stanza);
+
+        // error element
+        responseBuilder.startInnerElement("error")
+                         .addAttribute("type", type.value());
+
+        // insert defined error condition relating to the stanza error type
+        responseBuilder.startInnerElement(errorCondition.value(), NamespaceURIs.URN_IETF_PARAMS_XML_NS_XMPP_STANZAS)
+                         .endInnerElement();
+
+        // optional error text
+        if (errorText != null && errorLang != null) {
+            responseBuilder.startInnerElement("text")
+                             .addNamespaceAttribute(NamespaceURIs.URN_IETF_PARAMS_XML_NS_XMPP_STANZAS)
+                             .addAttribute("xml:lang", errorLang)
+                             .addText(errorText);
+        }
+        // optional application specific error condition element
+        if (errorConditionElement != null) responseBuilder.addPreparedElement(errorConditionElement);
+
+        responseBuilder.endInnerElement();
+    }
+
+}

Added: labs/vysper/src/main/java/org/apache/vysper/xmpp/server/response/ServerResponses.java
URL: http://svn.apache.org/viewvc/labs/vysper/src/main/java/org/apache/vysper/xmpp/server/response/ServerResponses.java?view=auto&rev=542950
==============================================================================
--- labs/vysper/src/main/java/org/apache/vysper/xmpp/server/response/ServerResponses.java (added)
+++ labs/vysper/src/main/java/org/apache/vysper/xmpp/server/response/ServerResponses.java Wed May 30 15:07:38 2007
@@ -0,0 +1,88 @@
+/***********************************************************************
+ * Copyright (c) 2006-2007 The Apache Software Foundation.             *
+ * All rights reserved.                                                *
+ * ------------------------------------------------------------------- *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you *
+ * may not use this file except in compliance with the License. You    *
+ * may obtain a copy of the License at:                                *
+ *                                                                     *
+ *     http://www.apache.org/licenses/LICENSE-2.0                      *
+ *                                                                     *
+ * Unless required by applicable law or agreed to in writing, software *
+ * distributed under the License is distributed on an "AS IS" BASIS,   *
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or     *
+ * implied.  See the License for the specific language governing       *
+ * permissions and limitations under the License.                      *
+ ***********************************************************************/
+
+package org.apache.vysper.xmpp.server.response;
+
+import org.apache.vysper.xmpp.protocol.NamespaceURIs;
+import org.apache.vysper.xmpp.stanza.Stanza;
+import org.apache.vysper.xmpp.stanza.StanzaBuilder;
+import org.apache.vysper.xmpp.server.XMPPVersion;
+import org.apache.vysper.xmpp.server.SessionContext;
+import org.apache.vysper.xmpp.addressing.Entity;
+
+/**
+ */
+public class ServerResponses {
+
+    public Stanza getStreamOpenerForError(boolean forClient, Entity from, XMPPVersion version, Stanza errorStanza) {
+        return getStreamOpener(forClient, from, null, version, errorStanza);
+    }
+
+    public Stanza getStreamOpener(boolean forClient, Entity from, XMPPVersion version, SessionContext sessionContext) {
+        return getStreamOpener(forClient, from, sessionContext.getXMLLang(), version, sessionContext.getSessionId(), null);
+    }
+
+    public Stanza getStreamOpener(boolean forClient, Entity from, String xmlLang, XMPPVersion version, Stanza innerStanza) {
+        return getStreamOpener(forClient, from, xmlLang, version, null, innerStanza);
+    }
+
+    public Stanza getStreamOpener(boolean forClient, Entity from, String xmlLang, XMPPVersion version, String sessionId, Stanza innerStanza) {
+        StanzaBuilder stanzaBuilder = new StanzaBuilder("stream", NamespaceURIs.HTTP_ETHERX_JABBER_ORG_STREAMS)
+            .addNamespaceAttribute(forClient ?  NamespaceURIs.JABBER_CLIENT : NamespaceURIs.JABBER_SERVER)
+            .addNamespaceAttribute("stream", NamespaceURIs.HTTP_ETHERX_JABBER_ORG_STREAMS);
+        if (xmlLang != null) stanzaBuilder.addAttribute("xml:lang", xmlLang);
+        if (version != null) stanzaBuilder.addAttribute("version", version.toString());
+        if (forClient && sessionId != null) stanzaBuilder.addAttribute("id", sessionId);
+        if (innerStanza != null) stanzaBuilder.addPreparedElement(innerStanza);
+        return stanzaBuilder.getFinalStanza();
+    }
+
+    public Stanza getStreamOpenerWithMechanisms_UNUSED(boolean forClient, Entity from, String sessionId, XMPPVersion version) {
+         /*
+           <stream:stream
+               xmlns='jabber:server'
+               xmlns:stream='http://etherx.jabber.org/streams'
+               from='example.com'
+               id='s2s_123'
+               version='1.0'>
+         */
+        StanzaBuilder stanzaBuilder = new StanzaBuilder("stream:stream");
+
+        stanzaBuilder.startInnerElement("mechanisms")
+            .addNamespaceAttribute(forClient ?  NamespaceURIs.JABBER_CLIENT : NamespaceURIs.JABBER_SERVER)
+            .addNamespaceAttribute("stream", NamespaceURIs.HTTP_ETHERX_JABBER_ORG_STREAMS)
+            .addAttribute("from", from.getFullQualifiedName())
+            .addAttribute("id", sessionId);
+        if (version != null) stanzaBuilder.addAttribute("version", version.toString());
+        return stanzaBuilder.getFinalStanza();
+    }
+
+    public Stanza getFeaturesForAuthentication() {
+
+        StanzaBuilder stanzaBuilder = new StanzaBuilder("features");
+
+        stanzaBuilder.startInnerElement("mechanisms")
+            .addNamespaceAttribute(NamespaceURIs.URN_IETF_PARAMS_XML_NS_XMPP_SASL)
+            .startInnerElement("mechanism").addText("DIGEST-MD5").endInnerElement()
+            .startInnerElement("mechanism").addText("PLAIN").endInnerElement()
+            .startInnerElement("mechanism").addText("KERBEROS_V4").endInnerElement()
+            .endInnerElement();
+
+        return stanzaBuilder.getFinalStanza();
+    }
+
+}

Added: labs/vysper/src/main/java/org/apache/vysper/xmpp/stanza/IQStanza.java
URL: http://svn.apache.org/viewvc/labs/vysper/src/main/java/org/apache/vysper/xmpp/stanza/IQStanza.java?view=auto&rev=542950
==============================================================================
--- labs/vysper/src/main/java/org/apache/vysper/xmpp/stanza/IQStanza.java (added)
+++ labs/vysper/src/main/java/org/apache/vysper/xmpp/stanza/IQStanza.java Wed May 30 15:07:38 2007
@@ -0,0 +1,46 @@
+/***********************************************************************
+ * Copyright (c) 2006-2007 The Apache Software Foundation.             *
+ * All rights reserved.                                                *
+ * ------------------------------------------------------------------- *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you *
+ * may not use this file except in compliance with the License. You    *
+ * may obtain a copy of the License at:                                *
+ *                                                                     *
+ *     http://www.apache.org/licenses/LICENSE-2.0                      *
+ *                                                                     *
+ * Unless required by applicable law or agreed to in writing, software *
+ * distributed under the License is distributed on an "AS IS" BASIS,   *
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or     *
+ * implied.  See the License for the specific language governing       *
+ * permissions and limitations under the License.                      *
+ ***********************************************************************/
+
+package org.apache.vysper.xmpp.stanza;
+
+/**
+ * info/query stanza (request/response)
+ */
+public class IQStanza extends XMPPCoreStanza {
+
+    public static final String NAME = "iq";
+
+    public static boolean isOfType(Stanza stanza) {
+        return isOfType(stanza, NAME);
+    }
+
+    public IQStanza(Stanza stanza) {
+        super(stanza);
+        if (!isOfType(stanza)) throw new IllegalArgumentException("only IQ stanza is allowed here");
+    }
+
+    public String getName() {
+        return NAME;
+    }
+
+    public IQStanzaType getIQType() {
+        String type = getType();
+        if (type == null) return null;
+        return IQStanzaType.valueOfOrNull(type);
+    }
+
+}

Added: labs/vysper/src/main/java/org/apache/vysper/xmpp/stanza/IQStanzaType.java
URL: http://svn.apache.org/viewvc/labs/vysper/src/main/java/org/apache/vysper/xmpp/stanza/IQStanzaType.java?view=auto&rev=542950
==============================================================================
--- labs/vysper/src/main/java/org/apache/vysper/xmpp/stanza/IQStanzaType.java (added)
+++ labs/vysper/src/main/java/org/apache/vysper/xmpp/stanza/IQStanzaType.java Wed May 30 15:07:38 2007
@@ -0,0 +1,48 @@
+/***********************************************************************
+ * Copyright (c) 2006-2007 The Apache Software Foundation.             *
+ * All rights reserved.                                                *
+ * ------------------------------------------------------------------- *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you *
+ * may not use this file except in compliance with the License. You    *
+ * may obtain a copy of the License at:                                *
+ *                                                                     *
+ *     http://www.apache.org/licenses/LICENSE-2.0                      *
+ *                                                                     *
+ * Unless required by applicable law or agreed to in writing, software *
+ * distributed under the License is distributed on an "AS IS" BASIS,   *
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or     *
+ * implied.  See the License for the specific language governing       *
+ * permissions and limitations under the License.                      *
+ ***********************************************************************/
+
+package org.apache.vysper.xmpp.stanza;
+
+/**
+ */
+public enum IQStanzaType {
+
+    GET ("get"),
+    SET ("set"),
+    RESULT ("result"),
+    ERROR ("error");
+
+    private final String value;
+
+    public static IQStanzaType valueOfOrNull(String value) {
+        try {
+            return valueOf(value.toUpperCase());
+        } catch (IllegalArgumentException e) {
+            return null;
+        }
+    }
+
+
+    IQStanzaType(String value) {
+        this.value = value;
+    }
+
+    public String value() {
+        return value;
+    }
+
+}

Added: labs/vysper/src/main/java/org/apache/vysper/xmpp/stanza/MessageStanza.java
URL: http://svn.apache.org/viewvc/labs/vysper/src/main/java/org/apache/vysper/xmpp/stanza/MessageStanza.java?view=auto&rev=542950
==============================================================================
--- labs/vysper/src/main/java/org/apache/vysper/xmpp/stanza/MessageStanza.java (added)
+++ labs/vysper/src/main/java/org/apache/vysper/xmpp/stanza/MessageStanza.java Wed May 30 15:07:38 2007
@@ -0,0 +1,39 @@
+/***********************************************************************
+ * Copyright (c) 2006-2007 The Apache Software Foundation.             *
+ * All rights reserved.                                                *
+ * ------------------------------------------------------------------- *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you *
+ * may not use this file except in compliance with the License. You    *
+ * may obtain a copy of the License at:                                *
+ *                                                                     *
+ *     http://www.apache.org/licenses/LICENSE-2.0                      *
+ *                                                                     *
+ * Unless required by applicable law or agreed to in writing, software *
+ * distributed under the License is distributed on an "AS IS" BASIS,   *
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or     *
+ * implied.  See the License for the specific language governing       *
+ * permissions and limitations under the License.                      *
+ ***********************************************************************/
+
+package org.apache.vysper.xmpp.stanza;
+
+/**
+ * message stanza (push)
+ */
+public class MessageStanza extends XMPPCoreStanza {
+
+    public static final String NAME = "message";
+
+    public static boolean isOfType(Stanza stanza) {
+        return isOfType(stanza, NAME);
+    }
+
+    public MessageStanza(Stanza stanza) {
+        super(stanza);
+        if (!MessageStanza.isOfType(stanza)) throw new IllegalArgumentException("only 'message' stanza is allowed here");
+    }
+
+    public String getName() {
+        return NAME;
+    }
+}

Added: labs/vysper/src/main/java/org/apache/vysper/xmpp/stanza/PresenceStanza.java
URL: http://svn.apache.org/viewvc/labs/vysper/src/main/java/org/apache/vysper/xmpp/stanza/PresenceStanza.java?view=auto&rev=542950
==============================================================================
--- labs/vysper/src/main/java/org/apache/vysper/xmpp/stanza/PresenceStanza.java (added)
+++ labs/vysper/src/main/java/org/apache/vysper/xmpp/stanza/PresenceStanza.java Wed May 30 15:07:38 2007
@@ -0,0 +1,38 @@
+/***********************************************************************
+ * Copyright (c) 2006-2007 The Apache Software Foundation.             *
+ * All rights reserved.                                                *
+ * ------------------------------------------------------------------- *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you *
+ * may not use this file except in compliance with the License. You    *
+ * may obtain a copy of the License at:                                *
+ *                                                                     *
+ *     http://www.apache.org/licenses/LICENSE-2.0                      *
+ *                                                                     *
+ * Unless required by applicable law or agreed to in writing, software *
+ * distributed under the License is distributed on an "AS IS" BASIS,   *
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or     *
+ * implied.  See the License for the specific language governing       *
+ * permissions and limitations under the License.                      *
+ ***********************************************************************/
+
+package org.apache.vysper.xmpp.stanza;
+
+/**
+ * presence stanza (publish/subscribe [aka "pub/sub"] or broadcast)
+ */
+public class PresenceStanza extends XMPPCoreStanza {
+    public static final String NAME = "presence";
+
+    public static boolean isOfType(Stanza stanza) {
+        return isOfType(stanza, NAME);
+    }
+
+    public PresenceStanza(Stanza stanza) {
+        super(stanza);
+        if (!PresenceStanza.isOfType(stanza)) throw new IllegalArgumentException("only 'presence' stanza is allowed here");
+    }
+
+    public String getName() {
+        return NAME;
+    }
+}

Added: labs/vysper/src/main/java/org/apache/vysper/xmpp/stanza/Stanza.java
URL: http://svn.apache.org/viewvc/labs/vysper/src/main/java/org/apache/vysper/xmpp/stanza/Stanza.java?view=auto&rev=542950
==============================================================================
--- labs/vysper/src/main/java/org/apache/vysper/xmpp/stanza/Stanza.java (added)
+++ labs/vysper/src/main/java/org/apache/vysper/xmpp/stanza/Stanza.java Wed May 30 15:07:38 2007
@@ -0,0 +1,49 @@
+/***********************************************************************
+ * Copyright (c) 2006-2007 The Apache Software Foundation.             *
+ * All rights reserved.                                                *
+ * ------------------------------------------------------------------- *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you *
+ * may not use this file except in compliance with the License. You    *
+ * may obtain a copy of the License at:                                *
+ *                                                                     *
+ *     http://www.apache.org/licenses/LICENSE-2.0                      *
+ *                                                                     *
+ * Unless required by applicable law or agreed to in writing, software *
+ * distributed under the License is distributed on an "AS IS" BASIS,   *
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or     *
+ * implied.  See the License for the specific language governing       *
+ * permissions and limitations under the License.                      *
+ ***********************************************************************/
+
+package org.apache.vysper.xmpp.stanza;
+
+import org.apache.vysper.xmpp.xmlfragment.Attribute;
+import org.apache.vysper.xmpp.xmlfragment.XMLElement;
+import org.apache.vysper.xmpp.xmlfragment.XMLFragment;
+
+import java.util.List;
+
+/**
+ * immutable container for all data contained in an XMPP stanza.
+ * it is surrounded by a family of classes used to build, parse, verify and process stanzas
+ */
+public class Stanza extends XMLElement {
+
+    public Stanza(String name, String namespace, List<Attribute> attributes, List<XMLFragment> innerFragments) {
+        super(name, namespace, attributes, innerFragments);
+    }
+
+    public Stanza(String name, String namespace, Attribute[] attributes, XMLFragment[] innerFragments) {
+        super(name, namespace, attributes, innerFragments);
+    }
+
+    public Stanza(String name, String namespace, List<Attribute> attributes, XMLFragment[] innerFragments) {
+        super(name, namespace, attributes, innerFragments);
+    }
+
+    public Stanza(String name, String namespace, Attribute[] attributes, List<XMLFragment> innerFragments) {
+        super(name, namespace, attributes, innerFragments);
+    }
+
+
+}

Added: labs/vysper/src/main/java/org/apache/vysper/xmpp/stanza/StanzaBuilder.java
URL: http://svn.apache.org/viewvc/labs/vysper/src/main/java/org/apache/vysper/xmpp/stanza/StanzaBuilder.java?view=auto&rev=542950
==============================================================================
--- labs/vysper/src/main/java/org/apache/vysper/xmpp/stanza/StanzaBuilder.java (added)
+++ labs/vysper/src/main/java/org/apache/vysper/xmpp/stanza/StanzaBuilder.java Wed May 30 15:07:38 2007
@@ -0,0 +1,149 @@
+/***********************************************************************
+ * Copyright (c) 2006-2007 The Apache Software Foundation.             *
+ * All rights reserved.                                                *
+ * ------------------------------------------------------------------- *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you *
+ * may not use this file except in compliance with the License. You    *
+ * may obtain a copy of the License at:                                *
+ *                                                                     *
+ *     http://www.apache.org/licenses/LICENSE-2.0                      *
+ *                                                                     *
+ * Unless required by applicable law or agreed to in writing, software *
+ * distributed under the License is distributed on an "AS IS" BASIS,   *
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or     *
+ * implied.  See the License for the specific language governing       *
+ * permissions and limitations under the License.                      *
+ ***********************************************************************/
+
+package org.apache.vysper.xmpp.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.XMLText;
+import org.apache.vysper.xmpp.xmlfragment.NamespaceAttribute;
+
+import java.util.Stack;
+import java.util.List;
+import java.util.ArrayList;
+
+/**
+ */
+public class StanzaBuilder {
+
+    class ElementStruct {
+        public ElementStruct parentElement = null;
+        public XMLElement element = null;
+        public List<Attribute> attributes = null;
+        public List<XMLFragment> innerFragments = null;
+    }
+
+    /**
+     * parent hierarchy for current element
+     */
+    private Stack<ElementStruct> stack = new Stack<ElementStruct>();
+    private ElementStruct currentElement = null;
+    private Stanza resultingStanza = null;
+
+
+    public StanzaBuilder(String stanzaName) {
+        this(stanzaName, null);
+    }
+    
+    public StanzaBuilder(String stanzaName, String namespaceURI) {
+        startNewElement(stanzaName, namespaceURI, true);
+        resultingStanza = (Stanza)currentElement.element;
+        stack.push(currentElement);
+    }
+
+    private void startNewElement(String name, String namespaceURI, boolean isStanza) {
+        // TODO assert that name does not contain namespace (":")
+        // TODO handle the namespace, given by URI, currently always NULL in Stanza/XMLElement constructors
+        ElementStruct element = new ElementStruct();
+        element.attributes = new ArrayList<Attribute>();
+        element.innerFragments = new ArrayList<XMLFragment>();
+        if (isStanza) {
+            element.element = new Stanza(name, namespaceURI, element.attributes, element.innerFragments);
+        } else {
+            element.element = new XMLElement(name, namespaceURI, element.attributes, element.innerFragments);
+        }
+        currentElement = element;
+    }
+
+    public StanzaBuilder addAttribute(String name, String value) {
+        addAttribute(new Attribute(name, value));
+        return this;
+    }
+
+    public StanzaBuilder addNamespaceAttribute(String value) {
+        addAttribute(new NamespaceAttribute(value));
+        return this;
+    }
+
+    public StanzaBuilder addNamespaceAttribute(String namespacePrefix, String value) {
+        addAttribute(new NamespaceAttribute(namespacePrefix, value));
+        return this;
+    }
+
+    public StanzaBuilder addAttribute(Attribute attribute) {
+        checkReset();
+        currentElement.attributes.add(attribute);
+        return this;
+    }
+
+    public StanzaBuilder addText(String text) {
+        checkReset();
+        currentElement.innerFragments.add(new XMLText(text));
+        return this;
+    }
+
+    public StanzaBuilder startInnerElement(String name) {
+        return this.startInnerElement(name, null);
+    }
+
+    public StanzaBuilder startInnerElement(String name, String namespaceURI) {
+        checkReset();
+
+        startNewElement(name, namespaceURI, false);
+
+        stack.peek().innerFragments.add(currentElement.element); // add new one to its parent
+
+        stack.push(currentElement);
+
+        return this;
+    }
+
+    public StanzaBuilder endInnerElement() {
+        checkReset();
+        if (stack.isEmpty()) throw new IllegalStateException("cannot end beyond top element");
+
+        stack.pop(); // take current off stack and forget (it was added to its parent before)
+        currentElement = stack.peek(); // we again deal with parent, which can be receive additions
+        return this;
+    }
+
+    public StanzaBuilder addPreparedElement(XMLElement preparedElement) {
+        checkReset();
+        currentElement.innerFragments.add(preparedElement);
+        return this;
+    }
+
+    /**
+     * the stanza can only be retrieved once
+     * @return retrieves the stanza and invalidates the builder
+     */
+    public Stanza getFinalStanza() {
+        checkReset();
+        Stanza returnStanza = resultingStanza;
+        resultingStanza = null; // reset
+        stack.clear();
+        return returnStanza;
+    }
+
+    /**
+     * assure that the immutable Stanza object is not changed after it was retrieved
+     */
+    private void checkReset() {
+        if (resultingStanza == null) throw new IllegalStateException("stanza builder was reset after retrieving stanza");
+    }
+}

Added: labs/vysper/src/main/java/org/apache/vysper/xmpp/stanza/XMPPCoreStanza.java
URL: http://svn.apache.org/viewvc/labs/vysper/src/main/java/org/apache/vysper/xmpp/stanza/XMPPCoreStanza.java?view=auto&rev=542950
==============================================================================
--- labs/vysper/src/main/java/org/apache/vysper/xmpp/stanza/XMPPCoreStanza.java (added)
+++ labs/vysper/src/main/java/org/apache/vysper/xmpp/stanza/XMPPCoreStanza.java Wed May 30 15:07:38 2007
@@ -0,0 +1,106 @@
+/***********************************************************************
+ * Copyright (c) 2006-2007 The Apache Software Foundation.             *
+ * All rights reserved.                                                *
+ * ------------------------------------------------------------------- *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you *
+ * may not use this file except in compliance with the License. You    *
+ * may obtain a copy of the License at:                                *
+ *                                                                     *
+ *     http://www.apache.org/licenses/LICENSE-2.0                      *
+ *                                                                     *
+ * Unless required by applicable law or agreed to in writing, software *
+ * distributed under the License is distributed on an "AS IS" BASIS,   *
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or     *
+ * implied.  See the License for the specific language governing       *
+ * permissions and limitations under the License.                      *
+ ***********************************************************************/
+
+package org.apache.vysper.xmpp.stanza;
+
+import org.apache.vysper.xmpp.addressing.Entity;
+import org.apache.vysper.xmpp.addressing.EntityFormatException;
+import org.apache.vysper.xmpp.addressing.EntityImpl;
+import org.apache.vysper.xmpp.protocol.NamespaceURIs;
+import org.apache.vysper.xmpp.xmlfragment.XMLElementVerifier;
+
+/**
+ * wraps an all-purpose stanza into a core stanza (iq, message, presence)
+ */
+abstract public class XMPPCoreStanza extends Stanza {
+
+    protected static boolean isOfType(Stanza stanza, String name) {
+        boolean nameMatches = stanza != null && stanza.getName().equals(name);
+        if (!nameMatches) return false;
+        String namespaceURI = stanza.getNamespace();
+        if (namespaceURI == null) return false;
+        return namespaceURI.equals(NamespaceURIs.JABBER_CLIENT) || namespaceURI.equals(NamespaceURIs.JABBER_SERVER);
+    }
+
+    public static XMPPCoreStanza getWrapper(Stanza stanza) {
+        if (IQStanza.isOfType(stanza)) return new IQStanza(stanza);
+        if (MessageStanza.isOfType(stanza)) return new MessageStanza(stanza);
+        if (PresenceStanza.isOfType(stanza)) return new PresenceStanza(stanza);
+        return null;
+    }
+
+    public XMPPCoreStanza(Stanza stanza) {
+        super(stanza.getName(), stanza.getNamespace(), stanza.getAttributes(), stanza.getInnerFragments());
+    }
+
+    public XMLElementVerifier getVerifier() {
+        if (xmlElementVerifier == null) xmlElementVerifier = new XMPPCoreStanzaVerifier(this);
+        return xmlElementVerifier;
+    }
+
+    public XMPPCoreStanzaVerifier getCoreVerifier() {
+        return (XMPPCoreStanzaVerifier) xmlElementVerifier;
+    }
+
+    abstract public String getName();
+    
+    public Entity getTo() {
+        return getEntity("to");
+    }
+
+    public Entity getFrom() {
+        return getEntity("from");
+    }
+
+    public String getXMLLang() {
+        return getVerifier().attributePresent("xml:lang") ? getAttribute("xml:lang").getValue() : null;
+    }
+
+    public String getType() {
+        return getVerifier().attributePresent("type") ? getAttribute("type").getValue() : null;
+    }
+
+    public String getID() {
+        return getVerifier().attributePresent("id") ? getAttribute("id").getValue() : null;
+    }
+
+    public boolean isError() {
+        return "error".equals(getType());
+    }
+
+    public boolean isServerCall() {
+        return getNamespace().equals(NamespaceURIs.JABBER_SERVER);
+    }
+
+    private EntityImpl getEntity(String attributeName) {
+        boolean isPresent = getVerifier().attributePresent(attributeName);
+        EntityImpl entity = null;
+        if (isPresent) {
+            String attributeValue = getAttribute(attributeName).getValue();
+            try {
+                entity = EntityImpl.parse(attributeValue);
+            } catch (EntityFormatException e) {
+                return null;
+            }
+        }
+        return entity;
+    }
+
+
+
+
+}

Added: labs/vysper/src/main/java/org/apache/vysper/xmpp/stanza/XMPPCoreStanzaVerifier.java
URL: http://svn.apache.org/viewvc/labs/vysper/src/main/java/org/apache/vysper/xmpp/stanza/XMPPCoreStanzaVerifier.java?view=auto&rev=542950
==============================================================================
--- labs/vysper/src/main/java/org/apache/vysper/xmpp/stanza/XMPPCoreStanzaVerifier.java (added)
+++ labs/vysper/src/main/java/org/apache/vysper/xmpp/stanza/XMPPCoreStanzaVerifier.java Wed May 30 15:07:38 2007
@@ -0,0 +1,39 @@
+/***********************************************************************
+ * Copyright (c) 2006-2007 The Apache Software Foundation.             *
+ * All rights reserved.                                                *
+ * ------------------------------------------------------------------- *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you *
+ * may not use this file except in compliance with the License. You    *
+ * may obtain a copy of the License at:                                *
+ *                                                                     *
+ *     http://www.apache.org/licenses/LICENSE-2.0                      *
+ *                                                                     *
+ * Unless required by applicable law or agreed to in writing, software *
+ * distributed under the License is distributed on an "AS IS" BASIS,   *
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or     *
+ * implied.  See the License for the specific language governing       *
+ * permissions and limitations under the License.                      *
+ ***********************************************************************/
+
+package org.apache.vysper.xmpp.stanza;
+
+import org.apache.vysper.xmpp.protocol.NamespaceURIs;
+import org.apache.vysper.xmpp.xmlfragment.XMLElementVerifier;
+
+/**
+ */
+public class XMPPCoreStanzaVerifier extends XMLElementVerifier {
+
+    XMPPCoreStanzaVerifier(Stanza element) {
+        super(element);
+    }
+
+    public boolean isInterServerCall() {
+        boolean clientCall = namespacePresent(NamespaceURIs.JABBER_CLIENT);
+        boolean serverCall = namespacePresent(NamespaceURIs.JABBER_SERVER);
+
+        if (clientCall && serverCall) serverCall = false; // silently ignore ambigous attributes
+        return serverCall;
+    }
+
+}

Added: labs/vysper/src/main/java/org/apache/vysper/xmpp/writer/StanzaWriter.java
URL: http://svn.apache.org/viewvc/labs/vysper/src/main/java/org/apache/vysper/xmpp/writer/StanzaWriter.java?view=auto&rev=542950
==============================================================================
--- labs/vysper/src/main/java/org/apache/vysper/xmpp/writer/StanzaWriter.java (added)
+++ labs/vysper/src/main/java/org/apache/vysper/xmpp/writer/StanzaWriter.java Wed May 30 15:07:38 2007
@@ -0,0 +1,32 @@
+/***********************************************************************
+ * Copyright (c) 2006-2007 The Apache Software Foundation.             *
+ * All rights reserved.                                                *
+ * ------------------------------------------------------------------- *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you *
+ * may not use this file except in compliance with the License. You    *
+ * may obtain a copy of the License at:                                *
+ *                                                                     *
+ *     http://www.apache.org/licenses/LICENSE-2.0                      *
+ *                                                                     *
+ * Unless required by applicable law or agreed to in writing, software *
+ * distributed under the License is distributed on an "AS IS" BASIS,   *
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or     *
+ * implied.  See the License for the specific language governing       *
+ * permissions and limitations under the License.                      *
+ ***********************************************************************/
+
+package org.apache.vysper.xmpp.writer;
+
+import org.apache.vysper.xmpp.stanza.Stanza;
+
+/**
+ * write stanzas to a stream or other output target
+ * the writer must assure that the first, opening stanza is only closed
+ * when the writer is closed
+ */
+public interface StanzaWriter {
+
+    void write(Stanza stanza);
+
+    void close();
+}

Added: labs/vysper/src/main/java/org/apache/vysper/xmpp/writer/SystemOutStanzaWriter.java
URL: http://svn.apache.org/viewvc/labs/vysper/src/main/java/org/apache/vysper/xmpp/writer/SystemOutStanzaWriter.java?view=auto&rev=542950
==============================================================================
--- labs/vysper/src/main/java/org/apache/vysper/xmpp/writer/SystemOutStanzaWriter.java (added)
+++ labs/vysper/src/main/java/org/apache/vysper/xmpp/writer/SystemOutStanzaWriter.java Wed May 30 15:07:38 2007
@@ -0,0 +1,50 @@
+/***********************************************************************
+ * Copyright (c) 2006-2007 The Apache Software Foundation.             *
+ * 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     *
+ * permissions and limitations under the License.                      *
+ ***********************************************************************/
+
+package org.apache.vysper.xmpp.writer;
+
+import org.apache.vysper.xmpp.stanza.Stanza;
+import org.apache.vysper.xmpp.xmlfragment.Renderer;
+
+/**
+ * writes stanza to System.out
+ */
+public class SystemOutStanzaWriter implements StanzaWriter {
+
+    boolean isFirst = true;
+    private String closingElement;
+
+    public void writeXMLProlog() {
+        System.out.println("<?xml version=\"1.0\"?>");
+    }
+
+    public void write(Stanza stanza) {
+        Renderer renderer = new Renderer(stanza);
+        System.out.print(renderer.getOpeningElement() + renderer.getElementContent());
+
+        if (isFirst) closingElement = renderer.getClosingElement();
+        else System.out.print(closingElement);
+
+        isFirst = false;
+    }
+
+    public void close() {
+        if (closingElement == null) {
+            System.out.print(closingElement);
+        }
+        closingElement = null;
+    }
+}

Added: labs/vysper/src/main/java/org/apache/vysper/xmpp/xmlfragment/Attribute.java
URL: http://svn.apache.org/viewvc/labs/vysper/src/main/java/org/apache/vysper/xmpp/xmlfragment/Attribute.java?view=auto&rev=542950
==============================================================================
--- labs/vysper/src/main/java/org/apache/vysper/xmpp/xmlfragment/Attribute.java (added)
+++ labs/vysper/src/main/java/org/apache/vysper/xmpp/xmlfragment/Attribute.java Wed May 30 15:07:38 2007
@@ -0,0 +1,60 @@
+/***********************************************************************
+ * Copyright (c) 2006-2007 The Apache Software Foundation.             *
+ * All rights reserved.                                                *
+ * ------------------------------------------------------------------- *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you *
+ * may not use this file except in compliance with the License. You    *
+ * may obtain a copy of the License at:                                *
+ *                                                                     *
+ *     http://www.apache.org/licenses/LICENSE-2.0                      *
+ *                                                                     *
+ * Unless required by applicable law or agreed to in writing, software *
+ * distributed under the License is distributed on an "AS IS" BASIS,   *
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or     *
+ * implied.  See the License for the specific language governing       *
+ * permissions and limitations under the License.                      *
+ ***********************************************************************/
+
+package org.apache.vysper.xmpp.xmlfragment;
+
+/**
+ * represents an XML element's attribute
+ */
+public class Attribute {
+    private String name;
+    private String value;
+
+    public Attribute(String name, String value) {
+        if (name == null) throw new IllegalArgumentException("name must not be null");
+        if (value == null) throw new IllegalArgumentException("value must not be null");
+        this.name = name;
+        this.value = value;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public String getValue() {
+        return value;
+    }
+
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (o == null || !(o instanceof Attribute)) return false;
+
+        final Attribute attribute = (Attribute) o;
+
+        if (name != null ? !name.equals(attribute.name) : attribute.name != null) return false;
+        if (value != null ? !value.equals(attribute.value) : attribute.value != null) return false;
+
+        return true;
+    }
+
+    public int hashCode() {
+        int result;
+        result = (name != null ? name.hashCode() : 0);
+        result = 29 * result + (value != null ? value.hashCode() : 0);
+        return result;
+    }
+}

Added: labs/vysper/src/main/java/org/apache/vysper/xmpp/xmlfragment/FragmentFactory.java
URL: http://svn.apache.org/viewvc/labs/vysper/src/main/java/org/apache/vysper/xmpp/xmlfragment/FragmentFactory.java?view=auto&rev=542950
==============================================================================
--- labs/vysper/src/main/java/org/apache/vysper/xmpp/xmlfragment/FragmentFactory.java (added)
+++ labs/vysper/src/main/java/org/apache/vysper/xmpp/xmlfragment/FragmentFactory.java Wed May 30 15:07:38 2007
@@ -0,0 +1,53 @@
+/***********************************************************************
+ * Copyright (c) 2006-2007 The Apache Software Foundation.             *
+ * All rights reserved.                                                *
+ * ------------------------------------------------------------------- *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you *
+ * may not use this file except in compliance with the License. You    *
+ * may obtain a copy of the License at:                                *
+ *                                                                     *
+ *     http://www.apache.org/licenses/LICENSE-2.0                      *
+ *                                                                     *
+ * Unless required by applicable law or agreed to in writing, software *
+ * distributed under the License is distributed on an "AS IS" BASIS,   *
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or     *
+ * implied.  See the License for the specific language governing       *
+ * permissions and limitations under the License.                      *
+ ***********************************************************************/
+
+package org.apache.vysper.xmpp.xmlfragment;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * convenience methods for creating XML fragments
+ */
+public class FragmentFactory {
+    public static XMLElement createElementWithInnerText(String name, String text) {
+        return new XMLElement(name, null, (List<Attribute>)null, asList(new XMLText(text)));
+    }
+
+    public static List<XMLFragment> asList(XMLFragment xmlFragment) {
+        List<XMLFragment> xmlFragments = new ArrayList<XMLFragment>();
+        if (xmlFragment != null) xmlFragments.add(xmlFragment);
+        return xmlFragments;
+    }
+
+    public static List<Attribute> asList(Attribute attribute) {
+        List<Attribute> attributes = new ArrayList<Attribute>();
+        if (attribute != null) attributes.add(attribute);
+        return attributes;
+    }
+
+    public static List<XMLFragment> asList(XMLFragment[] xmlFragmentArray) {
+        if (xmlFragmentArray == null) return new ArrayList<XMLFragment>();
+        return Arrays.asList(xmlFragmentArray);
+    }
+
+    public static List<Attribute> asList(Attribute[] attributeArray) {
+        if (attributeArray == null) return new ArrayList<Attribute>();
+        return Arrays.asList(attributeArray);
+    }
+}

Added: labs/vysper/src/main/java/org/apache/vysper/xmpp/xmlfragment/NamespaceAttribute.java
URL: http://svn.apache.org/viewvc/labs/vysper/src/main/java/org/apache/vysper/xmpp/xmlfragment/NamespaceAttribute.java?view=auto&rev=542950
==============================================================================
--- labs/vysper/src/main/java/org/apache/vysper/xmpp/xmlfragment/NamespaceAttribute.java (added)
+++ labs/vysper/src/main/java/org/apache/vysper/xmpp/xmlfragment/NamespaceAttribute.java Wed May 30 15:07:38 2007
@@ -0,0 +1,36 @@
+/***********************************************************************
+ * Copyright (c) 2006-2007 The Apache Software Foundation.             *
+ * All rights reserved.                                                *
+ * ------------------------------------------------------------------- *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you *
+ * may not use this file except in compliance with the License. You    *
+ * may obtain a copy of the License at:                                *
+ *                                                                     *
+ *     http://www.apache.org/licenses/LICENSE-2.0                      *
+ *                                                                     *
+ * Unless required by applicable law or agreed to in writing, software *
+ * distributed under the License is distributed on an "AS IS" BASIS,   *
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or     *
+ * implied.  See the License for the specific language governing       *
+ * permissions and limitations under the License.                      *
+ ***********************************************************************/
+
+package org.apache.vysper.xmpp.xmlfragment;
+
+/**
+ */
+public class NamespaceAttribute extends Attribute {
+
+    public static final String DEFAULT_NAMESPACE = "";
+
+    public static final String XMLNS = "xmlns";
+    public static final String XMLNS_COLON = "xmlns:";
+
+    public NamespaceAttribute(String value) {
+        super(XMLNS, value);
+    }
+
+    public NamespaceAttribute(String nsPrefix, String value) {
+        super(XMLNS_COLON + nsPrefix, value);
+    }
+}

Added: labs/vysper/src/main/java/org/apache/vysper/xmpp/xmlfragment/Renderer.java
URL: http://svn.apache.org/viewvc/labs/vysper/src/main/java/org/apache/vysper/xmpp/xmlfragment/Renderer.java?view=auto&rev=542950
==============================================================================
--- labs/vysper/src/main/java/org/apache/vysper/xmpp/xmlfragment/Renderer.java (added)
+++ labs/vysper/src/main/java/org/apache/vysper/xmpp/xmlfragment/Renderer.java Wed May 30 15:07:38 2007
@@ -0,0 +1,76 @@
+/***********************************************************************
+ * Copyright (c) 2006-2007 The Apache Software Foundation.             *
+ * All rights reserved.                                                *
+ * ------------------------------------------------------------------- *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you *
+ * may not use this file except in compliance with the License. You    *
+ * may obtain a copy of the License at:                                *
+ *                                                                     *
+ *     http://www.apache.org/licenses/LICENSE-2.0                      *
+ *                                                                     *
+ * Unless required by applicable law or agreed to in writing, software *
+ * distributed under the License is distributed on an "AS IS" BASIS,   *
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or     *
+ * implied.  See the License for the specific language governing       *
+ * permissions and limitations under the License.                      *
+ ***********************************************************************/
+
+package org.apache.vysper.xmpp.xmlfragment;
+
+/**
+ * TODO support namespaces
+ * TODO force "stream" for "http://etherx.jabber.org/streams"
+ */
+public class Renderer {
+
+    private XMLElement topElement;
+    private StringBuffer openElementBuffer = new StringBuffer();
+    private StringBuffer elementContentBuffer = new StringBuffer();
+    private StringBuffer closeElementBuffer = new StringBuffer();
+
+    public Renderer(XMLElement element) {
+        this.topElement = element;
+        renderXMLElement(topElement, openElementBuffer, elementContentBuffer, closeElementBuffer);
+
+    }
+
+    public String getOpeningElement() {
+        return openElementBuffer.toString();
+    }
+
+    public String getElementContent() {
+        return elementContentBuffer.toString();
+    }
+
+    public String getClosingElement() {
+        return closeElementBuffer.toString();
+    }
+
+    public String getComplete() {
+        return openElementBuffer.toString() + elementContentBuffer.toString() + closeElementBuffer.toString();
+    }
+
+    private void renderXMLElement(XMLElement element, StringBuffer openElementBuffer, StringBuffer elementContentBuffer, StringBuffer closeElementBuffer) {
+        String name = element.getName();
+
+        openElementBuffer.append("<").append(name);
+        for (Attribute attribute : element.getAttributes()) {
+            openElementBuffer.append(" ");
+            renderAttribute(openElementBuffer, attribute);
+        }
+        openElementBuffer.append(">");
+
+        for (XMLFragment xmlFragment : element.getInnerFragments()) {
+            if (xmlFragment instanceof XMLElement) renderXMLElement((XMLElement) xmlFragment, elementContentBuffer, elementContentBuffer, elementContentBuffer);
+            else if (xmlFragment instanceof XMLText) ((XMLText) xmlFragment).getText();
+            else throw new UnsupportedOperationException("cannot render XML fragement of type " + xmlFragment.getClass().getName());
+        }
+
+        closeElementBuffer.append("</").append(name).append(">");
+
+    }
+
+    private void renderAttribute(StringBuffer buffer, Attribute attribute) {
+        buffer.append(attribute.getName()).append("=\"").append(attribute.getValue()).append("\"");
+    }
+}

Added: labs/vysper/src/main/java/org/apache/vysper/xmpp/xmlfragment/XMLElement.java
URL: http://svn.apache.org/viewvc/labs/vysper/src/main/java/org/apache/vysper/xmpp/xmlfragment/XMLElement.java?view=auto&rev=542950
==============================================================================
--- labs/vysper/src/main/java/org/apache/vysper/xmpp/xmlfragment/XMLElement.java (added)
+++ labs/vysper/src/main/java/org/apache/vysper/xmpp/xmlfragment/XMLElement.java Wed May 30 15:07:38 2007
@@ -0,0 +1,115 @@
+/***********************************************************************
+ * Copyright (c) 2006-2007 The Apache Software Foundation.             *
+ * All rights reserved.                                                *
+ * ------------------------------------------------------------------- *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you *
+ * may not use this file except in compliance with the License. You    *
+ * may obtain a copy of the License at:                                *
+ *                                                                     *
+ *     http://www.apache.org/licenses/LICENSE-2.0                      *
+ *                                                                     *
+ * Unless required by applicable law or agreed to in writing, software *
+ * distributed under the License is distributed on an "AS IS" BASIS,   *
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or     *
+ * implied.  See the License for the specific language governing       *
+ * permissions and limitations under the License.                      *
+ ***********************************************************************/
+
+package org.apache.vysper.xmpp.xmlfragment;
+
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * an immutable xml element specialized for XMPP.
+ *
+ * TODO add unit test
+ */
+public class XMLElement implements XMLFragment {
+
+    private String name;
+    private String namespace;
+    private List<Attribute> attributes;
+    private List<XMLFragment> innerFragments;
+    protected XMLElementVerifier xmlElementVerifier;
+
+    public XMLElement(String name, String namespace, Attribute[] attributes, XMLFragment[] innerFragments) {
+        this(name, namespace, FragmentFactory.asList(attributes), FragmentFactory.asList(innerFragments));
+    }
+
+     public XMLElement(String name, String namespace, List<Attribute> attributes, XMLFragment[] innerFragments) {
+        this(name, namespace, attributes, FragmentFactory.asList(innerFragments));
+    }
+
+     public XMLElement(String name, String namespace, Attribute[] attributes, List<XMLFragment> innerFragments) {
+        this(name, namespace, FragmentFactory.asList(attributes), innerFragments);
+    }
+
+    public XMLElement(String name, String namespace, List<Attribute> attributes, List<XMLFragment> innerFragments) {
+        this.namespace = namespace == null ? NamespaceAttribute.DEFAULT_NAMESPACE : namespace;
+        this.name = name;
+        this.attributes = (attributes == null) ? Collections.EMPTY_LIST : Collections.unmodifiableList(attributes);
+        this.innerFragments = (innerFragments == null) ? Collections.EMPTY_LIST : Collections.unmodifiableList(innerFragments);
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public String getNamespace() {
+        return namespace;
+    }
+
+    public List<Attribute> getAttributes() {
+        return attributes;
+    }
+
+    public Attribute getAttribute(String name) {
+        for (Attribute attribute : attributes) {
+            if (attribute.getName().equals(name)) return attribute;
+        }
+        return null;
+    }
+
+    public List<XMLFragment> getInnerFragments() {
+        return innerFragments;
+    }
+
+    public XMLElement getFirstInnerElement() {
+        if (innerFragments == null || innerFragments.size() < 1) return null;
+        for (XMLFragment xmlFragment : innerFragments) {
+            if (xmlFragment instanceof XMLElement) return (XMLElement)xmlFragment;
+        }
+        return null;
+    }
+
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (o == null || !(o instanceof XMLElement)) return false;
+
+        final XMLElement that = (XMLElement) o;
+
+        if (attributes != null ? !attributes.equals(that.attributes) : that.attributes != null) return false;
+        if (innerFragments != null ? !innerFragments.equals(that.innerFragments) : that.innerFragments != null) {
+            return false;
+        }
+        if (name != null ? !name.equals(that.name) : that.name != null) return false;
+        if (namespace != null ? !namespace.equals(that.namespace) : that.namespace != null) return false;
+
+        return true;
+    }
+
+    public int hashCode() {
+        int result;
+        result = (name != null ? name.hashCode() : 0);
+        result = 29 * result + (namespace != null ? namespace.hashCode() : 0);
+        result = 29 * result + (attributes != null ? attributes.hashCode() : 0);
+        result = 29 * result + (innerFragments != null ? innerFragments.hashCode() : 0);
+        return result;
+    }
+
+    public XMLElementVerifier getVerifier() {
+        if (xmlElementVerifier == null) xmlElementVerifier = new XMLElementVerifier(this);
+        return xmlElementVerifier;
+    }
+}

Added: labs/vysper/src/main/java/org/apache/vysper/xmpp/xmlfragment/XMLElementVerifier.java
URL: http://svn.apache.org/viewvc/labs/vysper/src/main/java/org/apache/vysper/xmpp/xmlfragment/XMLElementVerifier.java?view=auto&rev=542950
==============================================================================
--- labs/vysper/src/main/java/org/apache/vysper/xmpp/xmlfragment/XMLElementVerifier.java (added)
+++ labs/vysper/src/main/java/org/apache/vysper/xmpp/xmlfragment/XMLElementVerifier.java Wed May 30 15:07:38 2007
@@ -0,0 +1,100 @@
+/***********************************************************************
+ * Copyright (c) 2006-2007 The Apache Software Foundation.             *
+ * All rights reserved.                                                *
+ * ------------------------------------------------------------------- *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you *
+ * may not use this file except in compliance with the License. You    *
+ * may obtain a copy of the License at:                                *
+ *                                                                     *
+ *     http://www.apache.org/licenses/LICENSE-2.0                      *
+ *                                                                     *
+ * Unless required by applicable law or agreed to in writing, software *
+ * distributed under the License is distributed on an "AS IS" BASIS,   *
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or     *
+ * implied.  See the License for the specific language governing       *
+ * permissions and limitations under the License.                      *
+ ***********************************************************************/
+
+package org.apache.vysper.xmpp.xmlfragment;
+
+import java.util.List;
+
+/**
+ * provides common tools to check a element against its specification or semantical context
+ * this classes instances are immutual.
+ *
+ * TODO add unit test
+ */
+public class XMLElementVerifier {
+    protected XMLElement element;
+
+    protected XMLElementVerifier(XMLElement element) {
+        if (element == null) throw new IllegalArgumentException("null not allowed for element");
+        this.element = element;
+    }
+
+    public boolean nameEquals(String name) {
+        return element.getName().equals(name);
+    }
+
+    public boolean attributePresent(String name) {
+        return null != element.getAttribute(name);
+    }
+
+    public boolean attributeEquals(String name, String value) {
+        return attributePresent(name) && element.getAttribute(name).getValue().equals(value);
+    }
+
+    public boolean subElementPresent(String name) {
+        for (XMLFragment xmlFragment : element.getInnerFragments()) {
+            if (xmlFragment instanceof XMLElement) {
+                XMLElement xmlElement = (XMLElement) xmlFragment;
+                if (xmlElement.getName().equals(name)) return true;
+            }
+        }
+        return false;
+    }
+
+    public boolean subElementsPresentExact(int numberOfSubelements) {
+        return element.getInnerFragments().size() == numberOfSubelements;
+    }
+
+    public boolean subElementsPresentAtLeast(int numberOfSubelements) {
+        return element.getInnerFragments().size() >= numberOfSubelements;
+    }
+
+    public boolean subElementsPresentAtMost(int numberOfSubelements) {
+        return element.getInnerFragments().size() <= numberOfSubelements;
+    }
+
+    public boolean namespacePresent(String namespaceURI) {
+        for (Attribute attribute : element.getAttributes()) {
+            if ((attribute.getName().equalsIgnoreCase(NamespaceAttribute.XMLNS)
+                 || attribute.getName().startsWith(NamespaceAttribute.XMLNS_COLON))
+                && attribute.getValue().equals(namespaceURI)) {
+                return true;
+            }
+        }
+        return false; // not present
+    }
+
+    public boolean toAttributeEquals(String toValue) {
+        return attributeEquals("to", toValue);
+    }
+
+    public boolean fromAttributeEquals(String fromValue) {
+        return attributeEquals("from", fromValue);
+    }
+
+    public boolean onlySubelementEquals(String name, String namespaceURI) {
+        List<XMLFragment> innerFragments = element.getInnerFragments();
+
+        // really is only subelement
+        if (innerFragments == null || innerFragments.size() != 1) return false;
+        XMLFragment onlySubelement = innerFragments.get(0);
+        if (!(onlySubelement instanceof XMLElement)) return false;
+
+        XMLElement xmlElement = ((XMLElement) onlySubelement);
+        return name.equals(xmlElement.getName()) && namespaceURI.equals(xmlElement.getNamespace());
+    }
+}



---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@labs.apache.org
For additional commands, e-mail: commits-help@labs.apache.org