001/*
002 * Licensed to DuraSpace under one or more contributor license agreements.
003 * See the NOTICE file distributed with this work for additional information
004 * regarding copyright ownership.
005 *
006 * DuraSpace licenses this file to you under the Apache License,
007 * Version 2.0 (the "License"); you may not use this file except in
008 * compliance with the License.  You may obtain a copy of the License at
009 *
010 *     http://www.apache.org/licenses/LICENSE-2.0
011 *
012 * Unless required by applicable law or agreed to in writing, software
013 * distributed under the License is distributed on an "AS IS" BASIS,
014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015 * See the License for the specific language governing permissions and
016 * limitations under the License.
017 */
018package org.fcrepo.http.api;
019
020import static javax.ws.rs.core.Response.Status.BAD_GATEWAY;
021import static javax.ws.rs.core.Response.Status.CONFLICT;
022import static javax.ws.rs.core.Response.Status.PRECONDITION_FAILED;
023import static javax.ws.rs.core.Response.created;
024import static org.slf4j.LoggerFactory.getLogger;
025
026import java.net.URI;
027import java.net.URISyntaxException;
028
029import javax.annotation.PostConstruct;
030import javax.jcr.ItemExistsException;
031import javax.jcr.PathNotFoundException;
032import javax.servlet.http.HttpServletResponse;
033import javax.ws.rs.ClientErrorException;
034import javax.ws.rs.HeaderParam;
035import javax.ws.rs.Path;
036import javax.ws.rs.PathParam;
037import javax.ws.rs.ServerErrorException;
038import javax.ws.rs.core.Context;
039import javax.ws.rs.core.Request;
040import javax.ws.rs.core.Response;
041import javax.ws.rs.core.UriInfo;
042
043import org.fcrepo.http.commons.domain.COPY;
044import org.fcrepo.http.commons.domain.MOVE;
045import org.fcrepo.kernel.api.models.FedoraResource;
046import org.fcrepo.kernel.api.exception.RepositoryRuntimeException;
047import org.slf4j.Logger;
048import org.springframework.context.annotation.Scope;
049
050import com.google.common.annotations.VisibleForTesting;
051import org.apache.jena.rdf.model.ResourceFactory;
052
053/**
054 * CRUD operations on Fedora Nodes
055 *
056 * @author cbeer
057 */
058@Scope("request")
059@Path("/{path: .*}")
060public class FedoraNodes extends ContentExposingResource {
061
062    private static final Logger LOGGER = getLogger(FedoraNodes.class);
063
064    @Context protected Request request;
065    @Context protected HttpServletResponse servletResponse;
066    @Context protected UriInfo uriInfo;
067
068    @PathParam("path") protected String externalPath;
069
070    protected FedoraResource resource;
071
072    /**
073     * Default JAX-RS entry point
074     */
075    public FedoraNodes() {
076        super();
077    }
078
079    /**
080     * Create a new FedoraNodes instance for a given path
081     * @param externalPath the external path
082     */
083    @VisibleForTesting
084    public FedoraNodes(final String externalPath) {
085        this.externalPath = externalPath;
086    }
087
088
089    /**
090     * Run these actions after initializing this resource
091     */
092    @PostConstruct
093    public void postConstruct() {
094        setUpJMSInfo(uriInfo, headers);
095    }
096
097    /**
098     * @deprecated
099     * Copies an object from one path to another
100     * @param destinationUri the destination uri
101     * @throws URISyntaxException if uri syntax exception occurred
102     * @return the response
103     */
104    @COPY
105    @Deprecated
106    public Response copyObject(@HeaderParam("Destination") final String destinationUri)
107            throws URISyntaxException {
108
109        try {
110            final String source = translator().asString(translator().toDomain(externalPath));
111
112            if (!nodeService.exists(session.getFedoraSession(), source)) {
113                throw new ClientErrorException("The source path does not exist", CONFLICT);
114            }
115
116            final String destination = translator().asString(ResourceFactory.createResource(destinationUri));
117
118            if (destination == null) {
119                throw new ServerErrorException("Destination was not a valid resource path", BAD_GATEWAY);
120            } else if (nodeService.exists(session.getFedoraSession(), destination)) {
121                throw new ClientErrorException("Destination resource already exists", PRECONDITION_FAILED);
122            }
123
124            LOGGER.info("Copy from '{}' to '{}'", source, destination);
125            nodeService.copyObject(session.getFedoraSession(), source, destination);
126            session.commit();
127
128            return created(new URI(destinationUri)).build();
129        } catch (final RepositoryRuntimeException e) {
130            final Throwable cause = e.getCause();
131
132            if (cause instanceof ItemExistsException) {
133
134                throw new ClientErrorException("Destination resource already exists", PRECONDITION_FAILED, e);
135
136            } else if (cause instanceof PathNotFoundException) {
137
138                throw new ClientErrorException("There is no node that will serve as the parent of the copied item",
139                        CONFLICT, e);
140            } else {
141                throw e;
142            }
143        }
144
145    }
146
147    /**
148     * @deprecated
149     * Moves an object from one path to another
150     * @param destinationUri the destination uri
151     * @throws URISyntaxException if uri syntax exception occurred
152     * @return the response
153     */
154    @MOVE
155    @Deprecated
156    public Response moveObject(@HeaderParam("Destination") final String destinationUri)
157            throws URISyntaxException {
158
159        try {
160
161            final String source = toPath(translator(), externalPath);
162
163            if (!nodeService.exists(session.getFedoraSession(), source)) {
164                throw new ClientErrorException("The source path does not exist", CONFLICT);
165            }
166
167
168            evaluateRequestPreconditions(request, servletResponse, resource(), session);
169
170            final String destination = translator().asString(ResourceFactory.createResource(destinationUri));
171
172            if (destination == null) {
173                throw new ServerErrorException("Destination was not a valid resource path", BAD_GATEWAY);
174            } else if (nodeService.exists(session.getFedoraSession(), destination)) {
175                throw new ClientErrorException("Destination resource already exists", PRECONDITION_FAILED);
176            }
177
178            LOGGER.info("Move from '{}' to '{}'", source, destination);
179            nodeService.moveObject(session.getFedoraSession(), source, destination);
180            session.commit();
181            return created(new URI(destinationUri)).build();
182        } catch (final RepositoryRuntimeException e) {
183            final Throwable cause = e.getCause();
184
185            if (cause instanceof ItemExistsException) {
186                throw new ClientErrorException("Destination resource already exists", PRECONDITION_FAILED, e);
187            } else if (cause instanceof PathNotFoundException) {
188                throw new ClientErrorException("There is no node that will serve as the parent of the moved item",
189                        CONFLICT, e);
190            } else {
191                throw e;
192            }
193        }
194    }
195
196    @Override
197    protected void addResourceHttpHeaders(final FedoraResource resource) {
198        throw new UnsupportedOperationException();
199    }
200
201    @Override
202    protected String externalPath() {
203        return externalPath;
204    }
205
206}