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.Transaction;
022import org.fcrepo.kernel.api.exception.ItemNotFoundException;
023import org.fcrepo.kernel.api.exception.PathNotFoundException;
024import org.fcrepo.kernel.api.exception.PathNotFoundRuntimeException;
025import org.fcrepo.kernel.api.exception.RepositoryRuntimeException;
026import org.fcrepo.kernel.api.identifiers.FedoraId;
027import org.fcrepo.kernel.api.models.Binary;
028import org.fcrepo.kernel.api.models.ExternalContent;
029import org.fcrepo.kernel.api.models.FedoraResource;
030import org.fcrepo.kernel.api.models.ResourceFactory;
031import org.fcrepo.persistence.api.PersistentStorageSessionManager;
032import org.fcrepo.persistence.api.exceptions.PersistentItemNotFoundException;
033import org.fcrepo.persistence.api.exceptions.PersistentStorageException;
034
035import java.io.IOException;
036import java.io.InputStream;
037import java.net.URI;
038import java.util.Collection;
039import java.util.List;
040
041import static org.fcrepo.kernel.api.RdfLexicon.FEDORA_BINARY;
042import static org.fcrepo.kernel.api.models.ExternalContent.PROXY;
043
044
045/**
046 * Implementation of a Non-RDF resource.
047 *
048 * @author bbpennel
049 */
050public class BinaryImpl extends FedoraResourceImpl implements Binary {
051
052    private static final URI FEDORA_BINARY_URI = URI.create(FEDORA_BINARY.getURI());
053
054    private String externalHandling;
055
056    private String externalUrl;
057
058    private Long contentSize;
059
060    private String filename;
061
062    private String mimeType;
063
064    private Collection<URI> digests;
065
066    /**
067     * Construct the binary
068     *
069     * @param fedoraID fedora identifier
070     * @param transaction transaction
071     * @param pSessionManager session manager
072     * @param resourceFactory resource factory
073     */
074    public BinaryImpl(final FedoraId fedoraID, final Transaction transaction,
075                      final PersistentStorageSessionManager pSessionManager, final ResourceFactory resourceFactory) {
076        super(fedoraID, transaction, pSessionManager, resourceFactory);
077    }
078
079    @Override
080    public InputStream getContent() {
081        try {
082            if (isProxy() || isRedirect()) {
083                return URI.create(getExternalURL()).toURL().openStream();
084            } else {
085                return getSession().getBinaryContent(getFedoraId().asResourceId(), getMementoDatetime());
086            }
087        } catch (final PersistentItemNotFoundException e) {
088            throw new ItemNotFoundException("Unable to find content for " + getId()
089                    + " version " + getMementoDatetime(), e);
090        } catch (final PersistentStorageException | IOException e) {
091            throw new RepositoryRuntimeException(e.getMessage(), e);
092        }
093    }
094
095    @Override
096    public long getContentSize() {
097        return contentSize;
098    }
099
100    @Override
101    public Collection<URI> getContentDigests() {
102        if (digests == null) {
103            return null;
104        }
105        return digests;
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(transaction, descIdAsMemento);
140            }
141            return resourceFactory.getResource(transaction, 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
202    @Override
203    public RdfStream getTriples() {
204        return getDescription().getTriples();
205    }
206}