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 com.fasterxml.jackson.databind.ObjectMapper;
021import com.fasterxml.jackson.databind.node.ObjectNode;
022import com.google.common.annotations.VisibleForTesting;
023import com.hp.hpl.jena.graph.Node;
024import com.hp.hpl.jena.rdf.model.Resource;
025import org.apache.commons.lang3.StringUtils;
026import org.fcrepo.http.commons.AbstractResource;
027import org.fcrepo.http.commons.api.rdf.HttpResourceConverter;
028import org.fcrepo.kernel.api.exception.SessionMissingException;
029import org.fcrepo.kernel.api.exception.TombstoneException;
030import org.fcrepo.kernel.api.identifiers.IdentifierConverter;
031import org.fcrepo.kernel.api.models.FedoraResource;
032import org.fcrepo.kernel.api.models.Tombstone;
033import org.slf4j.Logger;
034
035import javax.inject.Inject;
036import javax.jcr.Session;
037import javax.jcr.observation.ObservationManager;
038import javax.ws.rs.core.HttpHeaders;
039import javax.ws.rs.core.UriInfo;
040
041import static org.fcrepo.kernel.api.observer.OptionalValues.BASE_URL;
042import static org.fcrepo.kernel.api.observer.OptionalValues.USER_AGENT;
043import static org.slf4j.LoggerFactory.getLogger;
044
045/**
046 * @author cabeer
047 * @since 10/5/14
048 */
049abstract public class FedoraBaseResource extends AbstractResource {
050
051    private static final Logger LOGGER = getLogger(FedoraBaseResource.class);
052
053    @Inject
054    protected Session session;
055
056    protected IdentifierConverter<Resource, FedoraResource> idTranslator;
057
058    protected IdentifierConverter<Resource, FedoraResource> translator() {
059        if (idTranslator == null) {
060            idTranslator = new HttpResourceConverter(session(),
061                    uriInfo.getBaseUriBuilder().clone().path(FedoraLdp.class));
062        }
063
064        return idTranslator;
065    }
066
067    /**
068     * This is a helper method for using the idTranslator to convert this resource into an associated Jena Node.
069     *
070     * @param resource to be converted into a Jena Node
071     * @return the Jena node
072     */
073    protected Node asNode(final FedoraResource resource) {
074        return translator().reverse().convert(resource).asNode();
075    }
076
077    /**
078     * Get the FedoraResource for the resource at the external path
079     * @param externalPath the external path
080     * @return the fedora resource at the external path
081     */
082    @VisibleForTesting
083    public FedoraResource getResourceFromPath(final String externalPath) {
084        final Resource resource = translator().toDomain(externalPath);
085        final FedoraResource fedoraResource = translator().convert(resource);
086
087        if (fedoraResource instanceof Tombstone) {
088            throw new TombstoneException(fedoraResource, resource.getURI() + "/fcr:tombstone");
089        }
090
091        return fedoraResource;
092    }
093
094    /**
095     * Set the baseURL for JMS events.
096     * @param uriInfo the uri info
097     * @param headers HTTP headers
098     **/
099    protected void setUpJMSInfo(final UriInfo uriInfo, final HttpHeaders headers) {
100        try {
101            String baseURL = getBaseUrlProperty();
102            if (baseURL.length() == 0) {
103                baseURL = uriInfo.getBaseUri().toString();
104            }
105            LOGGER.debug("setting baseURL = " + baseURL);
106            final ObservationManager obs = session().getWorkspace().getObservationManager();
107            final ObjectMapper mapper = new ObjectMapper();
108            final ObjectNode json = mapper.createObjectNode();
109            json.put(BASE_URL, baseURL);
110            if (!StringUtils.isBlank(headers.getHeaderString("user-agent"))) {
111                json.put(USER_AGENT, headers.getHeaderString("user-agent"));
112            }
113            obs.setUserData(mapper.writeValueAsString(json));
114        } catch (final Exception ex) {
115            LOGGER.warn("Error setting baseURL", ex.getMessage());
116        }
117    }
118
119    /**
120     * Produce a baseURL for JMS events using the system property fcrepo.jms.baseUrl of the form http[s]://host[:port],
121     * if it exists.
122     *
123     * @return String the base Url
124     */
125    protected String getBaseUrlProperty() {
126        final String propBaseURL = System.getProperty("fcrepo.jms.baseUrl", "");
127        if (propBaseURL.length() > 0 && propBaseURL.startsWith("http")) {
128            return uriInfo.getBaseUriBuilder().uri(propBaseURL).toString();
129        }
130        return "";
131    }
132
133    protected Session session() {
134        if (session == null) {
135            throw new SessionMissingException("Invalid session");
136        }
137        return session;
138    }
139}