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