001/*-
002 * #%L
003 * HAPI FHIR Storage api
004 * %%
005 * Copyright (C) 2014 - 2024 Smile CDR, Inc.
006 * %%
007 * Licensed under the Apache License, Version 2.0 (the "License");
008 * you may not use this file except in compliance with the License.
009 * You may obtain a copy of the License at
010 *
011 *      http://www.apache.org/licenses/LICENSE-2.0
012 *
013 * Unless required by applicable law or agreed to in writing, software
014 * distributed under the License is distributed on an "AS IS" BASIS,
015 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
016 * See the License for the specific language governing permissions and
017 * limitations under the License.
018 * #L%
019 */
020package ca.uhn.fhir.jpa.binary.api;
021
022import ca.uhn.fhir.rest.api.server.RequestDetails;
023import ca.uhn.fhir.rest.server.servlet.ServletRequestDetails;
024import jakarta.annotation.Nonnull;
025import org.hl7.fhir.instance.model.api.IBaseBinary;
026import org.hl7.fhir.instance.model.api.IIdType;
027
028import java.io.IOException;
029import java.io.InputStream;
030import java.io.OutputStream;
031
032public interface IBinaryStorageSvc {
033
034        /**
035         * Gets the maximum number of bytes that can be stored in a single binary
036         * file by this service. The default is {@link Long#MAX_VALUE}
037         */
038        long getMaximumBinarySize();
039
040        /**
041         * Given a blob ID, return true if it is valid for the underlying storage mechanism, false otherwise.
042         *
043         * @param theNewBlobId the blob ID to validate
044         * @return true if the blob ID is valid, false otherwise.
045         */
046        default boolean isValidBinaryContentId(String theNewBlobId) {
047                return true; // default method here as we don't want to break existing implementations
048        }
049
050        /**
051         * Sets the maximum number of bytes that can be stored in a single binary
052         * file by this service. The default is {@link Long#MAX_VALUE}
053         *
054         * @param theMaximumBinarySize The maximum size
055         */
056        void setMaximumBinarySize(long theMaximumBinarySize);
057
058        /**
059         * Gets the minimum number of bytes that will be stored. Binary content smaller
060         * * than this threshold may be inlined even if a binary storage service
061         * * is active.
062         */
063        int getMinimumBinarySize();
064
065        /**
066         * Sets the minimum number of bytes that will be stored. Binary content smaller
067         * than this threshold may be inlined even if a binary storage service
068         * is active.
069         */
070        void setMinimumBinarySize(int theMinimumBinarySize);
071
072        /**
073         * Give the storage service the ability to veto items from storage
074         *
075         * @param theSize        How large is the item
076         * @param theResourceId  What is the resource ID it will be associated with
077         * @param theContentType What is the content type
078         * @return <code>true</code> if the storage service should store the item
079         */
080        boolean shouldStoreBinaryContent(long theSize, IIdType theResourceId, String theContentType);
081
082        /**
083         * Generate a new binaryContent ID that will be passed to {@link #storeBinaryContent(IIdType, String, String, InputStream)} later
084         */
085        String newBinaryContentId();
086
087        /**
088         * Store a new binary blob
089         *
090         * @param theResourceId   The resource ID that owns this blob. Note that it should not be possible to retrieve a blob without both the resource ID and the blob ID being correct.
091         * @param theBlobIdOrNull If set, forces
092         * @param theContentType  The content type to associate with this blob
093         * @param theInputStream  An InputStream to read from. This method should close the stream when it has been fully consumed.
094         * @return Returns details about the stored data
095         * @deprecated Use {@link #storeBinaryContent(IIdType theResourceId, String theBlobIdOrNull, String theContentType,
096         *      InputStream theInputStream, RequestDetails theRequestDetails)} instead. This method
097         *      will be removed because it doesn't receive the 'theRequestDetails' parameter it needs to forward to the pointcut)
098         */
099        @Deprecated(since = "6.6.0", forRemoval = true)
100        @Nonnull
101        default StoredDetails storeBinaryContent(
102                        IIdType theResourceId, String theBlobIdOrNull, String theContentType, InputStream theInputStream)
103                        throws IOException {
104                return storeBinaryContent(
105                                theResourceId, theBlobIdOrNull, theContentType, theInputStream, new ServletRequestDetails());
106        }
107
108        /**
109         * Store a new binary blob
110         *
111         * @param theResourceId   The resource ID that owns this blob. Note that it should not be possible to retrieve a blob without both the resource ID and the blob ID being correct.
112         * @param theBlobIdOrNull If set, forces
113         * @param theContentType  The content type to associate with this blob
114         * @param theInputStream  An InputStream to read from. This method should close the stream when it has been fully consumed.
115         * @param theRequestDetails The operation request details.
116         * @return Returns details about the stored data
117         */
118        @Nonnull
119        StoredDetails storeBinaryContent(
120                        IIdType theResourceId,
121                        String theBlobIdOrNull,
122                        String theContentType,
123                        InputStream theInputStream,
124                        RequestDetails theRequestDetails)
125                        throws IOException;
126
127        StoredDetails fetchBinaryContentDetails(IIdType theResourceId, String theBlobId) throws IOException;
128
129        /**
130         * @return Returns <code>true</code> if the blob was found and written, of <code>false</code> if the blob was not found (i.e. it was expunged or the ID was invalid)
131         */
132        boolean writeBinaryContent(IIdType theResourceId, String theBlobId, OutputStream theOutputStream)
133                        throws IOException;
134
135        void expungeBinaryContent(IIdType theResourceId, String theBlobId);
136
137        /**
138         * Fetch the contents of the given blob
139         *
140         * @param theResourceId The resource ID
141         * @param theBlobId     The blob ID
142         * @return The payload as a byte array
143         */
144        byte[] fetchBinaryContent(IIdType theResourceId, String theBlobId) throws IOException;
145
146        /**
147         * Fetch the byte[] contents of a given Binary resource's `data` element. If the data is a standard base64encoded string that is embedded, return it.
148         * Otherwise, attempt to load the externalized binary blob via the the externalized binary storage service.
149         *
150         * @param theResource The  Binary resource you want to extract data bytes from
151         * @return The binary data blob as a byte array
152         */
153        byte[] fetchDataByteArrayFromBinary(IBaseBinary theResource) throws IOException;
154}