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