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.kernel.impl.models;
019
020import org.fcrepo.kernel.api.exception.ItemNotFoundException;
021import org.fcrepo.kernel.api.exception.PathNotFoundException;
022import org.fcrepo.kernel.api.exception.PathNotFoundRuntimeException;
023import org.fcrepo.kernel.api.exception.RepositoryRuntimeException;
024import org.fcrepo.kernel.api.identifiers.FedoraId;
025import org.fcrepo.kernel.api.models.Binary;
026import org.fcrepo.kernel.api.models.ExternalContent;
027import org.fcrepo.kernel.api.models.FedoraResource;
028import org.fcrepo.kernel.api.models.ResourceFactory;
029import org.fcrepo.persistence.api.PersistentStorageSessionManager;
030import org.fcrepo.persistence.api.exceptions.PersistentItemNotFoundException;
031import org.fcrepo.persistence.api.exceptions.PersistentStorageException;
032
033import java.io.IOException;
034import java.io.InputStream;
035import java.net.URI;
036import java.util.Collection;
037import java.util.List;
038
039import static org.fcrepo.kernel.api.RdfLexicon.FEDORA_BINARY;
040import static org.fcrepo.kernel.api.models.ExternalContent.PROXY;
041
042
043/**
044 * Implementation of a Non-RDF resource.
045 *
046 * @author bbpennel
047 */
048public class BinaryImpl extends FedoraResourceImpl implements Binary {
049
050    private static final URI FEDORA_BINARY_URI = URI.create(FEDORA_BINARY.getURI());
051
052    private String externalHandling;
053
054    private String externalUrl;
055
056    private Long contentSize;
057
058    private String filename;
059
060    private String mimeType;
061
062    private Collection<URI> digests;
063
064    /**
065     * Construct the binary
066     *
067     * @param fedoraID fedora identifier
068     * @param txId transaction id
069     * @param pSessionManager session manager
070     * @param resourceFactory resource factory
071     */
072    public BinaryImpl(final FedoraId fedoraID, final String txId,
073                      final PersistentStorageSessionManager pSessionManager, final ResourceFactory resourceFactory) {
074        super(fedoraID, txId, pSessionManager, resourceFactory);
075    }
076
077    @Override
078    public InputStream getContent() {
079        try {
080            if (isProxy() || isRedirect()) {
081                return URI.create(getExternalURL()).toURL().openStream();
082            } else {
083                return getSession().getBinaryContent(getFedoraId().asResourceId(), getMementoDatetime());
084            }
085        } catch (final PersistentItemNotFoundException e) {
086            throw new ItemNotFoundException("Unable to find content for " + getId()
087                    + " version " + getMementoDatetime(), e);
088        } catch (final PersistentStorageException | IOException e) {
089            throw new RepositoryRuntimeException(e.getMessage(), e);
090        }
091    }
092
093    @Override
094    public long getContentSize() {
095        return contentSize;
096    }
097
098    @Override
099    public URI getContentDigest() {
100        // Returning the first digest for the time being
101        if (digests == null) {
102            return null;
103        }
104        final var digest = digests.stream().findFirst();
105        return digest.orElse(null);
106    }
107
108    @Override
109    public Boolean isProxy() {
110        return PROXY.equals(externalHandling);
111    }
112
113    @Override
114    public Boolean isRedirect() {
115        return ExternalContent.REDIRECT.equals(externalHandling);
116    }
117
118    @Override
119    public String getExternalURL() {
120        return externalUrl;
121    }
122
123    @Override
124    public String getMimeType() {
125        return mimeType;
126    }
127
128    @Override
129    public String getFilename() {
130        return filename;
131    }
132
133    @Override
134    public FedoraResource getDescription() {
135        try {
136            final FedoraId descId = getFedoraId().asDescription();
137            if (this.isMemento()) {
138                final var descIdAsMemento = descId.asMemento(getMementoDatetime());
139                return resourceFactory.getResource(txId, descIdAsMemento);
140            }
141            return resourceFactory.getResource(txId, descId);
142        } catch (final PathNotFoundException e) {
143            throw new PathNotFoundRuntimeException(e.getMessage(), e);
144        }
145    }
146
147    /**
148     * @param externalHandling the externalHandling to set
149     */
150    protected void setExternalHandling(final String externalHandling) {
151        this.externalHandling = externalHandling;
152    }
153
154    /**
155     * @param externalUrl the externalUrl to set
156     */
157    protected void setExternalUrl(final String externalUrl) {
158        this.externalUrl = externalUrl;
159    }
160
161    /**
162     * @param contentSize the contentSize to set
163     */
164    protected void setContentSize(final Long contentSize) {
165        this.contentSize = contentSize;
166    }
167
168    /**
169     * @param filename the filename to set
170     */
171    protected void setFilename(final String filename) {
172        this.filename = filename;
173    }
174
175    /**
176     * @param mimeType the mimeType to set
177     */
178    protected void setMimeType(final String mimeType) {
179        this.mimeType = mimeType;
180    }
181
182    /**
183     * @param digests the digests to set
184     */
185    protected void setDigests(final Collection<URI> digests) {
186        this.digests = digests;
187    }
188
189    @Override
190    public List<URI> getSystemTypes(final boolean forRdf) {
191        var types = resolveSystemTypes(forRdf);
192
193        if (types == null) {
194            types = super.getSystemTypes(forRdf);
195            // Add fedora:Binary type.
196            types.add(FEDORA_BINARY_URI);
197        }
198
199        return types;
200    }
201}