001// Generated by delombok at Thu Aug 13 13:56:43 UTC 2026
002/*
003 * Copyright (c) 2010-2026 Mark Allen, Norbert Bartels.
004 *
005 * Permission is hereby granted, free of charge, to any person obtaining a copy
006 * of this software and associated documentation files (the "Software"), to deal
007 * in the Software without restriction, including without limitation the rights
008 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
009 * copies of the Software, and to permit persons to whom the Software is
010 * furnished to do so, subject to the following conditions:
011 *
012 * The above copyright notice and this permission notice shall be included in
013 * all copies or substantial portions of the Software.
014 *
015 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
016 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
017 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
018 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
019 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
020 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
021 * THE SOFTWARE.
022 */
023package com.restfb;
024
025import static java.lang.String.format;
026import java.io.ByteArrayInputStream;
027import java.io.IOException;
028import java.io.InputStream;
029import java.net.URLConnection;
030import java.util.function.Supplier;
031import com.restfb.util.ObjectUtil;
032import com.restfb.util.ReflectionUtils;
033
034/**
035 * Represents a binary file that can be uploaded to Facebook.
036 * <p>
037 * Normally this would be a photo or video.
038 *
039 * @author <a href="http://restfb.com">Mark Allen</a>
040 * @author Marcel Stoer
041 * @since 1.6.5
042 */
043public class BinaryAttachment {
044  private static final String FIELD_NAME_CANNOT_BE_NULL = "Field name cannot be null.";
045  private final String filename;
046  protected byte[] data;
047  private Supplier<InputStream> dataSupplier;
048  private String contentType;
049  private String fieldName;
050
051  protected BinaryAttachment() {
052    filename = "default";
053  }
054
055  /**
056   * Creates a new binary attachment backed by a stream supplier.
057   *
058   * @param filename
059   *          The attachment's filename.
060   * @param dataSupplier
061   *          Provides a fresh {@link InputStream} for each access.
062   * @throws IllegalArgumentException
063   *           If {@code dataSupplier} is {@code null} or {@code filename} is {@code null} or blank.
064   */
065  protected BinaryAttachment(String filename, Supplier<InputStream> dataSupplier) {
066    ObjectUtil.requireNotEmpty(filename, "Binary attachment filename cannot be blank.");
067    ObjectUtil.verifyParameterPresence("dataSupplier", dataSupplier);
068    this.filename = filename;
069    this.dataSupplier = dataSupplier;
070  }
071
072  /**
073   * Creates a new binary attachment backed by a stream supplier.
074   *
075   * @param filename
076   *          The attachment's filename.
077   * @param dataSupplier
078   *          Provides a fresh {@link InputStream} for each access.
079   * @param fieldName
080   *          The field name the binary belongs to
081   * @throws IllegalArgumentException
082   *           If {@code dataSupplier} is {@code null} or {@code filename} is {@code null} or blank.
083   */
084  protected BinaryAttachment(String fieldName, String filename, Supplier<InputStream> dataSupplier) {
085    this(filename, dataSupplier);
086    ObjectUtil.requireNotEmpty(fieldName, FIELD_NAME_CANNOT_BE_NULL);
087    this.fieldName = fieldName;
088  }
089
090  public boolean isFacebookReel() {
091    return false;
092  }
093
094  /**
095   * Creates a new binary attachment backed by a stream supplier.
096   *
097   * @param filename
098   *          The attachment's filename.
099   * @param dataSupplier
100   *          Provides a fresh {@link InputStream} for each access.
101   * @param contentType
102   *          The attachment's contentType.
103   * @throws IllegalArgumentException
104   *           If {@code dataSupplier} is {@code null}, {@code filename} is {@code null} or blank, or
105   *           {@code contentType} is {@code null} or blank.
106   * @since 1.6.13
107   */
108  protected BinaryAttachment(String filename, Supplier<InputStream> dataSupplier, String contentType) {
109    this(filename, dataSupplier);
110    ObjectUtil.requireNotEmpty(contentType, "ContentType cannot be null.");
111    this.contentType = contentType;
112  }
113
114  /**
115   * Creates a new binary attachment backed by a stream supplier.
116   *
117   * @param filename
118   *          The attachment's filename.
119   * @param dataSupplier
120   *          Provides a fresh {@link InputStream} for each access.
121   * @param contentType
122   *          The attachment's contentType.
123   * @param fieldName
124   *          The field name the binary belongs to
125   * @throws IllegalArgumentException
126   *           If {@code dataSupplier} is {@code null}, {@code filename} is {@code null} or blank, or
127   *           {@code contentType} is {@code null} or blank.
128   * @since 1.6.13
129   */
130  protected BinaryAttachment(String fieldName, String filename, Supplier<InputStream> dataSupplier, String contentType) {
131    this(filename, dataSupplier, contentType);
132    ObjectUtil.requireNotEmpty(fieldName, FIELD_NAME_CANNOT_BE_NULL);
133    this.fieldName = fieldName;
134  }
135
136  /**
137   * Creates a new binary attachment.
138   *
139   * @param filename
140   *          The attachment's filename.
141   * @param data
142   *          The attachment's data.
143   * @throws IllegalArgumentException
144   *           If {@code data} is {@code null} or {@code filename} is {@code null} or blank.
145   * @since 1.6.17
146   */
147  protected BinaryAttachment(String filename, byte[] data) {
148    ObjectUtil.requireNotEmpty(filename, "Binary attachment filename cannot be blank.");
149    ObjectUtil.verifyParameterPresence("data", data);
150    this.filename = filename;
151    this.data = data;
152  }
153
154  /**
155   * Creates a new binary attachment.
156   *
157   * @param filename
158   *          The attachment's filename.
159   * @param data
160   *          The attachment's data.
161   * @param fieldName
162   *          The field name the binary belongs to
163   * @throws IllegalArgumentException
164   *           If {@code data} is {@code null} or {@code filename} is {@code null} or blank.
165   * @since 1.6.17
166   */
167  protected BinaryAttachment(String fieldName, String filename, byte[] data) {
168    this(filename, data);
169    ObjectUtil.requireNotEmpty(fieldName, FIELD_NAME_CANNOT_BE_NULL);
170    this.fieldName = fieldName;
171  }
172
173  /**
174   * Creates a new binary attachment.
175   *
176   * @param filename
177   *          The attachment's filename.
178   * @param data
179   *          The attachment's data.
180   * @param contentType
181   *          The attachment's contentType.
182   * @throws IllegalArgumentException
183   *           If {@code data} is {@code null}, {@code filename} is {@code null} or blank, or {@code contentType} is
184   *           {@code null} or blank.
185   * @since 1.6.17
186   */
187  protected BinaryAttachment(String filename, byte[] data, String contentType) {
188    this(filename, data);
189    ObjectUtil.requireNotEmpty(contentType, "ContentType cannot be null.");
190    this.contentType = contentType;
191  }
192
193  /**
194   * Creates a new binary attachment.
195   *
196   * @param filename
197   *          The attachment's filename.
198   * @param data
199   *          The attachment's data.
200   * @param contentType
201   *          The attachment's contentType.
202   * @param fieldName
203   *          The field name the binary belongs to
204   * @throws IllegalArgumentException
205   *           If {@code data} is {@code null}, {@code filename} is {@code null} or blank, or {@code contentType} is
206   *           {@code null} or blank.
207   * @since 1.6.17
208   */
209  protected BinaryAttachment(String fieldName, String filename, byte[] data, String contentType) {
210    this(filename, data, contentType);
211    ObjectUtil.requireNotEmpty(fieldName, FIELD_NAME_CANNOT_BE_NULL);
212    this.fieldName = fieldName;
213  }
214
215  /**
216   * Creates a binary attachment backed by a stream supplier.
217   *
218   * @param filename
219   *          The attachment's filename.
220   * @param dataSupplier
221   *          Provides a fresh {@link InputStream} for each access.
222   * @return A binary attachment.
223   * @throws IllegalArgumentException
224   *           If {@code dataSupplier} is {@code null} or {@code filename} is {@code null} or blank.
225   */
226  public static BinaryAttachment with(String filename, Supplier<InputStream> dataSupplier) {
227    return new BinaryAttachment(filename, dataSupplier);
228  }
229
230  /**
231   * Creates a binary attachment backed by a stream supplier.
232   *
233   * @param filename
234   *          The attachment's filename.
235   * @param dataSupplier
236   *          Provides a fresh {@link InputStream} for each access.
237   * @param fieldName
238   *          The field name the binary belongs to
239   * @return A binary attachment.
240   * @throws IllegalArgumentException
241   *           If {@code dataSupplier} is {@code null} or {@code filename} is {@code null} or blank.
242   */
243  public static BinaryAttachment with(String fieldName, String filename, Supplier<InputStream> dataSupplier) {
244    return new BinaryAttachment(fieldName, filename, dataSupplier);
245  }
246
247  /**
248   * Creates a binary attachment backed by a stream supplier.
249   *
250   * @param filename
251   *          The attachment's filename.
252   * @param dataSupplier
253   *          Provides a fresh {@link InputStream} for each access.
254   * @param contentType
255   *          The attachment's contentType.
256   * @return A binary attachment.
257   * @throws IllegalArgumentException
258   *           If {@code dataSupplier} is {@code null} or {@code filename} is {@code null} or blank.
259   */
260  public static BinaryAttachment with(String filename, Supplier<InputStream> dataSupplier, String contentType) {
261    return new BinaryAttachment(filename, dataSupplier, contentType);
262  }
263
264  /**
265   * Creates a binary attachment backed by a stream supplier.
266   *
267   * @param filename
268   *          The attachment's filename.
269   * @param dataSupplier
270   *          Provides a fresh {@link InputStream} for each access.
271   * @param fieldName
272   *          The field name the binary belongs to
273   * @param contentType
274   *          The attachment's contentType.
275   * @return A binary attachment.
276   * @throws IllegalArgumentException
277   *           If {@code dataSupplier} is {@code null} or {@code filename} is {@code null} or blank.
278   */
279  public static BinaryAttachment with(String fieldName, String filename, Supplier<InputStream> dataSupplier, String contentType) {
280    return new BinaryAttachment(fieldName, filename, dataSupplier, contentType);
281  }
282
283  /**
284   * Creates a binary attachment.
285   *
286   * @param filename
287   *          The attachment's filename.
288   * @param data
289   *          The attachment's data.
290   * @return A binary attachment.
291   * @throws IllegalArgumentException
292   *           If {@code data} is {@code null} or {@code filename} is {@code null} or blank.
293   * @since 1.6.17
294   */
295  public static BinaryAttachment with(String filename, byte[] data) {
296    return new BinaryAttachment(filename, data);
297  }
298
299  /**
300   * Creates a binary attachment.
301   *
302   * @param filename
303   *          The attachment's filename.
304   * @param data
305   *          The attachment's data.
306   * @param fieldName
307   *          The field name the binary belongs to
308   * @return A binary attachment.
309   * @throws IllegalArgumentException
310   *           If {@code data} is {@code null} or {@code filename} is {@code null} or blank.
311   * @since 1.6.17
312   */
313  public static BinaryAttachment with(String fieldName, String filename, byte[] data) {
314    return new BinaryAttachment(fieldName, filename, data);
315  }
316
317  /**
318   * Creates a binary attachment.
319   *
320   * @param filename
321   *          The attachment's filename.
322   * @param data
323   *          The attachment's data.
324   * @param contentType
325   *          The attachment's contentType.
326   * @return A binary attachment.
327   * @throws IllegalArgumentException
328   *           If {@code data} is {@code null} or {@code filename} is {@code null} or blank.
329   * @since 1.6.17
330   */
331  public static BinaryAttachment with(String filename, byte[] data, String contentType) {
332    return new BinaryAttachment(filename, data, contentType);
333  }
334
335  /**
336   * Creates a binary attachment.
337   *
338   * @param filename
339   *          The attachment's filename.
340   * @param data
341   *          The attachment's data.
342   * @param contentType
343   *          The attachment's contentType.
344   * @param fieldName
345   *          The field name the binary belongs to
346   * @return A binary attachment.
347   * @throws IllegalArgumentException
348   *           If {@code data} is {@code null} or {@code filename} is {@code null} or blank.
349   * @since 1.6.17
350   */
351  public static BinaryAttachment with(String fieldName, String filename, byte[] data, String contentType) {
352    return new BinaryAttachment(fieldName, filename, data, contentType);
353  }
354
355  @Override
356  public int hashCode() {
357    return ReflectionUtils.hashCode(this);
358  }
359
360  @Override
361  public boolean equals(Object that) {
362    return ReflectionUtils.equals(this, that);
363  }
364
365  @Override
366  public String toString() {
367    return format("[filename=%s]", getFilename());
368  }
369
370  /**
371   * The attachment's data.
372   *
373   * @return The attachment's data.
374   */
375  public InputStream getData() {
376    if (data != null) {
377      return new ByteArrayInputStream(data);
378    } else if (dataSupplier != null) {
379      InputStream stream = dataSupplier.get();
380      ObjectUtil.verifyParameterPresence("dataSupplier result", stream);
381      return stream;
382    } else {
383      throw new IllegalStateException("Either the byte[] or the stream mustn\'t be null at this point.");
384    }
385  }
386
387  /**
388   * return the given content type or try to guess from stream or file name. Depending of the available data.
389   *
390   * @return the content type
391   */
392  public String getContentType() {
393    if (contentType != null) {
394      return contentType;
395    }
396    if (dataSupplier != null) {
397      try (InputStream stream = dataSupplier.get()) {
398        if (stream != null) {
399          contentType = URLConnection.guessContentTypeFromStream(stream);
400        }
401      } catch (IOException ioe) {
402      }
403    }
404    // ignore exception
405    if (data != null) {
406      contentType = URLConnection.getFileNameMap().getContentTypeFor(filename);
407    }
408    // fallback - if we have no contenttype and cannot detect one, use 'application/octet-stream'
409    if (contentType == null) {
410      contentType = "application/octet-stream";
411    }
412    return contentType;
413  }
414
415  public boolean hasBinaryData() {
416    return data != null;
417  }
418
419  /**
420   * Returns the form field name used for multipart uploads.
421   *
422   * @return the explicit field name if set, otherwise the filename without its extension
423   */
424  public String getFormFieldName() {
425    if (fieldName != null) {
426      return fieldName;
427    }
428    String name = getFilename();
429    if (name == null) {
430      return null;
431    }
432    int dotIndex = name.lastIndexOf('.');
433    return dotIndex > 0 ? name.substring(0, dotIndex) : name;
434  }
435
436  @java.lang.SuppressWarnings("all")
437  @lombok.Generated
438  public String getFilename() {
439    return this.filename;
440  }
441
442  @java.lang.SuppressWarnings("all")
443  @lombok.Generated
444  public String getFieldName() {
445    return this.fieldName;
446  }
447}