You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mina.apache.org by be...@apache.org on 2013/07/04 13:18:04 UTC

[2/2] git commit: move JCR storage code over to dedicated module

move JCR storage code over to dedicated module


Project: http://git-wip-us.apache.org/repos/asf/mina-vysper/repo
Commit: http://git-wip-us.apache.org/repos/asf/mina-vysper/commit/46f1a8ef
Tree: http://git-wip-us.apache.org/repos/asf/mina-vysper/tree/46f1a8ef
Diff: http://git-wip-us.apache.org/repos/asf/mina-vysper/diff/46f1a8ef

Branch: refs/heads/master
Commit: 46f1a8eff08244af21510262a84fc5b4fb4331af
Parents: 3515de6
Author: Bernd Fondermann <be...@brainlounge.de>
Authored: Thu Jul 4 13:15:08 2013 +0200
Committer: Bernd Fondermann <be...@brainlounge.de>
Committed: Thu Jul 4 13:15:08 2013 +0200

----------------------------------------------------------------------
 server/core/pom.xml                             |  14 -
 .../apache/vysper/storage/jcr/JcrStorage.java   | 130 ----------
 .../vysper/storage/jcr/JcrStorageException.java |  41 ---
 .../storage/jcr/JcrStorageProviderRegistry.java |  41 ---
 .../JcrPrivateDataPersistenceManager.java       |  91 -------
 .../storage/jcr/roster/JcrRosterManager.java    | 257 -------------------
 .../storage/jcr/user/JcrUserManagement.java     | 118 ---------
 .../JcrVcardTempPersistenceManager.java         |  92 -------
 .../apache/vysper/storage/jcr/JcrStorage.java   | 130 ++++++++++
 .../vysper/storage/jcr/JcrStorageException.java |  41 +++
 .../storage/jcr/JcrStorageProviderRegistry.java |  41 +++
 .../JcrPrivateDataPersistenceManager.java       |  91 +++++++
 .../storage/jcr/roster/JcrRosterManager.java    | 257 +++++++++++++++++++
 .../storage/jcr/user/JcrUserManagement.java     | 118 +++++++++
 .../JcrVcardTempPersistenceManager.java         |  92 +++++++
 15 files changed, 770 insertions(+), 784 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/mina-vysper/blob/46f1a8ef/server/core/pom.xml
----------------------------------------------------------------------
diff --git a/server/core/pom.xml b/server/core/pom.xml
index 5def5c3..11c4cfa 100644
--- a/server/core/pom.xml
+++ b/server/core/pom.xml
@@ -67,20 +67,6 @@
       <artifactId>mina-core</artifactId>
     </dependency>
 
-<!-- TODO remove... -->      
-    <dependency>
-      <groupId>javax.jcr</groupId>
-      <artifactId>jcr</artifactId>
-      <optional>true</optional>
-    </dependency>
-
-    <dependency>
-      <groupId>org.apache.jackrabbit</groupId>
-      <artifactId>jackrabbit-core</artifactId>
-      <optional>true</optional>
-    </dependency>
-<!-- ...TODO remove -->      
-
     <dependency>
       <groupId>commons-codec</groupId>
       <artifactId>commons-codec</artifactId>

http://git-wip-us.apache.org/repos/asf/mina-vysper/blob/46f1a8ef/server/core/src/main/java/org/apache/vysper/storage/jcr/JcrStorage.java
----------------------------------------------------------------------
diff --git a/server/core/src/main/java/org/apache/vysper/storage/jcr/JcrStorage.java b/server/core/src/main/java/org/apache/vysper/storage/jcr/JcrStorage.java
deleted file mode 100644
index 670877c..0000000
--- a/server/core/src/main/java/org/apache/vysper/storage/jcr/JcrStorage.java
+++ /dev/null
@@ -1,130 +0,0 @@
-/*
- *  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.storage.jcr;
-
-import javax.jcr.Node;
-import javax.jcr.Repository;
-import javax.jcr.RepositoryException;
-import javax.jcr.Session;
-import javax.jcr.SimpleCredentials;
-
-import org.apache.jackrabbit.core.TransientRepository;
-import org.apache.vysper.xmpp.addressing.Entity;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * back-end stuff for JCR, used by the semantic specific adapters
- * @author The Apache MINA Project (dev@mina.apache.org)
- */
-public class JcrStorage {
-
-    final Logger logger = LoggerFactory.getLogger(JcrStorage.class);
-
-    protected static JcrStorage jcrStorageSingleton;
-
-    protected JcrStorage() {
-        super();
-        // protected
-    }
-
-    public static JcrStorage getInstance() {
-        synchronized (JcrStorage.class) {
-            if (jcrStorageSingleton == null)
-                jcrStorageSingleton = new JcrStorage();
-            return jcrStorageSingleton;
-        }
-    }
-
-    protected Session session = null;
-
-    public Session getRepositorySession() throws JcrStorageException {
-        if (session != null)
-            return session;
-        try {
-            Repository repository = new TransientRepository();
-            session = repository.login(new SimpleCredentials("xmpp-admin", "adminpassword".toCharArray()));
-            return session;
-        } catch (Exception e) {
-            throw new JcrStorageException(e);
-        }
-    }
-
-    public Node getRootNode() throws JcrStorageException {
-        try {
-            return getRepositorySession().getRootNode();
-        } catch (RepositoryException e) {
-            throw new JcrStorageException(e);
-        }
-    }
-
-    public Node getEntityNode(Entity bareEntity, String namespace, boolean createIfMissing) throws JcrStorageException {
-        bareEntity = bareEntity.getBareJID(); // make it really sure
-        if (namespace != null)
-            namespace = namespace.replace(':', '_');
-        final String path = "/accountentity/" + bareEntity.getFullQualifiedName()
-                + (namespace != null ? "/" + namespace : "");
-        if (!itemExists(path)) {
-            if (!createIfMissing)
-                return null;
-            Node accountEntityNode = getOrCreate(getRootNode(), "accountentity");
-            Node entityNode = getOrCreate(accountEntityNode, bareEntity.getFullQualifiedName());
-            if (namespace != null)
-                entityNode = getOrCreate(entityNode, namespace);
-            return entityNode;
-        } else {
-            try {
-                return (Node) getRepositorySession().getItem(path);
-            } catch (RepositoryException e) {
-                throw new JcrStorageException(e);
-            }
-        }
-    }
-
-    private boolean itemExists(String absolutePath) throws JcrStorageException {
-        try {
-            return getRepositorySession().itemExists(absolutePath);
-        } catch (RepositoryException e) {
-            throw new JcrStorageException(e);
-        } catch (JcrStorageException e) {
-            throw e;
-        }
-    }
-
-    protected Node getOrCreate(Node parent, String nodeName) throws JcrStorageException {
-        Node childNode;
-        try {
-            childNode = parent.getNode(nodeName);
-        } catch (RepositoryException e) {
-            childNode = null;
-        }
-        if (childNode == null) {
-            try {
-                childNode = parent.addNode(nodeName);
-                parent.save();
-                childNode.save();
-                logger.info("JCR node created: " + childNode);
-            } catch (RepositoryException e) {
-                throw new JcrStorageException(e);
-            }
-        }
-        return childNode;
-    }
-}

