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 2009/06/13 19:20:45 UTC
svn commit: r784437 - in
/mina/sandbox/vysper/trunk/src/main/java/org/apache/vysper: storage/jcr/
storage/jcr/privatedata/ xmpp/modules/extension/xep0049_privatedata/
xmpp/protocol/
Author: berndf
Date: Sat Jun 13 17:20:45 2009
New Revision: 784437
URL: http://svn.apache.org/viewvc?rev=784437&view=rev
Log:
[vysper] patch contributed by David Phillips. Many thanks.
(VYSPER-72) Implement XEP-0049 Private XML Storage
Added:
mina/sandbox/vysper/trunk/src/main/java/org/apache/vysper/storage/jcr/privatedata/
mina/sandbox/vysper/trunk/src/main/java/org/apache/vysper/storage/jcr/privatedata/JcrPrivateDataPersistenceManager.java
mina/sandbox/vysper/trunk/src/main/java/org/apache/vysper/xmpp/modules/extension/xep0049_privatedata/
mina/sandbox/vysper/trunk/src/main/java/org/apache/vysper/xmpp/modules/extension/xep0049_privatedata/PrivateDataIQHandler.java
mina/sandbox/vysper/trunk/src/main/java/org/apache/vysper/xmpp/modules/extension/xep0049_privatedata/PrivateDataModule.java
mina/sandbox/vysper/trunk/src/main/java/org/apache/vysper/xmpp/modules/extension/xep0049_privatedata/PrivateDataPersistenceManager.java
Modified:
mina/sandbox/vysper/trunk/src/main/java/org/apache/vysper/storage/jcr/JcrStorageProviderRegistry.java
mina/sandbox/vysper/trunk/src/main/java/org/apache/vysper/xmpp/protocol/NamespaceURIs.java
Modified: mina/sandbox/vysper/trunk/src/main/java/org/apache/vysper/storage/jcr/JcrStorageProviderRegistry.java
URL: http://svn.apache.org/viewvc/mina/sandbox/vysper/trunk/src/main/java/org/apache/vysper/storage/jcr/JcrStorageProviderRegistry.java?rev=784437&r1=784436&r2=784437&view=diff
==============================================================================
--- mina/sandbox/vysper/trunk/src/main/java/org/apache/vysper/storage/jcr/JcrStorageProviderRegistry.java (original)
+++ mina/sandbox/vysper/trunk/src/main/java/org/apache/vysper/storage/jcr/JcrStorageProviderRegistry.java Sat Jun 13 17:20:45 2009
@@ -20,6 +20,7 @@
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;
@@ -34,6 +35,7 @@
add(new JcrUserManagement(JcrStorage.getInstance()));
add(new JcrRosterManager(JcrStorage.getInstance()));
add(new JcrVcardTempPersistenceManager(JcrStorage.getInstance()));
+ add(new JcrPrivateDataPersistenceManager(JcrStorage.getInstance()));
}
}
Added: mina/sandbox/vysper/trunk/src/main/java/org/apache/vysper/storage/jcr/privatedata/JcrPrivateDataPersistenceManager.java
URL: http://svn.apache.org/viewvc/mina/sandbox/vysper/trunk/src/main/java/org/apache/vysper/storage/jcr/privatedata/JcrPrivateDataPersistenceManager.java?rev=784437&view=auto
==============================================================================
--- mina/sandbox/vysper/trunk/src/main/java/org/apache/vysper/storage/jcr/privatedata/JcrPrivateDataPersistenceManager.java (added)
+++ mina/sandbox/vysper/trunk/src/main/java/org/apache/vysper/storage/jcr/privatedata/JcrPrivateDataPersistenceManager.java Sat Jun 13 17:20:45 2009
@@ -0,0 +1,93 @@
+/*
+ * 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;
+ }
+}
Added: mina/sandbox/vysper/trunk/src/main/java/org/apache/vysper/xmpp/modules/extension/xep0049_privatedata/PrivateDataIQHandler.java
URL: http://svn.apache.org/viewvc/mina/sandbox/vysper/trunk/src/main/java/org/apache/vysper/xmpp/modules/extension/xep0049_privatedata/PrivateDataIQHandler.java?rev=784437&view=auto
==============================================================================
--- mina/sandbox/vysper/trunk/src/main/java/org/apache/vysper/xmpp/modules/extension/xep0049_privatedata/PrivateDataIQHandler.java (added)
+++ mina/sandbox/vysper/trunk/src/main/java/org/apache/vysper/xmpp/modules/extension/xep0049_privatedata/PrivateDataIQHandler.java Sat Jun 13 17:20:45 2009
@@ -0,0 +1,166 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.vysper.xmpp.modules.extension.xep0049_privatedata;
+
+import org.apache.vysper.compliance.SpecCompliant;
+import org.apache.vysper.xmpp.addressing.Entity;
+import org.apache.vysper.xmpp.modules.core.base.handler.DefaultIQHandler;
+import org.apache.vysper.xmpp.protocol.NamespaceURIs;
+import org.apache.vysper.xmpp.protocol.StreamErrorCondition;
+import org.apache.vysper.xmpp.server.ServerRuntimeContext;
+import org.apache.vysper.xmpp.server.SessionContext;
+import org.apache.vysper.xmpp.server.response.ServerErrorResponses;
+import org.apache.vysper.xmpp.stanza.IQStanza;
+import org.apache.vysper.xmpp.stanza.IQStanzaType;
+import org.apache.vysper.xmpp.stanza.Stanza;
+import org.apache.vysper.xmpp.stanza.StanzaBuilder;
+import org.apache.vysper.xmpp.stanza.StanzaErrorCondition;
+import org.apache.vysper.xmpp.stanza.StanzaErrorType;
+import org.apache.vysper.xmpp.xmlfragment.Attribute;
+import org.apache.vysper.xmpp.xmlfragment.Renderer;
+import org.apache.vysper.xmpp.xmlfragment.XMLElement;
+
+/**
+ * @author The Apache MINA Project (dev@mina.apache.org)
+ */
+@SpecCompliant(spec = "xep-0049", status = SpecCompliant.ComplianceStatus.FINISHED, coverage = SpecCompliant.ComplianceCoverage.COMPLETE)
+public class PrivateDataIQHandler extends DefaultIQHandler {
+
+ protected PrivateDataPersistenceManager persistenceManager;
+
+ public void setPersistenceManager(PrivateDataPersistenceManager persistenceManager) {
+ this.persistenceManager = persistenceManager;
+ }
+
+ @Override
+ protected boolean verifyNamespace(Stanza stanza) {
+ return verifyInnerNamespace(stanza, NamespaceURIs.PRIVATE_DATA);
+ }
+
+ @Override
+ protected boolean verifyInnerElement(Stanza stanza) {
+ return verifyInnerElementWorker(stanza, "query");
+ }
+
+ @Override
+ protected Stanza handleSet(IQStanza stanza, ServerRuntimeContext serverRuntimeContext, SessionContext sessionContext) {
+ // Get From
+ Entity to = stanza.getTo();
+ Entity from = stanza.getFrom();
+ if (from == null) {
+ from = sessionContext.getInitiatingEntity();
+ }
+
+ // Not null, and not addressed to itself
+ if (to != null && !to.getBareJID().equals(sessionContext.getInitiatingEntity().getBareJID())) {
+ return ServerErrorResponses.getInstance().getStreamError(StreamErrorCondition.BAD_FORMAT, null, "Private data only modifiable by the owner", null);
+ }
+
+ XMLElement queryElement = stanza.getFirstInnerElement();
+
+ // Example 4: http://xmpp.org/extensions/xep-0049.html
+ // Query element must have a child element with a non-null namespace
+ if (queryElement.getInnerElements().size() != 1) {
+ return ServerErrorResponses.getInstance().getStanzaError(StanzaErrorCondition.NOT_ACCEPTABLE, stanza, StanzaErrorType.MODIFY, "query's child element is missing", null, null);
+ }
+ XMLElement x = queryElement.getFirstInnerElement();
+ String ns = x.getAttribute("xmlns").getValue();
+ if (ns == null) {
+ return ServerErrorResponses.getInstance().getStanzaError(StanzaErrorCondition.NOT_ACCEPTABLE, stanza, StanzaErrorType.MODIFY, "no namespace", null, null);
+ }
+
+ // No persistancy Manager
+ if (persistenceManager == null) {
+ return ServerErrorResponses.getInstance().getStanzaError(StanzaErrorCondition.INTERNAL_SERVER_ERROR, stanza, StanzaErrorType.WAIT, "internal storage inaccessible", null, null);
+ }
+
+ String queryKey = getKey(x);
+ String queryContent = new Renderer(queryElement).getComplete();
+ boolean success = persistenceManager.setPrivateData(from, queryKey, queryContent);
+
+ if (success) {
+ return StanzaBuilder.createIQStanza(null, from, IQStanzaType.RESULT, stanza.getID()).getFinalStanza();
+ } else {
+ return StanzaBuilder.createIQStanza(null, from, IQStanzaType.ERROR, stanza.getID()).getFinalStanza();
+ }
+ }
+
+ @Override
+ protected Stanza handleGet(IQStanza stanza, ServerRuntimeContext serverRuntimeContext, SessionContext sessionContext) {
+ Entity to = stanza.getTo();
+ Entity from = stanza.getFrom();
+ if (from == null) {
+ from = sessionContext.getInitiatingEntity();
+ }
+
+ // Not null, and not addressed to itself
+ if (to != null && !to.getBareJID().equals(sessionContext.getInitiatingEntity().getBareJID())) {
+ return ServerErrorResponses.getInstance().getStreamError(StreamErrorCondition.BAD_FORMAT, null, "can only view your data", null);
+ }
+
+ XMLElement queryElement = stanza.getFirstInnerElement();
+ XMLElement x = queryElement.getFirstInnerElement();
+ if (x == null) {
+ return ServerErrorResponses.getInstance().getStanzaError(StanzaErrorCondition.NOT_ACCEPTABLE, stanza, StanzaErrorType.MODIFY, "query's child element missing", null, null);
+ }
+
+ // No persistancy Manager
+ if (persistenceManager == null) {
+ return ServerErrorResponses.getInstance().getStanzaError(StanzaErrorCondition.INTERNAL_SERVER_ERROR, stanza, StanzaErrorType.WAIT, "internal storage inaccessible", null, null);
+ }
+
+ String queryKey = getKey(x);
+ String privateDataXML = persistenceManager.getPrivateData(from, queryKey);
+
+ StanzaBuilder stanzaBuilder = StanzaBuilder.createIQStanza(stanza.getTo(), stanza.getFrom(), IQStanzaType.RESULT, stanza.getID());
+ if (privateDataXML == null) {
+ stanzaBuilder.startInnerElement(x.getName());
+ for (Attribute a : x.getAttributes()) {
+ stanzaBuilder.addAttribute(a);
+ }
+ stanzaBuilder.endInnerElement();
+ } else {
+ stanzaBuilder.addText(privateDataXML);
+ }
+ return stanzaBuilder.getFinalStanza();
+ }
+
+ /**
+ * Create a property name that is unique for this query. eg this XMLElement:
+ * <storage xmlns="storage:bookmarks"> is converted into this string:
+ * storage-storage-bookmarks
+ */
+ private String getKey(XMLElement x) {
+ StringBuilder queryKey = new StringBuilder();
+ queryKey.append(x.getName());
+ queryKey.append("-");
+ queryKey.append(x.getAttribute("xmlns").getValue());
+
+ // Some characters are not valid for property names
+ for (int i = 0; i < queryKey.length(); i++) {
+ char c = queryKey.charAt(i);
+ if (c == ' ' || c == ':') {
+ queryKey.setCharAt(i, '-');
+ }
+ }
+ return queryKey.toString();
+ }
+
+}
Added: mina/sandbox/vysper/trunk/src/main/java/org/apache/vysper/xmpp/modules/extension/xep0049_privatedata/PrivateDataModule.java
URL: http://svn.apache.org/viewvc/mina/sandbox/vysper/trunk/src/main/java/org/apache/vysper/xmpp/modules/extension/xep0049_privatedata/PrivateDataModule.java?rev=784437&view=auto
==============================================================================
--- mina/sandbox/vysper/trunk/src/main/java/org/apache/vysper/xmpp/modules/extension/xep0049_privatedata/PrivateDataModule.java (added)
+++ mina/sandbox/vysper/trunk/src/main/java/org/apache/vysper/xmpp/modules/extension/xep0049_privatedata/PrivateDataModule.java Sat Jun 13 17:20:45 2009
@@ -0,0 +1,87 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.vysper.xmpp.modules.extension.xep0049_privatedata;
+
+import org.apache.vysper.xmpp.modules.DefaultDiscoAwareModule;
+import org.apache.vysper.xmpp.modules.servicediscovery.management.Feature;
+import org.apache.vysper.xmpp.modules.servicediscovery.management.InfoElement;
+import org.apache.vysper.xmpp.modules.servicediscovery.management.InfoRequest;
+import org.apache.vysper.xmpp.modules.servicediscovery.management.ServerInfoRequestListener;
+import org.apache.vysper.xmpp.protocol.HandlerDictionary;
+import org.apache.vysper.xmpp.protocol.NamespaceHandlerDictionary;
+import org.apache.vysper.xmpp.protocol.NamespaceURIs;
+import org.apache.vysper.xmpp.server.ServerRuntimeContext;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ *
+ * @author The Apache MINA Project (dev@mina.apache.org)
+ */
+public class PrivateDataModule extends DefaultDiscoAwareModule implements ServerInfoRequestListener {
+
+ final Logger logger = LoggerFactory.getLogger(PrivateDataModule.class);
+
+ protected PrivateDataIQHandler iqHandler = new PrivateDataIQHandler();
+
+ @Override
+ public void initialize(ServerRuntimeContext serverRuntimeContext) {
+ super.initialize(serverRuntimeContext);
+
+ PrivateDataPersistenceManager persistenceManager = (PrivateDataPersistenceManager) serverRuntimeContext.getStorageProvider(PrivateDataPersistenceManager.class);
+ if (persistenceManager == null) {
+ logger.error("no PrivateDataPersistenceManager found");
+ } else if (!persistenceManager.isAvailable()) {
+ logger.warn("PrivateDataPersistenceManager not available");
+ } else {
+ iqHandler.setPersistenceManager(persistenceManager);
+ }
+ }
+
+ @Override
+ public String getName() {
+ return "XEP-0049 Private Data";
+ }
+
+ @Override
+ public String getVersion() {
+ return "1.2";
+ }
+
+ @Override
+ protected void addServerInfoRequestListeners(List<ServerInfoRequestListener> serverInfoRequestListeners) {
+ serverInfoRequestListeners.add(this);
+ }
+
+ public List<InfoElement> getServerInfosFor(InfoRequest request) {
+ List<InfoElement> infoElements = new ArrayList<InfoElement>();
+ infoElements.add(new Feature(NamespaceURIs.PRIVATE_DATA));
+ return infoElements;
+ }
+
+ @Override
+ protected void addHandlerDictionaries(List<HandlerDictionary> dictionary) {
+ iqHandler = new PrivateDataIQHandler();
+ dictionary.add(new NamespaceHandlerDictionary(NamespaceURIs.PRIVATE_DATA, iqHandler));
+ }
+}
Added: mina/sandbox/vysper/trunk/src/main/java/org/apache/vysper/xmpp/modules/extension/xep0049_privatedata/PrivateDataPersistenceManager.java
URL: http://svn.apache.org/viewvc/mina/sandbox/vysper/trunk/src/main/java/org/apache/vysper/xmpp/modules/extension/xep0049_privatedata/PrivateDataPersistenceManager.java?rev=784437&view=auto
==============================================================================
--- mina/sandbox/vysper/trunk/src/main/java/org/apache/vysper/xmpp/modules/extension/xep0049_privatedata/PrivateDataPersistenceManager.java (added)
+++ mina/sandbox/vysper/trunk/src/main/java/org/apache/vysper/xmpp/modules/extension/xep0049_privatedata/PrivateDataPersistenceManager.java Sat Jun 13 17:20:45 2009
@@ -0,0 +1,40 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.vysper.xmpp.modules.extension.xep0049_privatedata;
+
+import org.apache.vysper.storage.StorageProvider;
+import org.apache.vysper.xmpp.addressing.Entity;
+
+/**
+ *
+ * @author The Apache MINA Project (dev@mina.apache.org)
+ */
+public interface PrivateDataPersistenceManager extends StorageProvider {
+
+ /**
+ * @return if the persistene manager is ready to operate
+ */
+ boolean isAvailable();
+
+ String getPrivateData(Entity entity, String key);
+
+ boolean setPrivateData(Entity entity, String key, String xml);
+
+}
Modified: mina/sandbox/vysper/trunk/src/main/java/org/apache/vysper/xmpp/protocol/NamespaceURIs.java
URL: http://svn.apache.org/viewvc/mina/sandbox/vysper/trunk/src/main/java/org/apache/vysper/xmpp/protocol/NamespaceURIs.java?rev=784437&r1=784436&r2=784437&view=diff
==============================================================================
--- mina/sandbox/vysper/trunk/src/main/java/org/apache/vysper/xmpp/protocol/NamespaceURIs.java (original)
+++ mina/sandbox/vysper/trunk/src/main/java/org/apache/vysper/xmpp/protocol/NamespaceURIs.java Sat Jun 13 17:20:45 2009
@@ -44,6 +44,7 @@
public static final String JABBER_IQ_VERSION = "jabber:iq:version";
public static final String JABBER_IQ_TIME = "jabber:iq:time";
public static final String JABBER_X_DATA = "jabber:x:data";
+ public static final String PRIVATE_DATA = "jabber:iq:private";
public static final String URN_XMPP_TIME = "urn:xmpp:time";
public static final String VCARD_TEMP = "vcard-temp";
public static final String XEP0030_SERVICE_DISCOVERY_ITEMS = "http://jabber.org/protocol/disco#items";