All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.modeshape.web.jcr.rest.JcrResources Maven / Gradle / Ivy

There is a newer version: 5.4.1.Final
Show newest version
/*
 * ModeShape (http://www.modeshape.org)
 * See the COPYRIGHT.txt file distributed with this work for information
 * regarding copyright ownership.  Some portions may be licensed
 * to Red Hat, Inc. under one or more contributor license agreements.
 * See the AUTHORS.txt file in the distribution for a full listing of 
 * individual contributors. 
 *
 * ModeShape is free software. Unless otherwise indicated, all code in ModeShape
 * is licensed to you under the terms of the GNU Lesser General Public License as
 * published by the Free Software Foundation; either version 2.1 of
 * the License, or (at your option) any later version.
 *
 * ModeShape is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this software; if not, write to the Free
 * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
 * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
 */
package org.modeshape.web.jcr.rest;

import java.io.IOException;
import javax.jcr.RepositoryException;
import javax.jcr.Session;
import javax.jcr.query.InvalidQueryException;
import javax.jcr.query.Query;
import javax.servlet.http.HttpServletRequest;
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.DefaultValue;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriInfo;
import org.codehaus.jettison.json.JSONException;
import org.jboss.resteasy.spi.NotFoundException;
import org.jboss.resteasy.spi.UnauthorizedException;
import org.modeshape.common.annotation.Immutable;
import org.modeshape.common.util.Base64;
import org.modeshape.web.jcr.rest.handler.ItemHandler;
import org.modeshape.web.jcr.rest.handler.QueryHandler;
import org.modeshape.web.jcr.rest.handler.RepositoryHandler;
import org.modeshape.web.jcr.rest.handler.ServerHandler;