http://git-wip-us.apache.org/repos/asf/mina-vysper/blob/46f1a8ef/server/core/src/main/java/org/apache/vysper/storage/jcr/JcrStorageException.java
----------------------------------------------------------------------
diff --git a/server/core/src/main/java/org/apache/vysper/storage/jcr/JcrStorageException.java b/server/core/src/main/java/org/apache/vysper/storage/jcr/JcrStorageException.java
deleted file mode 100644
index d4747c5..0000000
--- a/server/core/src/main/java/org/apache/vysper/storage/jcr/JcrStorageException.java
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- *  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.storage.jcr;
-
-/**
- * @author The Apache MINA Project (dev@mina.apache.org)
- */
-public class JcrStorageException extends Exception {
-    public JcrStorageException() {
-        super();
-    }
-
-    public JcrStorageException(String message) {
-        super(message);
-    }
-
-    public JcrStorageException(String message, Throwable cause) {
-        super(message, cause);
-    }
-
-    public JcrStorageException(Throwable cause) {
-        super(cause);
-    }
-}

http://git-wip-us.apache.org/repos/asf/mina-vysper/blob/46f1a8ef/server/core/src/main/java/org/apache/vysper/storage/jcr/JcrStorageProviderRegistry.java
----------------------------------------------------------------------
diff --git a/server/core/src/main/java/org/apache/vysper/storage/jcr/JcrStorageProviderRegistry.java b/server/core/src/main/java/org/apache/vysper/storage/jcr/JcrStorageProviderRegistry.java
deleted file mode 100644
index d4393d7..0000000
--- a/server/core/src/main/java/org/apache/vysper/storage/jcr/JcrStorageProviderRegistry.java
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- *  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.storage.jcr;
-
-import org.apache.vysper.storage.OpenStorageProviderRegistry;
-import org.apache.vysper.storage.jcr.privatedata.JcrPrivateDataPersistenceManager;
-import org.apache.vysper.storage.jcr.roster.JcrRosterManager;
-import org.apache.vysper.storage.jcr.user.JcrUserManagement;
-import org.apache.vysper.storage.jcr.vcardtemp.JcrVcardTempPersistenceManager;
-
-/**
- *
- * @author The Apache MINA Project (dev@mina.apache.org)
- */
-public class JcrStorageProviderRegistry extends OpenStorageProviderRegistry {
-
-    public JcrStorageProviderRegistry() {
-        add(new JcrUserManagement(JcrStorage.getInstance()));
-        add(new JcrRosterManager(JcrStorage.getInstance()));
-        add(new JcrVcardTempPersistenceManager(JcrStorage.getInstance()));
-        add(new JcrPrivateDataPersistenceManager(JcrStorage.getInstance()));
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/mina-vysper/blob/46f1a8ef/server/core/src/main/java/org/apache/vysper/storage/jcr/privatedata/JcrPrivateDataPersistenceManager.java
----------------------------------------------------------------------
diff --git a/server/core/src/main/java/org/apache/vysper/storage/jcr/privatedata/JcrPrivateDataPersistenceManager.java b/server/core/src/main/java/org/apache/vysper/storage/jcr/privatedata/JcrPrivateDataPersistenceManager.java
deleted file mode 100644
index 6a7544d..0000000
--- a/server/core/src/main/java/org/apache/vysper/storage/jcr/privatedata/JcrPrivateDataPersistenceManager.java
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
- *  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.storage.jcr.privatedata;
-
-import javax.jcr.Node;
-import javax.jcr.RepositoryException;
-import javax.jcr.Session;
-
-import org.apache.vysper.storage.jcr.JcrStorage;
-import org.apache.vysper.storage.jcr.JcrStorageException;
-import org.apache.vysper.xmpp.addressing.Entity;
-import org.apache.vysper.xmpp.modules.extension.xep0049_privatedata.PrivateDataPersistenceManager;
-import org.apache.vysper.xmpp.protocol.NamespaceURIs;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * @author The Apache MINA Project (dev@mina.apache.org)
- */
-public class JcrPrivateDataPersistenceManager implements PrivateDataPersistenceManager {
-
-    final Logger logger = LoggerFactory.getLogger(JcrPrivateDataPersistenceManager.class);
-
-    protected JcrStorage jcrStorage;
-
-    public JcrPrivateDataPersistenceManager(JcrStorage jcrStorage) {
-        this.jcrStorage = jcrStorage;
-    }
-
-    public boolean isAvailable() {
-        Session session = null;
-        try {
-            session = jcrStorage.getRepositorySession();
-            return session != null;
-        } catch (JcrStorageException e) {
-            return false;
-        }
-    }
-
-    public String getPrivateData(Entity entity, String key) {
-        Node entityNode = getEntityNodeSave(entity, false);
-        if (entityNode == null)
-            return null;
-        try {
-            return entityNode.getProperty(key).getString();
-        } catch (RepositoryException e) {
-            return null;
-        }
-    }
-
-    public boolean setPrivateData(Entity entity, String key, String xml) {
-        Node entityNode = getEntityNodeSave(entity, true);
-        try {
-            entityNode.setProperty(key, xml);
-            entityNode.save();
-            logger.info("JCR node created: " + entityNode);
-            return true;
-        } catch (RepositoryException e) {
-            return false;
-        }
-    }
-
-    private Node getEntityNodeSave(Entity entity, boolean createIfMissing) {
-        Node entityNode;
-        try {
-            entityNode = jcrStorage.getEntityNode(entity.getBareJID(), NamespaceURIs.PRIVATE_DATA, createIfMissing);
-        } catch (JcrStorageException e) {
-            return null;
-        }
-        if (entityNode == null)
-            return null;
-        return entityNode;
-    }
-}

http://git-wip-us.apache.org/repos/asf/mina-vysper/blob/46f1a8ef/server/core/src/main/java/org/apache/vysper/storage/jcr/roster/JcrRosterManager.java
----------------------------------------------------------------------
diff --git a/server/core/src/main/java/org/apache/vysper/storage/jcr/roster/JcrRosterManager.java b/server/core/src/main/java/org/apache/vysper/storage/jcr/roster/JcrRosterManager.java
deleted file mode 100644
index dbb92d7..0000000
--- a/server/core/src/main/java/org/apache/vysper/storage/jcr/roster/JcrRosterManager.java
+++ /dev/null
@@ -1,257 +0,0 @@
-/*
- *  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.storage.jcr.roster;
-
-import java.util.ArrayList;
-import java.util.List;
-
-import javax.jcr.Node;
-import javax.jcr.NodeIterator;
-import javax.jcr.Property;
-import javax.jcr.RepositoryException;
-
-import org.apache.vysper.storage.jcr.JcrStorage;
-import org.apache.vysper.storage.jcr.JcrStorageException;
-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.modules.roster.AskSubscriptionType;
-import org.apache.vysper.xmpp.modules.roster.MutableRoster;
-import org.apache.vysper.xmpp.modules.roster.Roster;
-import org.apache.vysper.xmpp.modules.roster.RosterException;
-import org.apache.vysper.xmpp.modules.roster.RosterGroup;
-import org.apache.vysper.xmpp.modules.roster.RosterItem;
-import org.apache.vysper.xmpp.modules.roster.SubscriptionType;
-import org.apache.vysper.xmpp.modules.roster.persistence.AbstractRosterManager;
-import org.apache.vysper.xmpp.protocol.NamespaceURIs;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * roster items are stored for contacts in the following path:
- * /accountentity/user@vysper.org/jabber_iq_roster/contact@vysper.org
- * all item properties besides contact jid (which is used as a node name)
- * are stored as node properties
- *
- * @author The Apache MINA Project (dev@mina.apache.org)
- */
-public class JcrRosterManager extends AbstractRosterManager {
-
-    final Logger logger = LoggerFactory.getLogger(JcrRosterManager.class);
-
-    protected JcrStorage jcrStorage;
-
-    public JcrRosterManager(JcrStorage jcrStorage) {
-        this.jcrStorage = jcrStorage;
-    }
-
-    /*package*/static Node retrieveRosterNode(JcrStorage jcrStorage, Entity bareJid) {
-        try {
-            if (jcrStorage.getEntityNode(bareJid, null, false) == null)
-                return null;
-            return jcrStorage.getEntityNode(bareJid, NamespaceURIs.JABBER_IQ_ROSTER, true);
-        } catch (JcrStorageException e) {
-            return null;
-        }
-    }
-
-    @Override
-    protected Roster retrieveRosterInternal(Entity bareJid) {
-        final Node rosterNode = retrieveRosterNode(jcrStorage, bareJid);
-
-        MutableRoster roster = new MutableRoster();
-
-        NodeIterator nodes = null;
-        try {
-            nodes = rosterNode.getNodes();
-        } catch (RepositoryException e) {
-            return roster; // empty roster object
-        }
-        while (nodes != null && nodes.hasNext()) {
-            Node node = nodes.nextNode();
-
-            String contactJidString = null;
-            try {
-                contactJidString = node.getName();
-            } catch (RepositoryException e) {
-                logger.warn("when loading roster for user {} cannot read node name for node id = " + node.toString());
-            }
-            logger.warn("try now loading contact " + contactJidString + " from node " + node.toString());
-            EntityImpl contactJid = null;
-            if (contactJidString != null) {
-                try {
-                    contactJid = EntityImpl.parse(contactJidString);
-                } catch (EntityFormatException e) {
-                    logger.warn("when loading roster for user {} parsing  contact jid {}", bareJid, contactJidString);
-                }
-            }
-            if (contactJid == null) {
-                logger.warn("when loading roster for user {}, skipping a contact due to missing or unparsable jid",
-                        bareJid);
-                continue;
-            }
-
-            String name = readAttribute(node, "name");
-            String typeString = readAttribute(node, "type");
-            SubscriptionType subscriptionType = null;
-            try {
-                subscriptionType = SubscriptionType.valueOf(typeString == null ? "NONE" : typeString.toUpperCase());
-            } catch (IllegalArgumentException e) {
-                logger.warn("when loading roster for user " + bareJid + ", contact " + contactJid
-                        + " misses a subscription type", bareJid, contactJid);
-            }
-            String askTypeString = readAttribute(node, "askType");
-            AskSubscriptionType askSubscriptionType = AskSubscriptionType.NOT_SET;
-            try {
-                if (askTypeString != null)
-                    askSubscriptionType = AskSubscriptionType.valueOf(askTypeString);
-            } catch (IllegalArgumentException e) {
-                logger.warn("when loading roster for user " + bareJid.getFullQualifiedName() + ", contact "
-                        + contactJid.getFullQualifiedName() + ", the ask subscription type is unparsable. skipping!");
-                continue; // don't return it, don't set a default!
-            }
-
-            List<RosterGroup> groups = new ArrayList<RosterGroup>();
-            // TODO read groups
-
-            RosterItem item = new RosterItem(contactJid, name, subscriptionType, askSubscriptionType, groups);
-            logger.info("item loaded for " + bareJid.getFullQualifiedName() + ": " + item.toString());
-            roster.addItem(item);
-        }
-        return roster;
-    }
-
-    private String readAttribute(Node node, String propertyName) {
-        try {
-            Property property = node.getProperty(propertyName);
-            if (property == null)
-                return null;
-            return property.getString();
-        } catch (RepositoryException e) {
-            return null;
-        }
-    }
-
-    @Override
-    protected Roster addNewRosterInternal(Entity jid) {
-        return new MutableRoster();
-    }
-
-    @Override
-    public void addContact(Entity jid, RosterItem rosterItem) throws RosterException {
-        if (jid == null)
-            throw new RosterException("jid not provided");
-        if (rosterItem.getJid() == null)
-            throw new RosterException("contact jid not provided");
-
-        // TODO think about concurrent updates
-
-        Entity contactJid = rosterItem.getJid().getBareJID();
-        Node contactNode = getOrCreateContactNode(jid, contactJid);
-        try {
-            setOrRemoveAttribute(contactNode, "name", rosterItem.getName());
-            String subscriptionTypeValue = rosterItem.getSubscriptionType() == null ? null : rosterItem
-                    .getSubscriptionType().value();
-            setOrRemoveAttribute(contactNode, "type", subscriptionTypeValue);
-            String askSubscriptionTypeValue = null;
-            if (rosterItem.getAskSubscriptionType() != null
-                    && rosterItem.getAskSubscriptionType() != AskSubscriptionType.NOT_SET) {
-                askSubscriptionTypeValue = rosterItem.getAskSubscriptionType().value();
-            }
-            setOrRemoveAttribute(contactNode, "askType", askSubscriptionTypeValue);
-            contactNode.save();
-            logger.info("JCR node created/updated: " + contactNode);
-        } catch (RepositoryException e) {
-            throw new RosterException("failed to add contact node to roster for user = " + jid.getFullQualifiedName()
-                    + " and contact jid = " + rosterItem.getJid().getFullQualifiedName(), e);
-        }
-    }
-
-    private void setOrRemoveAttribute(Node contactNode, String attributeName, String attributeValue)
-            throws RepositoryException {
-        if (attributeValue != null)
-            contactNode.setProperty(attributeName, attributeValue);
-        else if (contactNode.hasProperty(attributeName))
-            contactNode.setProperty(attributeName, (String) null);
-    }
-
-    private Node getOrCreateContactNode(Entity jid, Entity contactJid) throws RosterException {
-        Node entityNode = null;
-        try {
-            entityNode = jcrStorage.getEntityNode(jid, NamespaceURIs.JABBER_IQ_ROSTER, true);
-        } catch (JcrStorageException e) {
-            throw new RosterException("failed to create roster store for " + jid.getFullQualifiedName(), e);
-        }
-        Node contactNode = null;
-        try {
-            contactNode = entityNode.getNode(contactJid.getFullQualifiedName());
-        } catch (RepositoryException e) {
-            // not exists, create
-            try {
-                contactNode = entityNode.addNode(contactJid.getFullQualifiedName());
-                entityNode.save();
-            } catch (RepositoryException addNodeEx) {
-                throw new RosterException("failed to add contact node to roster for user = "
-                        + jid.getFullQualifiedName() + " and contact jid = " + contactJid.getFullQualifiedName(),
-                        addNodeEx);
-            }
-
-        }
-        return contactNode;
-    }
-
-    @Override
-    public void removeContact(Entity jidUser, Entity jidContact) throws RosterException {
-        if (jidUser == null)
-            throw new RosterException("jid not provided");
-        if (jidContact == null)
-            throw new RosterException("contact jid not provided");
-        Node rosterNode = null;
-        try {
-            rosterNode = jcrStorage.getEntityNode(jidUser, NamespaceURIs.JABBER_IQ_ROSTER, false);
-        } catch (JcrStorageException e) {
-            throw new RosterException("failed to retrieve roster store for " + jidUser.getFullQualifiedName(), e);
-        }
-        if (rosterNode == null)
-            return; // done, no contacts anyway. oops
-
-        NodeIterator nodes = null;
-        try {
-            nodes = rosterNode.getNodes("contact");
-        } catch (RepositoryException e) {
-            return; // failed to find any contacts, done.
-        }
-        boolean foundOne = false;
-        while (nodes != null && nodes.hasNext()) {
-            Node node = nodes.nextNode();
-            String contactJidString = readAttribute(node, "jid");
-            if (contactJidString != null && contactJidString.equals(jidContact.getFullQualifiedName())) {
-                foundOne = true;
-                try {
-                    node.remove();
-                } catch (RepositoryException e) {
-                    logger.warn("failed to remove from roster for user {} the contact jid " + jidContact, jidUser, e);
-                }
-            }
-        }
-        if (!foundOne)
-            logger.warn("failed to remove from roster for user " + jidUser + " the contact jid " + jidContact);
-    }
-}

http://git-wip-us.apache.org/repos/asf/mina-vysper/blob/46f1a8ef/server/core/src/main/java/org/apache/vysper/storage/jcr/user/JcrUserManagement.java
----------------------------------------------------------------------
diff --git a/server/core/src/main/java/org/apache/vysper/storage/jcr/user/JcrUserManagement.java b/server/core/src/main/java/org/apache/vysper/storage/jcr/user/JcrUserManagement.java
deleted file mode 100644
index 0f5da9f..0000000
--- a/server/core/src/main/java/org/apache/vysper/storage/jcr/user/JcrUserManagement.java
+++ /dev/null
@@ -1,118 +0,0 @@
-/*
- *  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.storage.jcr.user;
-
-import javax.jcr.Node;
-import javax.jcr.Property;
-
-import org.apache.vysper.storage.jcr.JcrStorage;
-import org.apache.vysper.storage.jcr.JcrStorageException;
-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.authentication.AccountCreationException;
-import org.apache.vysper.xmpp.authentication.AccountManagement;
-import org.apache.vysper.xmpp.authentication.UserAuthentication;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- *
- * @author The Apache MINA Project (dev@mina.apache.org)
- */
-public class JcrUserManagement implements UserAuthentication, AccountManagement {
-
-    final Logger logger = LoggerFactory.getLogger(JcrUserManagement.class);
-
-    protected JcrStorage jcrStorage;
-
-    private static final String CREDENTIALS_NAMESPACE = "vysper_internal_credentials";
-
-    public JcrUserManagement(JcrStorage jcrStorage) {
-        this.jcrStorage = jcrStorage;
-    }
-
-    public boolean verifyCredentials(Entity jid, String passwordCleartext, Object credentials) {
-        if (passwordCleartext == null)
-            return false;
-        try {
-            final Node credentialsNode = jcrStorage.getEntityNode(jid, CREDENTIALS_NAMESPACE, false);
-            if (credentialsNode == null)
-                return false;
-            final Property property = credentialsNode.getProperty("password");
-            if (property == null)
-                return false;
-            final String password = property.getValue().getString();
-            return passwordCleartext.equals(password);
-        } catch (Exception e) {
-            return false;
-        }
-    }
-
-    public boolean verifyCredentials(String username, String passwordCleartext, Object credentials) {
-        try {
-            return verifyCredentials(EntityImpl.parse(username), passwordCleartext, credentials);
-        } catch (EntityFormatException e) {
-            return false;
-        }
-    }
-
-    public boolean verifyAccountExists(Entity jid) {
-        try {
-            return jcrStorage.getEntityNode(jid, CREDENTIALS_NAMESPACE, false) != null;
-        } catch (JcrStorageException e) {
-            return false;
-        }
-    }
-
-    public void addUser(Entity username, String password) throws AccountCreationException {
-        // if already existent, don't create, throw error
-        try {
-            if (jcrStorage.getEntityNode(username, CREDENTIALS_NAMESPACE, false) != null) {
-                throw new AccountCreationException("account already exists: " + username.getFullQualifiedName());
-            }
-        } catch (JcrStorageException e) {
-            throw new AccountCreationException("account exists check failed for " + username.getFullQualifiedName(), e);
-        }
-        // now, finally, create
-        try {
-            final Node credentialsNode = jcrStorage.getEntityNode(username, CREDENTIALS_NAMESPACE, true);
-            credentialsNode.setProperty("password", password);
-            credentialsNode.save();
-            logger.info("JCR node created: " + credentialsNode);
-        } catch (Exception e) {
-            // TODO remove account?
-            throw new AccountCreationException("failed to create the account set credentials", e);
-        }
-
-    }
-
-    public void changePassword(Entity username, String password) throws AccountCreationException {
-        try {
-            final Node credentialsNode = jcrStorage.getEntityNode(username, CREDENTIALS_NAMESPACE, false);
-            credentialsNode.setProperty("password", password);
-            credentialsNode.save();
-            logger.info("JCR password changed: " + credentialsNode);
-        } catch (Exception e) {
-            // TODO remove account?
-            throw new AccountCreationException("failed to create the account set credentials", e);
-        }
-    }
-}

http://git-wip-us.apache.org/repos/asf/mina-vysper/blob/46f1a8ef/server/core/src/main/java/org/apache/vysper/storage/jcr/vcardtemp/JcrVcardTempPersistenceManager.java
----------------------------------------------------------------------
diff --git a/server/core/src/main/java/org/apache/vysper/storage/jcr/vcardtemp/JcrVcardTempPersistenceManager.java b/server/core/src/main/java/org/apache/vysper/storage/jcr/vcardtemp/JcrVcardTempPersistenceManager.java
deleted file mode 100644
index 293bad5..0000000
--- a/server/core/src/main/java/org/apache/vysper/storage/jcr/vcardtemp/JcrVcardTempPersistenceManager.java
+++ /dev/null
@@ -1,92 +0,0 @@
-/*
- *  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.storage.jcr.vcardtemp;
-
-import javax.jcr.Node;
-import javax.jcr.RepositoryException;
-import javax.jcr.Session;
-
-import org.apache.vysper.storage.jcr.JcrStorage;
-import org.apache.vysper.storage.jcr.JcrStorageException;
-import org.apache.vysper.xmpp.addressing.Entity;
-import org.apache.vysper.xmpp.modules.extension.xep0054_vcardtemp.VcardTempPersistenceManager;
-import org.apache.vysper.xmpp.protocol.NamespaceURIs;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- *
- * @author The Apache MINA Project (dev@mina.apache.org)
- */
-public class JcrVcardTempPersistenceManager implements VcardTempPersistenceManager {
-
-    final Logger logger = LoggerFactory.getLogger(JcrVcardTempPersistenceManager.class);
-
-    protected JcrStorage jcrStorage;
-
-    public JcrVcardTempPersistenceManager(JcrStorage jcrStorage) {
-        this.jcrStorage = jcrStorage;
-    }
-
-    public boolean isAvailable() {
-        Session session = null;
-        try {
-            session = jcrStorage.getRepositorySession();
-            return session != null;
-        } catch (JcrStorageException e) {
-            return false;
-        }
-    }
-
-    public String getVcard(Entity entity) {
-        Node entityNode = getEntityNodeSave(entity, false);
-        if (entityNode == null)
-            return null;
-        try {
-            return entityNode.getProperty("content").getString();
-        } catch (RepositoryException e) {
-            return null;
-        }
-    }
-
-    private Node getEntityNodeSave(Entity entity, boolean createIfMissing) {
-        Node entityNode;
-        try {
-            entityNode = jcrStorage.getEntityNode(entity.getBareJID(), NamespaceURIs.VCARD_TEMP, createIfMissing);
-        } catch (JcrStorageException e) {
-            return null;
-        }
-        if (entityNode == null)
-            return null;
-        return entityNode;
-    }
-
-    public boolean setVcard(Entity entity, String xml) {
-        Node entityNode = getEntityNodeSave(entity, true);
-        try {
-            entityNode.setProperty("content", xml);
-            entityNode.save();
-            logger.info("JCR node created: " + entityNode);
-            return true;
-        } catch (RepositoryException e) {
-            return false;
-        }
-    }
-}

http://git-wip-us.apache.org/repos/asf/mina-vysper/blob/46f1a8ef/server/storage/jcr/src/main/java/org/apache/vysper/storage/jcr/JcrStorage.java
----------------------------------------------------------------------
diff --git a/server/storage/jcr/src/main/java/org/apache/vysper/storage/jcr/JcrStorage.java b/server/storage/jcr/src/main/java/org/apache/vysper/storage/jcr/JcrStorage.java
new file mode 100644
index 0000000..670877c
--- /dev/null
+++ b/server/storage/jcr/src/main/java/org/apache/vysper/storage/jcr/JcrStorage.java
@@ -0,0 +1,130 @@
+/*
+ *  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.storage.jcr;
+
+import javax.jcr.Node;
+import javax.jcr.Repository;
+import javax.jcr.RepositoryException;
+import javax.jcr.Session;
+import javax.jcr.SimpleCredentials;
+
+import org.apache.jackrabbit.core.TransientRepository;
+import org.apache.vysper.xmpp.addressing.Entity;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * back-end stuff for JCR, used by the semantic specific adapters
+ * @author The Apache MINA Project (dev@mina.apache.org)
+ */
+public class JcrStorage {
+
+    final Logger logger = LoggerFactory.getLogger(JcrStorage.class);
+
+    protected static JcrStorage jcrStorageSingleton;
+
+    protected JcrStorage() {
+        super();
+        // protected
+    }
+
+    public static JcrStorage getInstance() {
+        synchronized (JcrStorage.class) {
+            if (jcrStorageSingleton == null)
+                jcrStorageSingleton = new JcrStorage();
+            return jcrStorageSingleton;
+        }
+    }
+
+    protected Session session = null;
+
+    public Session getRepositorySession() throws JcrStorageException {
+        if (session != null)
+            return session;
+        try {
+            Repository repository = new TransientRepository();
+            session = repository.login(new SimpleCredentials("xmpp-admin", "adminpassword".toCharArray()));
+            return session;
+        } catch (Exception e) {
+            throw new JcrStorageException(e);
+        }
+    }
+
+    public Node getRootNode() throws JcrStorageException {
+        try {
+            return getRepositorySession().getRootNode();
+        } catch (RepositoryException e) {
+            throw new JcrStorageException(e);
+        }
+    }
+
+    public Node getEntityNode(Entity bareEntity, String namespace, boolean createIfMissing) throws JcrStorageException {
+        bareEntity = bareEntity.getBareJID(); // make it really sure
+        if (namespace != null)
+            namespace = namespace.replace(':', '_');
+        final String path = "/accountentity/" + bareEntity.getFullQualifiedName()
+                + (namespace != null ? "/" + namespace : "");
+        if (!itemExists(path)) {
+            if (!createIfMissing)
+                return null;
+            Node accountEntityNode = getOrCreate(getRootNode(), "accountentity");
+            Node entityNode = getOrCreate(accountEntityNode, bareEntity.getFullQualifiedName());
+            if (namespace != null)
+                entityNode = getOrCreate(entityNode, namespace);
+            return entityNode;
+        } else {
+            try {
+                return (Node) getRepositorySession().getItem(path);
+            } catch (RepositoryException e) {
+                throw new JcrStorageException(e);
+            }
+        }
+    }
+
+    private boolean itemExists(String absolutePath) throws JcrStorageException {
+        try {
+            return getRepositorySession().itemExists(absolutePath);
+        } catch (RepositoryException e) {
+            throw new JcrStorageException(e);
+        } catch (JcrStorageException e) {
+            throw e;
+        }
+    }
+
+    protected Node getOrCreate(Node parent, String nodeName) throws JcrStorageException {
+        Node childNode;
+        try {
+            childNode = parent.getNode(nodeName);
+        } catch (RepositoryException e) {
+            childNode = null;
+        }
+        if (childNode == null) {
+            try {
+                childNode = parent.addNode(nodeName);
+                parent.save();
+                childNode.save();
+                logger.info("JCR node created: " + childNode);
+            } catch (RepositoryException e) {
+                throw new JcrStorageException(e);
+            }
+        }
+        return childNode;
+    }
+}

http://git-wip-us.apache.org/repos/asf/mina-vysper/blob/46f1a8ef/server/storage/jcr/src/main/java/org/apache/vysper/storage/jcr/JcrStorageException.java
----------------------------------------------------------------------
diff --git a/server/storage/jcr/src/main/java/org/apache/vysper/storage/jcr/JcrStorageException.java b/server/storage/jcr/src/main/java/org/apache/vysper/storage/jcr/JcrStorageException.java
new file mode 100644
index 0000000..d4747c5
--- /dev/null
+++ b/server/storage/jcr/src/main/java/org/apache/vysper/storage/jcr/JcrStorageException.java
@@ -0,0 +1,41 @@
+/*
+ *  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.storage.jcr;
+
+/**
+ * @author The Apache MINA Project (dev@mina.apache.org)
+ */
+public class JcrStorageException extends Exception {
+    public JcrStorageException() {
+        super();
+    }
+
+    public JcrStorageException(String message) {
+        super(message);
+    }
+
+    public JcrStorageException(String message, Throwable cause) {
+        super(message, cause);
+    }
+
+    public JcrStorageException(Throwable cause) {
+        super(cause);
+    }
+}

http://git-wip-us.apache.org/repos/asf/mina-vysper/blob/46f1a8ef/server/storage/jcr/src/main/java/org/apache/vysper/storage/jcr/JcrStorageProviderRegistry.java
----------------------------------------------------------------------
diff --git a/server/storage/jcr/src/main/java/org/apache/vysper/storage/jcr/JcrStorageProviderRegistry.java b/server/storage/jcr/src/main/java/org/apache/vysper/storage/jcr/JcrStorageProviderRegistry.java
new file mode 100644
index 0000000..d4393d7
--- /dev/null
+++ b/server/storage/jcr/src/main/java/org/apache/vysper/storage/jcr/JcrStorageProviderRegistry.java
@@ -0,0 +1,41 @@
+/*
+ *  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.storage.jcr;
+
+import org.apache.vysper.storage.OpenStorageProviderRegistry;
+import org.apache.vysper.storage.jcr.privatedata.JcrPrivateDataPersistenceManager;
+import org.apache.vysper.storage.jcr.roster.JcrRosterManager;
+import org.apache.vysper.storage.jcr.user.JcrUserManagement;
+import org.apache.vysper.storage.jcr.vcardtemp.JcrVcardTempPersistenceManager;
+
+/**
+ *
+ * @author The Apache MINA Project (dev@mina.apache.org)
+ */
+public class JcrStorageProviderRegistry extends OpenStorageProviderRegistry {
+
+    public JcrStorageProviderRegistry() {
+        add(new JcrUserManagement(JcrStorage.getInstance()));
+        add(new JcrRosterManager(JcrStorage.getInstance()));
+        add(new JcrVcardTempPersistenceManager(JcrStorage.getInstance()));
+        add(new JcrPrivateDataPersistenceManager(JcrStorage.getInstance()));
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/mina-vysper/blob/46f1a8ef/server/storage/jcr/src/main/java/org/apache/vysper/storage/jcr/privatedata/JcrPrivateDataPersistenceManager.java
----------------------------------------------------------------------
diff --git a/server/storage/jcr/src/main/java/org/apache/vysper/storage/jcr/privatedata/JcrPrivateDataPersistenceManager.java b/server/storage/jcr/src/main/java/org/apache/vysper/storage/jcr/privatedata/JcrPrivateDataPersistenceManager.java
new file mode 100644
index 0000000..6a7544d
--- /dev/null
+++ b/server/storage/jcr/src/main/java/org/apache/vysper/storage/jcr/privatedata/JcrPrivateDataPersistenceManager.java
@@ -0,0 +1,91 @@
+/*
+ *  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.storage.jcr.privatedata;
+
+import javax.jcr.Node;
+import javax.jcr.RepositoryException;
+import javax.jcr.Session;
+
+import org.apache.vysper.storage.jcr.JcrStorage;
+import org.apache.vysper.storage.jcr.JcrStorageException;
+import org.apache.vysper.xmpp.addressing.Entity;
+import org.apache.vysper.xmpp.modules.extension.xep0049_privatedata.PrivateDataPersistenceManager;
+import org.apache.vysper.xmpp.protocol.NamespaceURIs;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * @author The Apache MINA Project (dev@mina.apache.org)
+ */
+public class JcrPrivateDataPersistenceManager implements PrivateDataPersistenceManager {
+
+    final Logger logger = LoggerFactory.getLogger(JcrPrivateDataPersistenceManager.class);
+
+    protected JcrStorage jcrStorage;
+
+    public JcrPrivateDataPersistenceManager(JcrStorage jcrStorage) {
+        this.jcrStorage = jcrStorage;
+    }
+
+    public boolean isAvailable() {
+        Session session = null;
+        try {
+            session = jcrStorage.getRepositorySession();
+            return session != null;
+        } catch (JcrStorageException e) {
+            return false;
+        }
+    }
+
+    public String getPrivateData(Entity entity, String key) {
+        Node entityNode = getEntityNodeSave(entity, false);
+        if (entityNode == null)
+            return null;
+        try {
+            return entityNode.getProperty(key).getString();
+        } catch (RepositoryException e) {
+            return null;
+        }
+    }
+
+    public boolean setPrivateData(Entity entity, String key, String xml) {
+        Node entityNode = getEntityNodeSave(entity, true);
+        try {
+            entityNode.setProperty(key, xml);
+            entityNode.save();
+            logger.info("JCR node created: " + entityNode);
+            return true;
+        } catch (RepositoryException e) {
+            return false;
+        }
+    }
+
+    private Node getEntityNodeSave(Entity entity, boolean createIfMissing) {
+        Node entityNode;
+        try {
+            entityNode = jcrStorage.getEntityNode(entity.getBareJID(), NamespaceURIs.PRIVATE_DATA, createIfMissing);
+        } catch (JcrStorageException e) {
+            return null;
+        }
+        if (entityNode == null)
+            return null;
+        return entityNode;
+    }
+}

http://git-wip-us.apache.org/repos/asf/mina-vysper/blob/46f1a8ef/server/storage/jcr/src/main/java/org/apache/vysper/storage/jcr/roster/JcrRosterManager.java
----------------------------------------------------------------------
diff --git a/server/storage/jcr/src/main/java/org/apache/vysper/storage/jcr/roster/JcrRosterManager.java b/server/storage/jcr/src/main/java/org/apache/vysper/storage/jcr/roster/JcrRosterManager.java
new file mode 100644
index 0000000..dbb92d7
--- /dev/null
+++ b/server/storage/jcr/src/main/java/org/apache/vysper/storage/jcr/roster/JcrRosterManager.java
@@ -0,0 +1,257 @@
+/*
+ *  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.storage.jcr.roster;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.jcr.Node;
+import javax.jcr.NodeIterator;
+import javax.jcr.Property;
+import javax.jcr.RepositoryException;
+
+import org.apache.vysper.storage.jcr.JcrStorage;
+import org.apache.vysper.storage.jcr.JcrStorageException;
+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.modules.roster.AskSubscriptionType;
+import org.apache.vysper.xmpp.modules.roster.MutableRoster;
+import org.apache.vysper.xmpp.modules.roster.Roster;
+import org.apache.vysper.xmpp.modules.roster.RosterException;
+import org.apache.vysper.xmpp.modules.roster.RosterGroup;
+import org.apache.vysper.xmpp.modules.roster.RosterItem;
+import org.apache.vysper.xmpp.modules.roster.SubscriptionType;
+import org.apache.vysper.xmpp.modules.roster.persistence.AbstractRosterManager;
+import org.apache.vysper.xmpp.protocol.NamespaceURIs;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * roster items are stored for contacts in the following path:
+ * /accountentity/user@vysper.org/jabber_iq_roster/contact@vysper.org
+ * all item properties besides contact jid (which is used as a node name)
+ * are stored as node properties
+ *
+ * @author The Apache MINA Project (dev@mina.apache.org)
+ */
+public class JcrRosterManager extends AbstractRosterManager {
+
+    final Logger logger = LoggerFactory.getLogger(JcrRosterManager.class);
+
+    protected JcrStorage jcrStorage;
+
+    public JcrRosterManager(JcrStorage jcrStorage) {
+        this.jcrStorage = jcrStorage;
+    }
+
+    /*package*/static Node retrieveRosterNode(JcrStorage jcrStorage, Entity bareJid) {
+        try {
+            if (jcrStorage.getEntityNode(bareJid, null, false) == null)
+                return null;
+            return jcrStorage.getEntityNode(bareJid, NamespaceURIs.JABBER_IQ_ROSTER, true);
+        } catch (JcrStorageException e) {
+            return null;
+        }
+    }
+
+    @Override
+    protected Roster retrieveRosterInternal(Entity bareJid) {
+        final Node rosterNode = retrieveRosterNode(jcrStorage, bareJid);
+
+        MutableRoster roster = new MutableRoster();
+
+        NodeIterator nodes = null;
+        try {
+            nodes = rosterNode.getNodes();
+        } catch (RepositoryException e) {
+            return roster; // empty roster object
+        }
+        while (nodes != null && nodes.hasNext()) {
+            Node node = nodes.nextNode();
+
+            String contactJidString = null;
+            try {
+                contactJidString = node.getName();
+            } catch (RepositoryException e) {
+                logger.warn("when loading roster for user {} cannot read node name for node id = " + node.toString());
+            }
+            logger.warn("try now loading contact " + contactJidString + " from node " + node.toString());
+            EntityImpl contactJid = null;
+            if (contactJidString != null) {
+                try {
+                    contactJid = EntityImpl.parse(contactJidString);
+                } catch (EntityFormatException e) {
+                    logger.warn("when loading roster for user {} parsing  contact jid {}", bareJid, contactJidString);
+                }
+            }
+            if (contactJid == null) {
+                logger.warn("when loading roster for user {}, skipping a contact due to missing or unparsable jid",
+                        bareJid);
+                continue;
+            }
+
+            String name = readAttribute(node, "name");
+            String typeString = readAttribute(node, "type");
+            SubscriptionType subscriptionType = null;
+            try {
+                subscriptionType = SubscriptionType.valueOf(typeString == null ? "NONE" : typeString.toUpperCase());
+            } catch (IllegalArgumentException e) {
+                logger.warn("when loading roster for user " + bareJid + ", contact " + contactJid
+                        + " misses a subscription type", bareJid, contactJid);
+            }
+            String askTypeString = readAttribute(node, "askType");
+            AskSubscriptionType askSubscriptionType = AskSubscriptionType.NOT_SET;
+            try {
+                if (askTypeString != null)
+                    askSubscriptionType = AskSubscriptionType.valueOf(askTypeString);
+            } catch (IllegalArgumentException e) {
+                logger.warn("when loading roster for user " + bareJid.getFullQualifiedName() + ", contact "
+                        + contactJid.getFullQualifiedName() + ", the ask subscription type is unparsable. skipping!");
+                continue; // don't return it, don't set a default!
+            }
+
+            List<RosterGroup> groups = new ArrayList<RosterGroup>();
+            // TODO read groups
+
+            RosterItem item = new RosterItem(contactJid, name, subscriptionType, askSubscriptionType, groups);
+            logger.info("item loaded for " + bareJid.getFullQualifiedName() + ": " + item.toString());
+            roster.addItem(item);
+        }
+        return roster;
+    }
+
+    private String readAttribute(Node node, String propertyName) {
+        try {
+            Property property = node.getProperty(propertyName);
+            if (property == null)
+                return null;
+            return property.getString();
+        } catch (RepositoryException e) {
+            return null;
+        }
+    }
+
+    @Override
+    protected Roster addNewRosterInternal(Entity jid) {
+        return new MutableRoster();
+    }
+
+    @Override
+    public void addContact(Entity jid, RosterItem rosterItem) throws RosterException {
+        if (jid == null)
+            throw new RosterException("jid not provided");
+        if (rosterItem.getJid() == null)
+            throw new RosterException("contact jid not provided");
+
+        // TODO think about concurrent updates
+
+        Entity contactJid = rosterItem.getJid().getBareJID();
+        Node contactNode = getOrCreateContactNode(jid, contactJid);
+        try {
+            setOrRemoveAttribute(contactNode, "name", rosterItem.getName());
+            String subscriptionTypeValue = rosterItem.getSubscriptionType() == null ? null : rosterItem
+                    .getSubscriptionType().value();
+            setOrRemoveAttribute(contactNode, "type", subscriptionTypeValue);
+            String askSubscriptionTypeValue = null;
+            if (rosterItem.getAskSubscriptionType() != null
+                    && rosterItem.getAskSubscriptionType() != AskSubscriptionType.NOT_SET) {
+                askSubscriptionTypeValue = rosterItem.getAskSubscriptionType().value();
+            }
+            setOrRemoveAttribute(contactNode, "askType", askSubscriptionTypeValue);
+            contactNode.save();
+            logger.info("JCR node created/updated: " + contactNode);
+        } catch (RepositoryException e) {
+            throw new RosterException("failed to add contact node to roster for user = " + jid.getFullQualifiedName()
+                    + " and contact jid = " + rosterItem.getJid().getFullQualifiedName(), e);
+        }
+    }
+
+    private void setOrRemoveAttribute(Node contactNode, String attributeName, String attributeValue)
+            throws RepositoryException {
+        if (attributeValue != null)
+            contactNode.setProperty(attributeName, attributeValue);
+        else if (contactNode.hasProperty(attributeName))
+            contactNode.setProperty(attributeName, (String) null);
+    }
+
+    private Node getOrCreateContactNode(Entity jid, Entity contactJid) throws RosterException {
+        Node entityNode = null;
+        try {
+            entityNode = jcrStorage.getEntityNode(jid, NamespaceURIs.JABBER_IQ_ROSTER, true);
+        } catch (JcrStorageException e) {
+            throw new RosterException("failed to create roster store for " + jid.getFullQualifiedName(), e);
+        }
+        Node contactNode = null;
+        try {
+            contactNode = entityNode.getNode(contactJid.getFullQualifiedName());
+        } catch (RepositoryException e) {
+            // not exists, create
+            try {
+                contactNode = entityNode.addNode(contactJid.getFullQualifiedName());
+                entityNode.save();
+            } catch (RepositoryException addNodeEx) {
+                throw new RosterException("failed to add contact node to roster for user = "
+                        + jid.getFullQualifiedName() + " and contact jid = " + contactJid.getFullQualifiedName(),
+                        addNodeEx);
+            }
+
+        }
+        return contactNode;
+    }
+
+    @Override
+    public void removeContact(Entity jidUser, Entity jidContact) throws RosterException {
+        if (jidUser == null)
+            throw new RosterException("jid not provided");
+        if (jidContact == null)
+            throw new RosterException("contact jid not provided");
+        Node rosterNode = null;
+        try {
+            rosterNode = jcrStorage.getEntityNode(jidUser, NamespaceURIs.JABBER_IQ_ROSTER, false);
+        } catch (JcrStorageException e) {
+            throw new RosterException("failed to retrieve roster store for " + jidUser.getFullQualifiedName(), e);
+        }
+        if (rosterNode == null)
+            return; // done, no contacts anyway. oops
+
+        NodeIterator nodes = null;
+        try {
+            nodes = rosterNode.getNodes("contact");
+        } catch (RepositoryException e) {
+            return; // failed to find any contacts, done.
+        }
+        boolean foundOne = false;
+        while (nodes != null && nodes.hasNext()) {
+            Node node = nodes.nextNode();
+            String contactJidString = readAttribute(node, "jid");
+            if (contactJidString != null && contactJidString.equals(jidContact.getFullQualifiedName())) {
+                foundOne = true;
+                try {
+                    node.remove();
+                } catch (RepositoryException e) {
+                    logger.warn("failed to remove from roster for user {} the contact jid " + jidContact, jidUser, e);
+                }
+            }
+        }
+        if (!foundOne)
+            logger.warn("failed to remove from roster for user " + jidUser + " the contact jid " + jidContact);
+    }
+}

http://git-wip-us.apache.org/repos/asf/mina-vysper/blob/46f1a8ef/server/storage/jcr/src/main/java/org/apache/vysper/storage/jcr/user/JcrUserManagement.java
----------------------------------------------------------------------
diff --git a/server/storage/jcr/src/main/java/org/apache/vysper/storage/jcr/user/JcrUserManagement.java b/server/storage/jcr/src/main/java/org/apache/vysper/storage/jcr/user/JcrUserManagement.java
new file mode 100644
index 0000000..0f5da9f
--- /dev/null
+++ b/server/storage/jcr/src/main/java/org/apache/vysper/storage/jcr/user/JcrUserManagement.java
@@ -0,0 +1,118 @@
+/*
+ *  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.storage.jcr.user;
+
+import javax.jcr.Node;
+import javax.jcr.Property;
+
+import org.apache.vysper.storage.jcr.JcrStorage;
+import org.apache.vysper.storage.jcr.JcrStorageException;
+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.authentication.AccountCreationException;
+import org.apache.vysper.xmpp.authentication.AccountManagement;
+import org.apache.vysper.xmpp.authentication.UserAuthentication;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ *
+ * @author The Apache MINA Project (dev@mina.apache.org)
+ */
+public class JcrUserManagement implements UserAuthentication, AccountManagement {
+
+    final Logger logger = LoggerFactory.getLogger(JcrUserManagement.class);
+
+    protected JcrStorage jcrStorage;
+
+    private static final String CREDENTIALS_NAMESPACE = "vysper_internal_credentials";
+
+    public JcrUserManagement(JcrStorage jcrStorage) {
+        this.jcrStorage = jcrStorage;
+    }
+
+    public boolean verifyCredentials(Entity jid, String passwordCleartext, Object credentials) {
+        if (passwordCleartext == null)
+            return false;
+        try {
+            final Node credentialsNode = jcrStorage.getEntityNode(jid, CREDENTIALS_NAMESPACE, false);
+            if (credentialsNode == null)
+                return false;
+            final Property property = credentialsNode.getProperty("password");
+            if (property == null)
+                return false;
+            final String password = property.getValue().getString();
+            return passwordCleartext.equals(password);
+        } catch (Exception e) {
+            return false;
+        }
+    }
+
+    public boolean verifyCredentials(String username, String passwordCleartext, Object credentials) {
+        try {
+            return verifyCredentials(EntityImpl.parse(username), passwordCleartext, credentials);
+        } catch (EntityFormatException e) {
+            return false;
+        }
+    }
+
+    public boolean verifyAccountExists(Entity jid) {
+        try {
+            return jcrStorage.getEntityNode(jid, CREDENTIALS_NAMESPACE, false) != null;
+        } catch (JcrStorageException e) {
+            return false;
+        }
+    }
+
+    public void addUser(Entity username, String password) throws AccountCreationException {
+        // if already existent, don't create, throw error
+        try {
+            if (jcrStorage.getEntityNode(username, CREDENTIALS_NAMESPACE, false) != null) {
+                throw new AccountCreationException("account already exists: " + username.getFullQualifiedName());
+            }
+        } catch (JcrStorageException e) {
+            throw new AccountCreationException("account exists check failed for " + username.getFullQualifiedName(), e);
+        }
+        // now, finally, create
+        try {
+            final Node credentialsNode = jcrStorage.getEntityNode(username, CREDENTIALS_NAMESPACE, true);
+            credentialsNode.setProperty("password", password);
+            credentialsNode.save();
+            logger.info("JCR node created: " + credentialsNode);
+        } catch (Exception e) {
+            // TODO remove account?
+            throw new AccountCreationException("failed to create the account set credentials", e);
+        }
+
+    }
+
+    public void changePassword(Entity username, String password) throws AccountCreationException {
+        try {
+            final Node credentialsNode = jcrStorage.getEntityNode(username, CREDENTIALS_NAMESPACE, false);
+            credentialsNode.setProperty("password", password);
+            credentialsNode.save();
+            logger.info("JCR password changed: " + credentialsNode);
+        } catch (Exception e) {
+            // TODO remove account?
+            throw new AccountCreationException("failed to create the account set credentials", e);
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/mina-vysper/blob/46f1a8ef/server/storage/jcr/src/main/java/org/apache/vysper/storage/jcr/vcardtemp/JcrVcardTempPersistenceManager.java
----------------------------------------------------------------------
diff --git a/server/storage/jcr/src/main/java/org/apache/vysper/storage/jcr/vcardtemp/JcrVcardTempPersistenceManager.java b/server/storage/jcr/src/main/java/org/apache/vysper/storage/jcr/vcardtemp/JcrVcardTempPersistenceManager.java
new file mode 100644
index 0000000..293bad5
--- /dev/null
+++ b/server/storage/jcr/src/main/java/org/apache/vysper/storage/jcr/vcardtemp/JcrVcardTempPersistenceManager.java
@@ -0,0 +1,92 @@
+/*
+ *  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.storage.jcr.vcardtemp;
+
+import javax.jcr.Node;
+import javax.jcr.RepositoryException;
+import javax.jcr.Session;
+
+import org.apache.vysper.storage.jcr.JcrStorage;
+import org.apache.vysper.storage.jcr.JcrStorageException;
+import org.apache.vysper.xmpp.addressing.Entity;
+import org.apache.vysper.xmpp.modules.extension.xep0054_vcardtemp.VcardTempPersistenceManager;
+import org.apache.vysper.xmpp.protocol.NamespaceURIs;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ *
+ * @author The Apache MINA Project (dev@mina.apache.org)
+ */
+public class JcrVcardTempPersistenceManager implements VcardTempPersistenceManager {
+
+    final Logger logger = LoggerFactory.getLogger(JcrVcardTempPersistenceManager.class);
+
+    protected JcrStorage jcrStorage;
+
+    public JcrVcardTempPersistenceManager(JcrStorage jcrStorage) {
+        this.jcrStorage = jcrStorage;
+    }
+
+    public boolean isAvailable() {
+        Session session = null;
+        try {
+            session = jcrStorage.getRepositorySession();
+            return session != null;
+        } catch (JcrStorageException e) {
+            return false;
+        }
+    }
+
+    public String getVcard(Entity entity) {
+        Node entityNode = getEntityNodeSave(entity, false);
+        if (entityNode == null)
+            return null;
+        try {
+            return entityNode.getProperty("content").getString();
+        } catch (RepositoryException e) {
+            return null;
+        }
+    }
+
+    private Node getEntityNodeSave(Entity entity, boolean createIfMissing) {
+        Node entityNode;
+        try {
+            entityNode = jcrStorage.getEntityNode(entity.getBareJID(), NamespaceURIs.VCARD_TEMP, createIfMissing);
+        } catch (JcrStorageException e) {
+            return null;
+        }
+        if (entityNode == null)
+            return null;
+        return entityNode;
+    }
+
+    public boolean setVcard(Entity entity, String xml) {
+        Node entityNode = getEntityNodeSave(entity, true);
+        try {
+            entityNode.setProperty("content", xml);
+            entityNode.save();
+            logger.info("JCR node created: " + entityNode);
+            return true;
+        } catch (RepositoryException e) {
+            return false;
+        }
+    }
+}