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