![JAR search and dependency download from the Maven repository](/logo.png)
org.modeshape.web.jcr.rest.handler.RestItemHandler Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of modeshape-web-jcr-rest
Show all versions of modeshape-web-jcr-rest
ModeShape REST support library
/*
* ModeShape (http://www.modeshape.org)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.modeshape.web.jcr.rest.handler;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.TreeMap;
import java.util.TreeSet;
import javax.jcr.Item;
import javax.jcr.Node;
import javax.jcr.RepositoryException;
import javax.jcr.Session;
import javax.servlet.http.HttpServletRequest;
import javax.ws.rs.NotFoundException;
import javax.ws.rs.core.GenericEntity;
import javax.ws.rs.core.Response;
import org.codehaus.jettison.json.JSONArray;
import org.codehaus.jettison.json.JSONException;
import org.codehaus.jettison.json.JSONObject;
import org.modeshape.common.util.StringUtil;
import org.modeshape.web.jcr.rest.model.RestItem;
/**
* An extension to the {@link ItemHandler} which is used by {@link org.modeshape.web.jcr.rest.ModeShapeRestService} to interact
* with properties and nodes.
*
* @author Horia Chiorean ([email protected])
*/
public final class RestItemHandler extends ItemHandler {
/**
* Retrieves the JCR {@link Item} at the given path, returning its rest representation.
*
* @param request the servlet request; may not be null or unauthenticated
* @param repositoryName the URL-encoded repository name
* @param workspaceName the URL-encoded workspace name
* @param path the path to the item
* @param depth the depth of the node graph that should be returned if {@code path} refers to a node. @{code 0} means return
* the requested node only. A negative value indicates that the full subgraph under the node should be returned. This
* parameter defaults to {@code 0} and is ignored if {@code path} refers to a property.
* @return a the rest representation of the item, as a {@link RestItem} instance.
* @throws RepositoryException if any JCR operations fail.
*/
public RestItem item( HttpServletRequest request,
String repositoryName,
String workspaceName,
String path,
int depth ) throws RepositoryException {
Session session = getSession(request, repositoryName, workspaceName);
Item item = itemAtPath(path, session);
return createRestItem(request, depth, session, item);
}
/**
* Adds the content of the request as a node (or subtree of nodes) at the location specified by {@code path}.
*
* The primary type and mixin type(s) may optionally be specified through the {@code jcr:primaryType} and
* {@code jcr:mixinTypes} properties.
*
*
* @param request the servlet request; may not be null or unauthenticated
* @param repositoryName the URL-encoded repository name
* @param workspaceName the URL-encoded workspace name
* @param path the path to the item
* @param requestBody the JSON-encoded representation of the node or nodes to be added
* @return the JSON-encoded representation of the node or nodes that were added. This will differ from {@code requestBody} in
* that auto-created and protected properties (e.g., jcr:uuid) will be populated.
* @throws org.codehaus.jettison.json.JSONException if the request body cannot be translated into json
* @throws RepositoryException if any other error occurs while interacting with the repository
*/
public Response addItem( HttpServletRequest request,
String repositoryName,
String workspaceName,
String path,
String requestBody ) throws JSONException, RepositoryException {
JSONObject requestBodyJSON = stringToJSONObject(requestBody);
String parentAbsPath = parentPath(path);
String newNodeName = newNodeName(path);
Session session = getSession(request, repositoryName, workspaceName);
Node parentNode = (Node)session.getItem(parentAbsPath);
Node newNode = addNode(parentNode, newNodeName, requestBodyJSON);
session.save();
RestItem restNewNode = createRestItem(request, 0, session, newNode);
return Response.status(Response.Status.CREATED).entity(restNewNode).build();
}
@Override
protected JSONObject getProperties( JSONObject jsonNode ) throws JSONException {
JSONObject properties = new JSONObject();
for (Iterator> keysIterator = jsonNode.keys(); keysIterator.hasNext();) {
String key = keysIterator.next().toString();
if (CHILD_NODE_HOLDER.equalsIgnoreCase(key)) {
continue;
}
properties.put(key, jsonNode.get(key));
}
return properties;
}
private String newNodeName( String path ) {
int lastSlashInd = path.lastIndexOf('/');
String name = lastSlashInd == -1 ? path : path.substring(lastSlashInd + 1);
// Remove any SNS index ...
name = name.replaceAll("\\[\\d+\\]$", "");
return name;
}
/**
* Updates the properties at the path.
*
* If path points to a property, this method expects the request content to be either a JSON array or a JSON string. The array
* or string will become the values or value of the property. If path points to a node, this method expects the request
* content to be a JSON object. The keys of the objects correspond to property names that will be set and the values for the
* keys correspond to the values that will be set on the properties.
*
*
* @param request the servlet request; may not be null or unauthenticated
* @param rawRepositoryName the URL-encoded repository name
* @param rawWorkspaceName the URL-encoded workspace name
* @param path the path to the item
* @param requestContent the JSON-encoded representation of the values and, possibly, properties to be set
* @return the JSON-encoded representation of the node on which the property or properties were set.
* @throws JSONException if there is an error encoding the node
* @throws RepositoryException if any error occurs at the repository level.
*/
public RestItem updateItem( HttpServletRequest request,
String rawRepositoryName,
String rawWorkspaceName,
String path,
String requestContent ) throws JSONException, RepositoryException {
Session session = getSession(request, rawRepositoryName, rawWorkspaceName);
Item item = itemAtPath(path, session);
item = updateItem(item, stringToJSONObject(requestContent));
session.save();
return createRestItem(request, 0, session, item);
}
private JSONObject stringToJSONObject( String requestBody ) throws JSONException {
return StringUtil.isBlank(requestBody) ? new JSONObject() : new JSONObject(requestBody);
}
private JSONArray stringToJSONArray( String requestBody ) throws JSONException {
return StringUtil.isBlank(requestBody) ? new JSONArray() : new JSONArray(requestBody);
}
/**
* Performs a bulk creation of items, using a single {@link Session}. If any of the items cannot be created for whatever
* reason, the entire operation fails.
*
* @param request the servlet request; may not be null or unauthenticated
* @param repositoryName the URL-encoded repository name
* @param workspaceName the URL-encoded workspace name
* @param requestContent the JSON-encoded representation of the nodes and, possibly, properties to be added
* @return a {@code non-null} {@link Response}
* @throws JSONException if the body of the request is not a valid JSON object
* @throws RepositoryException if any of the JCR operations fail
* @see RestItemHandler#addItem(javax.servlet.http.HttpServletRequest, String, String, String, String)
*/
public Response addItems( HttpServletRequest request,
String repositoryName,
String workspaceName,
String requestContent ) throws JSONException, RepositoryException {
JSONObject requestBody = stringToJSONObject(requestContent);
if (requestBody.length() == 0) {
return Response.ok().build();
}
Session session = getSession(request, repositoryName, workspaceName);
TreeMap nodesByPath = createNodesByPathMap(requestBody);
return addMultipleNodes(request, nodesByPath, session);
}
/**
* Performs a bulk updating of items, using a single {@link Session}. If any of the items cannot be updated for whatever
* reason, the entire operation fails.
*
* @param request the servlet request; may not be null or unauthenticated
* @param repositoryName the URL-encoded repository name
* @param workspaceName the URL-encoded workspace name
* @param requestContent the JSON-encoded representation of the values and, possibly, properties to be set
* @return a {@code non-null} {@link Response}
* @throws JSONException if the body of the request is not a valid JSON object
* @throws RepositoryException if any of the JCR operations fail
* @see RestItemHandler#updateItem(javax.servlet.http.HttpServletRequest, String, String, String, String)
*/
public Response updateItems( HttpServletRequest request,
String repositoryName,
String workspaceName,
String requestContent ) throws JSONException, RepositoryException {
JSONObject requestBody = stringToJSONObject(requestContent);
if (requestBody.length() == 0) {
return Response.ok().build();
}
Session session = getSession(request, repositoryName, workspaceName);
TreeMap nodesByPath = createNodesByPathMap(requestBody);
List result = updateMultipleNodes(request, session, nodesByPath);
return createOkResponse(result);
}
/**
* Performs a bulk deletion of items, using a single {@link Session}. If any of the items cannot be deleted for whatever
* reason, the entire operation fails.
*
* @param request the servlet request; may not be null or unauthenticated
* @param repositoryName the URL-encoded repository name
* @param workspaceName the URL-encoded workspace name
* @param requestContent the JSON-encoded array of the nodes to remove
* @return a {@code non-null} {@link Response}
* @throws JSONException if the body of the request is not a valid JSON array
* @throws RepositoryException if any of the JCR operations fail
* @see RestItemHandler#deleteItem(javax.servlet.http.HttpServletRequest, String, String, String)
*/
public Response deleteItems( HttpServletRequest request,
String repositoryName,
String workspaceName,
String requestContent ) throws JSONException, RepositoryException {
JSONArray requestArray = stringToJSONArray(requestContent);
if (requestArray.length() == 0) {
return Response.ok().build();
}
Session session = getSession(request, repositoryName, workspaceName);
TreeSet pathsInOrder = new TreeSet<>();
for (int i = 0; i < requestArray.length(); i++) {
pathsInOrder.add(absPath(requestArray.get(i).toString()));
}
List pathsInOrderList = new ArrayList<>(pathsInOrder);
Collections.reverse(pathsInOrderList);
for (String path : pathsInOrderList) {
try {
doDelete(path, session);
} catch (NotFoundException e) {
logger.info("Node at path {0} already deleted", path);
}
}
session.save();
return Response.ok().build();
}
private List updateMultipleNodes( HttpServletRequest request,
Session session,
TreeMap nodesByPath )
throws RepositoryException, JSONException {
List result = new ArrayList();
for (String nodePath : nodesByPath.keySet()) {
Item item = session.getItem(nodePath);
item = updateItem(item, nodesByPath.get(nodePath));
result.add(createRestItem(request, 0, session, item));
}
session.save();
return result;
}
private TreeMap createNodesByPathMap( JSONObject requestBodyJSON ) throws JSONException {
TreeMap nodesByPath = new TreeMap();
for (Iterator> iterator = requestBodyJSON.keys(); iterator.hasNext();) {
String key = iterator.next().toString();
String nodePath = absPath(key);
JSONObject nodeJSON = requestBodyJSON.getJSONObject(key);
nodesByPath.put(nodePath, nodeJSON);
}
return nodesByPath;
}
private Response addMultipleNodes( HttpServletRequest request,
TreeMap nodesByPath,
Session session ) throws RepositoryException, JSONException {
List result = new ArrayList();
for (String nodePath : nodesByPath.keySet()) {
String parentAbsPath = parentPath(nodePath);
String newNodeName = newNodeName(nodePath);
Node parentNode = (Node)session.getItem(parentAbsPath);
Node newNode = addNode(parentNode, newNodeName, nodesByPath.get(nodePath));
RestItem restNewNode = createRestItem(request, 0, session, newNode);
result.add(restNewNode);
}
session.save();
return createOkResponse(result);
}
private Response createOkResponse( final List result ) {
GenericEntity> entity = new GenericEntity>(result) {};
return Response.ok().entity(entity).build();
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy