use of org.jivesoftware.openfire.pubsub.cluster.RefreshNodeTask in project Openfire by igniterealtime.
the class PubSubEngine method createNodeHelper.
/**
* Checks if the following conditions are satisfied and creates a node
* - Requester can create nodes
* - Instant node creation is enabled
* - Node does not already exist
* - New node configuration is valid
*
* <br>NOTE 1: This method should not reply to the client
* <br>NOTE 2: This method calls UserManager::isRegisteredUser(JID) which can block waiting for a response - so
* do not call this method in the same thread in which a response might arrive
*
* @param service The service instance that's responsible for processing (cannot be null)
* @param requester The (full) JID of the entity that performs the action (cannot be null)
* @param configuration Optional Configuration dataform, if user requested to configure the node (can be null)
* @param nodeID The ID of the node to be created, or null when an instant node is to be created.
* @param publishOptions Optional Publishing Options, which are either preconditions or configuration overrides (can be null)
* @return {@link CreateNodeResponse}
*/
public static CreateNodeResponse createNodeHelper(PubSubService service, JID requester, Element configuration, String nodeID, DataForm publishOptions) {
// Verify that sender has permissions to create nodes
if (!service.canCreateNode(requester) || (!isComponent(requester) && !UserManager.getInstance().isRegisteredUser(requester, true))) {
// The user is not allowed to create nodes so return an error
return new CreateNodeResponse(PacketError.Condition.forbidden, null, null);
}
DataForm completedForm = null;
CollectionNode parentNode = null;
String newNodeID = nodeID;
if (nodeID == null) {
// User requested an instant node
if (!service.isInstantNodeSupported()) {
// Instant nodes creation is not allowed so return an error
Element pubsubError = DocumentHelper.createElement(QName.get("nodeid-required", "http://jabber.org/protocol/pubsub#errors"));
return new CreateNodeResponse(PacketError.Condition.not_acceptable, pubsubError, null);
}
do {
// Create a new nodeID and make sure that the random generated string does not
// match an existing node. Probability to match an existing node are very very low
// but they exist :)
newNodeID = StringUtils.randomString(15);
} while (service.getNode(newNodeID) != null);
}
boolean collectionType = false;
// Check if user requested to configure the node (using a data form)
if (configuration != null) {
// Get the data form that contains the parent nodeID
completedForm = getSentConfigurationForm(configuration);
}
if (publishOptions != null) {
// Apply publish options to override provided config.
if (completedForm == null) {
completedForm = publishOptions;
} else {
for (final FormField publishOption : publishOptions.getFields()) {
completedForm.removeField(publishOption.getVariable());
final FormField formField = completedForm.addField(publishOption.getVariable(), publishOption.getLabel(), publishOption.getType());
for (final String value : publishOption.getValues()) {
formField.addValue(value);
}
}
}
}
if (completedForm != null) {
// Calculate newNodeID when new node is affiliated with a Collection
FormField field = completedForm.getField("pubsub#collection");
if (field != null) {
List<String> values = field.getValues();
if (!values.isEmpty()) {
String parentNodeID = values.get(0);
Node tempNode = service.getNode(parentNodeID);
if (tempNode == null) {
// Requested parent node was not found so return an error
return new CreateNodeResponse(PacketError.Condition.item_not_found, null, null);
} else if (!tempNode.isCollectionNode()) {
// Requested parent node is not a collection node so return an error
return new CreateNodeResponse(PacketError.Condition.not_acceptable, null, null);
}
parentNode = (CollectionNode) tempNode;
}
}
field = completedForm.getField("pubsub#node_type");
if (field != null) {
// Check if user requested to create a new collection node
List<String> values = field.getValues();
if (!values.isEmpty()) {
collectionType = "collection".equals(values.get(0));
}
}
}
// If no parent was defined then use the root collection node
if (parentNode == null && service.isCollectionNodesSupported()) {
parentNode = service.getRootCollectionNode();
}
// Check that the requested nodeID does not exist
Node existingNode = service.getNode(newNodeID);
if (existingNode != null) {
// There is a conflict since a node with the same ID already exists
return new CreateNodeResponse(PacketError.Condition.conflict, null, null);
}
if (collectionType && !service.isCollectionNodesSupported()) {
// Cannot create a collection node since the service doesn't support it
Element pubsubError = DocumentHelper.createElement(QName.get("unsupported", "http://jabber.org/protocol/pubsub#errors"));
pubsubError.addAttribute("feature", "collections");
return new CreateNodeResponse(PacketError.Condition.feature_not_implemented, pubsubError, null);
}
if (parentNode != null && !collectionType) {
// Check if requester is allowed to add a new leaf child node to the parent node
if (!parentNode.isAssociationAllowed(requester)) {
// User is not allowed to add child leaf node to parent node. Return an error.
return new CreateNodeResponse(PacketError.Condition.forbidden, null, null);
}
// Check if number of child leaf nodes has not been exceeded
if (parentNode.isMaxLeafNodeReached()) {
// Max number of child leaf nodes has been reached. Return an error.
Element pubsubError = DocumentHelper.createElement(QName.get("max-nodes-exceeded", "http://jabber.org/protocol/pubsub#errors"));
return new CreateNodeResponse(PacketError.Condition.conflict, pubsubError, null);
}
}
// Create and configure the node
boolean conflict = false;
Node newNode = null;
try {
// TODO Assumed that the owner of the subscription is the bare JID of the subscription JID. Waiting StPeter answer for explicit field.
JID owner = requester.asBareJID();
final DefaultNodeConfiguration defaultConfiguration = service.getDefaultNodeConfiguration(!collectionType);
synchronized ((newNodeID + MUTEX_SUFFIX_NODE).intern()) {
if (service.getNode(newNodeID) == null) {
// Create the node
if (collectionType) {
newNode = new CollectionNode(service.getUniqueIdentifier(), parentNode, newNodeID, requester, defaultConfiguration);
} else {
newNode = new LeafNode(service.getUniqueIdentifier(), parentNode, newNodeID, requester, defaultConfiguration);
}
// Add the creator as the node owner
newNode.addOwner(owner);
// Configure and save the node to the backend store
if (completedForm != null) {
newNode.configure(completedForm);
} else {
newNode.saveToDB();
}
// TODO Replace with a cluster task that does not interact with the database (OF-2141).
CacheFactory.doClusterTask(new RefreshNodeTask(newNode));
} else {
conflict = true;
}
}
if (conflict) {
// There is a conflict since a node with the same ID already exists
return new CreateNodeResponse(PacketError.Condition.conflict, null, null);
} else {
// Return success to the node owner
return new CreateNodeResponse(null, null, newNode);
}
} catch (NotAcceptableException e) {
// Node should have at least one owner. Return not-acceptable error.
return new CreateNodeResponse(PacketError.Condition.not_acceptable, null, null);
}
}
use of org.jivesoftware.openfire.pubsub.cluster.RefreshNodeTask in project Openfire by igniterealtime.
the class PubSubEngine method createNodeHelper.
/**
* Checks if the following conditions are satisfied and creates a node
* - Requester can create nodes
* - Instant node creation is enabled
* - Node does not already exist
* - New node configuration is valid
*
* NOTE: This method should not reply to the client
*
* @param service
* @param iq
* @param childElement
* @param createElement
* @return {@link CreateNodeResponse}
*/
private CreateNodeResponse createNodeHelper(PubSubService service, IQ iq, Element childElement, Element createElement) {
// Get sender of the IQ packet
JID from = iq.getFrom();
// Verify that sender has permissions to create nodes
if (!service.canCreateNode(from) || (!UserManager.getInstance().isRegisteredUser(from) && !isComponent(from))) {
// The user is not allowed to create nodes so return an error
return new CreateNodeResponse(PacketError.Condition.forbidden, null, null);
}
DataForm completedForm = null;
CollectionNode parentNode = null;
String nodeID = createElement.attributeValue("node");
String newNodeID = nodeID;
if (nodeID == null) {
// User requested an instant node
if (!service.isInstantNodeSupported()) {
// Instant nodes creation is not allowed so return an error
Element pubsubError = DocumentHelper.createElement(QName.get("nodeid-required", "http://jabber.org/protocol/pubsub#errors"));
return new CreateNodeResponse(PacketError.Condition.not_acceptable, pubsubError, null);
}
do {
// Create a new nodeID and make sure that the random generated string does not
// match an existing node. Probability to match an existing node are very very low
// but they exist :)
newNodeID = StringUtils.randomString(15);
} while (service.getNode(newNodeID) != null);
}
boolean collectionType = false;
// Check if user requested to configure the node (using a data form)
Element configureElement = childElement.element("configure");
if (configureElement != null) {
// Get the data form that contains the parent nodeID
completedForm = getSentConfigurationForm(configureElement);
if (completedForm != null) {
// Calculate newNodeID when new node is affiliated with a Collection
FormField field = completedForm.getField("pubsub#collection");
if (field != null) {
List<String> values = field.getValues();
if (!values.isEmpty()) {
String parentNodeID = values.get(0);
Node tempNode = service.getNode(parentNodeID);
if (tempNode == null) {
// Requested parent node was not found so return an error
return new CreateNodeResponse(PacketError.Condition.item_not_found, null, null);
} else if (!tempNode.isCollectionNode()) {
// Requested parent node is not a collection node so return an error
return new CreateNodeResponse(PacketError.Condition.not_acceptable, null, null);
}
parentNode = (CollectionNode) tempNode;
}
}
field = completedForm.getField("pubsub#node_type");
if (field != null) {
// Check if user requested to create a new collection node
List<String> values = field.getValues();
if (!values.isEmpty()) {
collectionType = "collection".equals(values.get(0));
}
}
}
}
// If no parent was defined then use the root collection node
if (parentNode == null && service.isCollectionNodesSupported()) {
parentNode = service.getRootCollectionNode();
}
// Check that the requested nodeID does not exist
Node existingNode = service.getNode(newNodeID);
if (existingNode != null) {
// There is a conflict since a node with the same ID already exists
return new CreateNodeResponse(PacketError.Condition.conflict, null, null);
}
if (collectionType && !service.isCollectionNodesSupported()) {
// Cannot create a collection node since the service doesn't support it
Element pubsubError = DocumentHelper.createElement(QName.get("unsupported", "http://jabber.org/protocol/pubsub#errors"));
pubsubError.addAttribute("feature", "collections");
return new CreateNodeResponse(PacketError.Condition.feature_not_implemented, pubsubError, null);
}
if (parentNode != null && !collectionType) {
// Check if requester is allowed to add a new leaf child node to the parent node
if (!parentNode.isAssociationAllowed(from)) {
// User is not allowed to add child leaf node to parent node. Return an error.
return new CreateNodeResponse(PacketError.Condition.forbidden, null, null);
}
// Check if number of child leaf nodes has not been exceeded
if (parentNode.isMaxLeafNodeReached()) {
// Max number of child leaf nodes has been reached. Return an error.
Element pubsubError = DocumentHelper.createElement(QName.get("max-nodes-exceeded", "http://jabber.org/protocol/pubsub#errors"));
return new CreateNodeResponse(PacketError.Condition.conflict, pubsubError, null);
}
}
// Create and configure the node
boolean conflict = false;
Node newNode = null;
try {
// TODO Assumed that the owner of the subscription is the bare JID of the subscription JID. Waiting StPeter answer for explicit field.
JID owner = from.asBareJID();
synchronized (newNodeID.intern()) {
if (service.getNode(newNodeID) == null) {
// Create the node
if (collectionType) {
newNode = new CollectionNode(service, parentNode, newNodeID, from);
} else {
newNode = new LeafNode(service, parentNode, newNodeID, from);
}
// Add the creator as the node owner
newNode.addOwner(owner);
// Configure and save the node to the backend store
if (completedForm != null) {
newNode.configure(completedForm);
} else {
newNode.saveToDB();
}
CacheFactory.doClusterTask(new RefreshNodeTask(newNode));
} else {
conflict = true;
}
}
if (conflict) {
// There is a conflict since a node with the same ID already exists
return new CreateNodeResponse(PacketError.Condition.conflict, null, null);
} else {
// Return success to the node owner
return new CreateNodeResponse(null, null, newNode);
}
} catch (NotAcceptableException e) {
// Node should have at least one owner. Return not-acceptable error.
return new CreateNodeResponse(PacketError.Condition.not_acceptable, null, null);
}
}
use of org.jivesoftware.openfire.pubsub.cluster.RefreshNodeTask in project Openfire by igniterealtime.
the class PubSubEngine method configureNode.
private void configureNode(PubSubService service, IQ iq, Element configureElement, String nodeID) {
Node node = service.getNode(nodeID);
if (node == null) {
// Node does not exist. Return item-not-found error
sendErrorPacket(iq, PacketError.Condition.item_not_found, null);
return;
}
if (!node.isAdmin(iq.getFrom())) {
// Requesting entity is not allowed to get node configuration. Return forbidden error
sendErrorPacket(iq, PacketError.Condition.forbidden, null);
return;
}
// Get the data form that contains the parent nodeID
DataForm completedForm = getSentConfigurationForm(configureElement);
if (completedForm != null) {
try {
// Update node configuration with the provided data form
// (and update the backend store)
node.configure(completedForm);
// TODO Replace with a cluster task that does not interact with the database (OF-2141).
CacheFactory.doClusterTask(new RefreshNodeTask(node));
// Return that node configuration was successful
router.route(IQ.createResultIQ(iq));
} catch (NotAcceptableException e) {
// Node should have at least one owner. Return not-acceptable error.
sendErrorPacket(iq, PacketError.Condition.not_acceptable, null);
}
} else {
// No data form was included so return bad-request error
sendErrorPacket(iq, PacketError.Condition.bad_request, null);
}
}
Aggregations