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 Collection<URI> getContentDigests() {
101        if (digests == null) {
102            return null;
103        }
104        return digests;
105    }
106
107    @Override
108    public Boolean isProxy() {
109        return PROXY.equals(externalHandling);
110    }
111
112    @Override
113    public Boolean isRedirect() {
114        return ExternalContent.REDIRECT.equals(externalHandling);
115    }
116
117    @Override
118    public String getExternalURL() {
119        return externalUrl;
120    }
121
122    @Override
123    public String getMimeType() {
124        return mimeType;
125    }
126
127    @Override
128    public String getFilename() {
129        return filename;
130    }
131
132    @Override
133    public FedoraResource getDescription() {
134        try {
135            final FedoraId descId = getFedoraId().asDescription();
136            if (this.isMemento()) {
137                final var descIdAsMemento = descId.asMemento(getMementoDatetime());
138                return resourceFactory.getResource(txId, descIdAsMemento);
139            }
140            return resourceFactory.getResource(txId, descId);
141        } catch (final PathNotFoundException e) {
142            throw new PathNotFoundRuntimeException(e.getMessage(), e);
143        }
144    }
145
146    /**
147     * @param externalHandling the externalHandling to set
148     */
149    protected void setExternalHandling(final String externalHandling) {
150        this.externalHandling = externalHandling;
151    }
152
153    /**
154     * @param externalUrl the externalUrl to set
155     */
156    protected void setExternalUrl(final String externalUrl) {
157        this.externalUrl = externalUrl;
158    }
159
160    /**
161     * @param contentSize the contentSize to set
162     */
163    protected void setContentSize(final Long contentSize) {
164        this.contentSize = contentSize;
165    }
166
167    /**
168     * @param filename the filename to set
169     */
170    protected void setFilename(final String filename) {
171        this.filename = filename;
172    }
173
174    /**
175     * @param mimeType the mimeType to set
176     */
177    protected void setMimeType(final String mimeType) {
178        this.mimeType = mimeType;
179    }
180
181    /**
182     * @param digests the digests to set
183     */
184    protected void setDigests(final Collection<URI> digests) {
185        this.digests = digests;
186    }
187
188    @Override
189    public List<URI> getSystemTypes(final boolean forRdf) {
190        var types = resolveSystemTypes(forRdf);
191
192        if (types == null) {
193            types = super.getSystemTypes(forRdf);
194            // Add fedora:Binary type.
195            types.add(FEDORA_BINARY_URI);
196        }
197
198        return types;
199    }
200
201    @Override
202    public RdfStream getTriples() {
203        return getDescription().getTriples();
204    }
205}