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.codahale.metrics.annotation.Timed;
051import com.google.common.annotations.VisibleForTesting;
052import org.apache.jena.rdf.model.ResourceFactory;
053
054/**
055 * CRUD operations on Fedora Nodes
056 *
057 * @author cbeer
058 */
059@Scope("request")
060@Path("/{path: .*}")
061public class FedoraNodes extends ContentExposingResource {
062
063    private static final Logger LOGGER = getLogger(FedoraNodes.class);
064
065    @Context protected Request request;
066    @Context protected HttpServletResponse servletResponse;
067    @Context protected UriInfo uriInfo;
068
069    @PathParam("path") protected String externalPath;
070
071    protected FedoraResource resource;
072
073    /**
074     * Default JAX-RS entry point
075     */
076    public FedoraNodes() {
077        super();
078    }
079
080    /**
081     * Create a new FedoraNodes instance for a given path
082     * @param externalPath the external path
083     */
084    @VisibleForTesting
085    public FedoraNodes(final String externalPath) {
086        this.externalPath = externalPath;
087    }
088
089
090    /**
091     * Run these actions after initializing this resource
092     */
093    @PostConstruct
094    public void postConstruct() {
095        setUpJMSInfo(uriInfo, headers);
096    }
097
098    /**
099     * @deprecated
100     * Copies an object from one path to another
101     * @param destinationUri the destination uri
102     * @throws URISyntaxException if uri syntax exception occurred
103     * @return the response
104     */
105    @COPY
106    @Timed
107    @Deprecated
108    public Response copyObject(@HeaderParam("Destination") final String destinationUri)
109            throws URISyntaxException {
110
111        try {
112            final String source = translator().asString(translator().toDomain(externalPath));
113
114            if (!nodeService.exists(session.getFedoraSession(), source)) {
115                throw new ClientErrorException("The source path does not exist", CONFLICT);
116            }
117
118            final String destination = translator().asString(ResourceFactory.createResource(destinationUri));
119
120            if (destination == null) {
121                throw new ServerErrorException("Destination was not a valid resource path", BAD_GATEWAY);
122            } else if (nodeService.exists(session.getFedoraSession(), destination)) {
123                throw new ClientErrorException("Destination resource already exists", PRECONDITION_FAILED);
124            }
125
126            LOGGER.info("Copy from '{}' to '{}'", source, destination);
127            nodeService.copyObject(session.getFedoraSession(), source, destination);
128            session.commit();
129
130            return created(new URI(destinationUri)).build();
131        } catch (final RepositoryRuntimeException e) {
132            final Throwable cause = e.getCause();
133
134            if (cause instanceof ItemExistsException) {
135
136                throw new ClientErrorException("Destination resource already exists", PRECONDITION_FAILED, e);
137
138            } else if (cause instanceof PathNotFoundException) {
139
140                throw new ClientErrorException("There is no node that will serve as the parent of the copied item",
141                        CONFLICT, e);
142            } else {
143                throw e;
144            }
145        }
146
147    }
148
149    /**
150     * @deprecated
151     * Moves an object from one path to another
152     * @param destinationUri the destination uri
153     * @throws URISyntaxException if uri syntax exception occurred
154     * @return the response
155     */
156    @MOVE
157    @Timed
158    @Deprecated
159    public Response moveObject(@HeaderParam("Destination") final String destinationUri)
160            throws URISyntaxException {
161
162        try {
163
164            final String source = toPath(translator(), externalPath);
165
166            if (!nodeService.exists(session.getFedoraSession(), source)) {
167                throw new ClientErrorException("The source path does not exist", CONFLICT);
168            }
169
170
171            evaluateRequestPreconditions(request, servletResponse, resource(), session);
172
173            final String destination = translator().asString(ResourceFactory.createResource(destinationUri));
174
175            if (destination == null) {
176                throw new ServerErrorException("Destination was not a valid resource path", BAD_GATEWAY);
177            } else if (nodeService.exists(session.getFedoraSession(), destination)) {
178                throw new ClientErrorException("Destination resource already exists", PRECONDITION_FAILED);
179            }
180
181            LOGGER.info("Move from '{}' to '{}'", source, destination);
182            nodeService.moveObject(session.getFedoraSession(), source, destination);
183            session.commit();
184            return created(new URI(destinationUri)).build();
185        } catch (final RepositoryRuntimeException e) {
186            final Throwable cause = e.getCause();
187
188            if (cause instanceof ItemExistsException) {
189                throw new ClientErrorException("Destination resource already exists", PRECONDITION_FAILED, e);
190            } else if (cause instanceof PathNotFoundException) {
191                throw new ClientErrorException("There is no node that will serve as the parent of the moved item",
192                        CONFLICT, e);
193            } else {
194                throw e;
195            }
196        }
197    }
198
199    @Override
200    protected void addResourceHttpHeaders(final FedoraResource resource) {
201        throw new UnsupportedOperationException();
202    }
203
204    @Override
205    protected String externalPath() {
206        return externalPath;
207    }
208
209}