/**
 * RESTEasy handler to provide the JCR resources at the URIs below. Please note that these URIs assume a context of
 * {@code /resources} for the web application.
 * 
 * 
 * 
 * 
 * 
 * 
 * 
 * 
 * 
 * 
 * 
 * 
 * 
 * 
 * 
 * 
 * 
 * 
 * 
 * 
 * 
 * 
 * 
 * 
 * 
 * 
 * 
 * 
 * 
 * 
 * 
 * 
URI PatternDescriptionSupported Methods
/resourcesreturns a list of accessible repositoriesGET
/resources/{repositoryName}returns a list of accessible workspaces within that repositoryGET
/resources/{repositoryName}/{workspaceName}returns a list of operations within the workspaceGET
/resources/{repositoryName}/{workspaceName}/items/{path}accesses the item (node or property) at the pathGET, POST, PUT, DELETE
/resources/{repositoryName}/{workspaceName}/queryexecutes the query in the body of the request with a language specified by the content type (application/jcr+xpath, * application/jcr+sql, application/jcr+sql2, or application/search)POST
*

Binary data

*

* There are several ways to transfer binary property values, but all involve encoding the binary value into ASCII characters * using a {@link Base64} notation and denoting this by adding annotating the property name with a suffix defining the type of * encoding. Currently, only "base64" encoding is supported. *

*

* For example, if the "jcr:data" property contains a single binary value of "propertyValue", then the JSON object representing * that property will be: * *

 *   "jcr:data/base64/" : "cHJvcGVydHlWYWx1ZQ=="
 * 
* * Likewise, if the "jcr:data" property contains two binary values each being "propertyValue", then the JSON object representing * that property will be: * *
 *   "jcr:data/base64/" : [ "cHJvcGVydHlWYWx1ZQ==", "cHJvcGVydHlWYWx1ZQ==" ]
 * 
* * Note that JCR 1.0.1 does not allow property names to and with a '/' character (among others), while JCR 2.0 does not allow * property names to contain an unescaped or unencoded '/' character. Therefore, the "/{encoding}/" suffix can never appear in a * valid JCR property name, and will always identify an encoded property. *

*

* Here are the details: *

    *
  • Getting a node with GET /resources/{repositoryName}/item/{pathToNode} obtains the JSON object representing the * node, and each property is represented as a nested JSON object where the name is the property name and the value(s) are * represented as either a single string value or an array of string values. If the property has a binary value, then the property * name is appended with "/base64/" and the string representation of each value is encoded in Base64.
  • *
  • Getting a property with GET /resources/{repositoryName}/item/{pathToProperty} allows only the value(s) for the * one property to be included in the response. If any of the values is a binary value, then all of the values will be * encoded in Base64.
  • *
  • Setting a property with PUT /resources/{repositoryName}/item/{pathToProperty} allows setting the property to a * single value, and only that value needs to be included in the body of the request. If the value is binary, the value * must be {@link Base64 encoded} by the client and the "Content-Transfer-Encoding" header must be set to "base64" (case * does not matter). When the request is received, the value is decoded before the property value is updated on the node.
  • *
  • Creating a node with POST /resources/{repositoryName}/item/{pathToNode} requires a request that is structured * in the same way as the response from getting a node: the resulting JSON object represents the node, with nested JSON objects * for the properties and children. If any property of the new node has a binary value, then the name of the property must * be appended with "/base64/" and the string representation of each value are to be encoded in Base64.
  • *
  • Updating a node with PUT /resources/{repositoryName}/item/{pathToNode} requires a request that is structured * in the same way as the response from getting or posting a node: the resulting JSON object represents the node, with nested JSON * objects for the properties and children. If any property of the new node has a binary value, then the name of the property * must be appended with "/base64/" and the string representation of each value are to be encoded in Base64.
  • *
*

* * @deprecated since 3.0, the default service is {@link ModeShapeRestService} */ @Deprecated @Immutable @Path( "/v1" ) public class JcrResources { /** * This is a duplicate of the FullTextSearchParser.LANGUAGE field, but it is split out here to avoid adding a dependency on * the modeshape-jcr package. */ private final static String SEARCH_LANGUAGE = "Search"; private ServerHandler serverHandler = new ServerHandler(); private RepositoryHandler repositoryHandler = new RepositoryHandler(); private ItemHandler itemHandler = new ItemHandler(); private QueryHandler queryHandler = new QueryHandler(); /** * Returns the list of JCR repositories available on this server * * @param request the servlet request; may not be null * @return the list of JCR repositories available on this server * @throws JSONException if there is an error encoding the node * @throws RepositoryException if any other error occurs */ @GET @Path( "/" ) @Produces( {MediaType.TEXT_PLAIN, MediaType.APPLICATION_JSON, MediaType.TEXT_HTML} ) public String getRepositories( @Context HttpServletRequest request ) throws JSONException, RepositoryException { return serverHandler.getRepositories(request); } /** * Returns the list of workspaces available to this user within the named repository. * * @param rawRepositoryName the name of the repository; may not be null * @param request the servlet request; may not be null * @return the list of workspaces available to this user within the named repository. * @throws JSONException if there is an error encoding the node * @throws RepositoryException if there is any other error accessing the list of available workspaces for the repository */ @GET @Path( "{repositoryName}" ) @Produces( {MediaType.TEXT_PLAIN, MediaType.APPLICATION_JSON, MediaType.TEXT_HTML} ) public String getWorkspaces( @Context HttpServletRequest request, @PathParam( "repositoryName" ) String rawRepositoryName ) throws JSONException, RepositoryException { return repositoryHandler.getWorkspaces(request, rawRepositoryName); } /** * Handles GET requests for an item in a workspace. * * @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 deprecatedDepth the old depth parameter ("mode:depth"). This version is deprecated and should use the "depth" query * parameter instead. * @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 the JSON-encoded version of the item (and, if the item is a node, its subgraph, depending on the value of * {@code depth}) * @throws NotFoundException if the named repository does not exists, the named workspace does not exist, or the user does not * have access to the named workspace * @throws JSONException if there is an error encoding the node * @throws UnauthorizedException if the given login information is invalid * @throws RepositoryException if any other error occurs * @see org.modeshape.web.jcr.rest.handler.AbstractHandler#EMPTY_REPOSITORY_NAME * @see org.modeshape.web.jcr.rest.handler.AbstractHandler#EMPTY_REPOSITORY_NAME * @see Session#getItem(String) */ @GET @Path( "{repositoryName}/{workspaceName}/items{path:.*}" ) @Produces( {MediaType.TEXT_PLAIN, MediaType.APPLICATION_JSON, MediaType.TEXT_HTML} ) public String getItem( @Context HttpServletRequest request, @PathParam( "repositoryName" ) String rawRepositoryName, @PathParam( "workspaceName" ) String rawWorkspaceName, @PathParam( "path" ) String path, @QueryParam( "mode:depth" ) @DefaultValue( "0" ) int deprecatedDepth, @QueryParam( "depth" ) @DefaultValue( "0" ) int depth ) throws JSONException, UnauthorizedException, RepositoryException { if (depth == 0 && deprecatedDepth != 0) { depth = deprecatedDepth; } return itemHandler.getItem(request, rawRepositoryName, rawWorkspaceName, path, depth); } /** * 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 rawRepositoryName the URL-encoded repository name * @param rawWorkspaceName the URL-encoded workspace name * @param path the path to the item * @param fullNodeInResponse if {@code fullNodeInResponse == null || Boolean.valueOf(fullNodeInResponse)}, indicates that a * representation of the created node (including all properties and children) should be returned; otherwise, only the * path to the new node will be returned * @param requestContent 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 requestContent} * in that auto-created and protected properties (e.g., jcr:uuid) will be populated. * @throws NotFoundException if the parent of the item to be added does not exist * @throws UnauthorizedException if the user does not have the access required to create the node at this path * @throws JSONException if there is an error encoding the node * @throws RepositoryException if any other error occurs */ @POST @Path( "{repositoryName}/{workspaceName}/items/{path:.*}" ) @Produces( {MediaType.TEXT_PLAIN, MediaType.APPLICATION_JSON, MediaType.TEXT_HTML} ) public Response postItem( @Context HttpServletRequest request, @PathParam( "repositoryName" ) String rawRepositoryName, @PathParam( "workspaceName" ) String rawWorkspaceName, @PathParam( "path" ) String path, @QueryParam( "mode:includeNode" ) String fullNodeInResponse, String requestContent ) throws NotFoundException, UnauthorizedException, RepositoryException, JSONException { return itemHandler.postItem(request, rawRepositoryName, rawWorkspaceName, path, fullNodeInResponse == null || Boolean.valueOf(fullNodeInResponse), requestContent); } /** * Deletes the item at {@code path}. * * @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 * @throws NotFoundException if no item exists at {@code path} * @throws UnauthorizedException if the user does not have the access required to delete the item at this path * @throws RepositoryException if any other error occurs */ @DELETE @Path( "{repositoryName}/{workspaceName}/items{path:.*}" ) public void deleteItem( @Context HttpServletRequest request, @PathParam( "repositoryName" ) String rawRepositoryName, @PathParam( "workspaceName" ) String rawWorkspaceName, @PathParam( "path" ) String path ) throws NotFoundException, UnauthorizedException, RepositoryException { itemHandler.deleteItem(request, rawRepositoryName, rawWorkspaceName, path); } /** * 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 NotFoundException if the parent of the item to be added does not exist * @throws UnauthorizedException if the user does not have the access required to create the node at this path * @throws JSONException if there is an error encoding the node * @throws RepositoryException if any other error occurs * @throws IOException if there is a problem reading the value */ @PUT @Path( "{repositoryName}/{workspaceName}/items{path:.*}" ) @Consumes( MediaType.APPLICATION_JSON ) @Produces( {MediaType.TEXT_PLAIN, MediaType.APPLICATION_JSON, MediaType.TEXT_HTML} ) public String putItem( @Context HttpServletRequest request, @PathParam( "repositoryName" ) String rawRepositoryName, @PathParam( "workspaceName" ) String rawWorkspaceName, @PathParam( "path" ) String path, String requestContent ) throws UnauthorizedException, JSONException, RepositoryException, IOException { return itemHandler.putItem(request, rawRepositoryName, rawWorkspaceName, path, requestContent); } /** * Executes the XPath query contained in the body of the request against the give repository and workspace. *

* The query results will be JSON-encoded in the response body. *

* * @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 offset the offset to the first row to be returned. If this value is greater than the size of the result set, no * records will be returned. If this value is less than 0, results will be returned starting from the first record in * the result set. * @param limit the maximum number of rows to be returned. If this value is greater than the size of the result set, the * entire result set will be returned. If this value is less than zero, the entire result set will be returned. The * results are counted from the record specified in the offset parameter. * @param uriInfo the information about the URI (from which the other query parameters will be obtained) * @param requestContent the query expression * @return the JSON-encoded representation of the query results. * @throws JSONException if there is an error encoding the node * @throws InvalidQueryException if the query contained an error, was invalid, or could not be executed * @throws RepositoryException if any other error occurs */ @POST @Path( "{repositoryName}/{workspaceName}/query" ) @Consumes( "application/jcr+xpath" ) @Produces( {MediaType.TEXT_PLAIN, MediaType.APPLICATION_JSON, MediaType.TEXT_HTML} ) public String postXPathQuery( @Context HttpServletRequest request, @PathParam( "repositoryName" ) String rawRepositoryName, @PathParam( "workspaceName" ) String rawWorkspaceName, @QueryParam( "offset" ) @DefaultValue( "-1" ) long offset, @QueryParam( "limit" ) @DefaultValue( "-1" ) long limit, @Context UriInfo uriInfo, String requestContent ) throws InvalidQueryException, RepositoryException, JSONException { return queryHandler.postItem(request, rawRepositoryName, rawWorkspaceName, Query.XPATH, requestContent, offset, limit, uriInfo); } /** * Executes the JCR-SQL query contained in the body of the request against the give repository and workspace. *

* The query results will be JSON-encoded in the response body. *

* * @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 offset the offset to the first row to be returned. If this value is greater than the size of the result set, no * records will be returned. If this value is less than 0, results will be returned starting from the first record in * the result set. * @param limit the maximum number of rows to be returned. If this value is greater than the size of the result set, the * entire result set will be returned. If this value is less than zero, the entire result set will be returned. The * results are counted from the record specified in the offset parameter. * @param uriInfo the information about the URI (from which the other query parameters will be obtained) * @param requestContent the query expression * @return the JSON-encoded representation of the query results. * @throws JSONException if there is an error encoding the node * @throws InvalidQueryException if the query contained an error, was invalid, or could not be executed * @throws RepositoryException if any other error occurs */ @POST @Path( "{repositoryName}/{workspaceName}/query" ) @Consumes( "application/jcr+sql" ) @Produces( {MediaType.TEXT_PLAIN, MediaType.APPLICATION_JSON, MediaType.TEXT_HTML} ) public String postJcrSqlQuery( @Context HttpServletRequest request, @PathParam( "repositoryName" ) String rawRepositoryName, @PathParam( "workspaceName" ) String rawWorkspaceName, @QueryParam( "offset" ) @DefaultValue( "-1" ) long offset, @QueryParam( "limit" ) @DefaultValue( "-1" ) long limit, @Context UriInfo uriInfo, String requestContent ) throws InvalidQueryException, RepositoryException, JSONException { return queryHandler.postItem(request, rawRepositoryName, rawWorkspaceName, Query.SQL, requestContent, offset, limit, uriInfo); } /** * Executes the JCR-SQL2 query contained in the body of the request against the give repository and workspace. *

* The query results will be JSON-encoded in the response body. *

* * @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 offset the offset to the first row to be returned. If this value is greater than the size of the result set, no * records will be returned. If this value is less than 0, results will be returned starting from the first record in * the result set. * @param limit the maximum number of rows to be returned. If this value is greater than the size of the result set, the * entire result set will be returned. If this value is less than zero, the entire result set will be returned. The * results are counted from the record specified in the offset parameter. * @param uriInfo the information about the URI (from which the other query parameters will be obtained) * @param requestContent the query expression * @return the JSON-encoded representation of the query results. * @throws JSONException if there is an error encoding the node * @throws InvalidQueryException if the query contained an error, was invalid, or could not be executed * @throws RepositoryException if any other error occurs */ @POST @Path( "{repositoryName}/{workspaceName}/query" ) @Consumes( "application/jcr+sql2" ) @Produces( {MediaType.TEXT_PLAIN, MediaType.APPLICATION_JSON, MediaType.TEXT_HTML} ) public String postJcrSql2Query( @Context HttpServletRequest request, @PathParam( "repositoryName" ) String rawRepositoryName, @PathParam( "workspaceName" ) String rawWorkspaceName, @QueryParam( "offset" ) @DefaultValue( "-1" ) long offset, @QueryParam( "limit" ) @DefaultValue( "-1" ) long limit, @Context UriInfo uriInfo, String requestContent ) throws InvalidQueryException, RepositoryException, JSONException { return queryHandler.postItem(request, rawRepositoryName, rawWorkspaceName, Query.JCR_SQL2, requestContent, offset, limit, uriInfo); } /** * Executes the JCR-SQL query contained in the body of the request against the give repository and workspace. *

* The query results will be JSON-encoded in the response body. *

* * @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 offset the offset to the first row to be returned. If this value is greater than the size of the result set, no * records will be returned. If this value is less than 0, results will be returned starting from the first record in * the result set. * @param limit the maximum number of rows to be returned. If this value is greater than the size of the result set, the * entire result set will be returned. If this value is less than zero, the entire result set will be returned. The * results are counted from the record specified in the offset parameter. * @param uriInfo the information about the URI (from which the other query parameters will be obtained) * @param requestContent the query expression * @return the JSON-encoded representation of the query results. * @throws JSONException if there is an error encoding the node * @throws InvalidQueryException if the query contained an error, was invalid, or could not be executed * @throws RepositoryException if any other error occurs */ @POST @Path( "{repositoryName}/{workspaceName}/query" ) @Consumes( "application/jcr+search" ) @Produces( {MediaType.TEXT_PLAIN, MediaType.APPLICATION_JSON, MediaType.TEXT_HTML} ) public String postJcrSearchQuery( @Context HttpServletRequest request, @PathParam( "repositoryName" ) String rawRepositoryName, @PathParam( "workspaceName" ) String rawWorkspaceName, @QueryParam( "offset" ) @DefaultValue( "-1" ) long offset, @QueryParam( "limit" ) @DefaultValue( "-1" ) long limit, @Context UriInfo uriInfo, String requestContent ) throws RepositoryException, JSONException { return queryHandler.postItem(request, rawRepositoryName, rawWorkspaceName, SEARCH_LANGUAGE, requestContent, offset, limit, uriInfo); } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy