001/* 002 * Copyright 2022-2026 Revetware LLC. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016 017package com.soklet; 018 019import org.jspecify.annotations.NonNull; 020import org.jspecify.annotations.Nullable; 021 022import java.io.IOException; 023import java.util.Optional; 024 025import static java.lang.String.format; 026import static java.util.Objects.requireNonNull; 027 028/** 029 * Thrown when a response stream has been canceled. 030 * 031 * @author <a href="https://www.revetkn.com">Mark Allen</a> 032 */ 033public class StreamingResponseCanceledException extends IOException { 034 private static final long serialVersionUID = 1L; 035 036 @NonNull 037 private final StreamTerminationReason cancelationReason; 038 039 /** 040 * Creates an exception with the given cancelation reason. 041 * 042 * @param cancelationReason the cancelation reason 043 */ 044 public StreamingResponseCanceledException(@NonNull StreamTerminationReason cancelationReason) { 045 this(cancelationReason, null); 046 } 047 048 /** 049 * Creates an exception with the given cancelation reason and cause. 050 * 051 * @param cancelationReason the cancelation reason 052 * @param cancelationCause the underlying cause, or {@code null} if unavailable 053 */ 054 public StreamingResponseCanceledException(@NonNull StreamTerminationReason cancelationReason, 055 @Nullable Throwable cancelationCause) { 056 super(format("Streaming response was canceled: %s", requireNonNull(cancelationReason).name()), cancelationCause); 057 if (cancelationReason == StreamTerminationReason.COMPLETED) 058 throw new IllegalArgumentException("Cancelation reason cannot be COMPLETED"); 059 this.cancelationReason = cancelationReason; 060 } 061 062 /** 063 * The cancelation reason. 064 * 065 * @return the cancelation reason 066 */ 067 @NonNull 068 public StreamTerminationReason getCancelationReason() { 069 return this.cancelationReason; 070 } 071 072 /** 073 * The underlying cancelation cause, if available. 074 * 075 * @return the underlying cancelation cause 076 */ 077 @NonNull 078 public Optional<Throwable> getCancelationCause() { 079 return Optional.ofNullable(getCause()); 080 } 081}