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