
net.dongliu.cute.http.body.AggregateBodyPublisher Maven / Gradle / Ivy
The newest version!
package net.dongliu.cute.http.body;
import java.net.http.HttpRequest.BodyPublisher;
import java.nio.ByteBuffer;
import java.util.List;
import java.util.concurrent.Flow.Subscriber;
import java.util.concurrent.Flow.Subscription;
/**
* Aggregate multi BodyPublisher into One.
*/
class AggregateBodyPublisher implements BodyPublisher {
private final BodyPublisher[] publishers;
private final long len;
AggregateBodyPublisher(List publishers) {
this.publishers = publishers.toArray(BodyPublisher[]::new);
this.len = accumulateLen(publishers);
}
private static long accumulateLen(List publishers) {
int len = 0;
for (var publisher : publishers) {
if (publisher.contentLength() < 0) {
return -1;
}
len += publisher.contentLength();
}
return len;
}
@Override
public long contentLength() {
return len;
}
@Override
public void subscribe(Subscriber super ByteBuffer> subscriber) {
var aggregateSubscription = new AggregateSubscription(publishers, subscriber);
subscriber.onSubscribe(aggregateSubscription);
}
private static class AggregateSubscription implements Subscription {
private final BodyPublisher[] publishers;
private final Subscriber super ByteBuffer> subscriber;
private final SubscriberAdapter subscriberAdapter;
private Subscription currentSubscription;
private long requestCount = 0;
private int index = 0;
private AggregateSubscription(BodyPublisher[] publishers, Subscriber super ByteBuffer> subscriber) {
this.publishers = publishers;
this.subscriber = subscriber;
this.subscriberAdapter = this.new SubscriberAdapter();
publishers[0].subscribe(subscriberAdapter);
}
@Override
public void request(long n) {
synchronized (this) {
requestCount += n;
currentSubscription.request(n);
}
}
@Override
public void cancel() {
synchronized (this) {
currentSubscription.cancel();
}
}
private class SubscriberAdapter implements Subscriber {
private SubscriberAdapter() {
}
@Override
public void onSubscribe(Subscription subscription) {
synchronized (AggregateSubscription.this) {
currentSubscription = subscription;
}
}
@Override
public void onNext(ByteBuffer item) {
synchronized (AggregateSubscription.this) {
requestCount--;
}
subscriber.onNext(item);
}
@Override
public void onError(Throwable throwable) {
subscriber.onError(throwable);
}
@Override
public void onComplete() {
synchronized (AggregateSubscription.this) {
index++;
if (index == publishers.length) {
subscriber.onComplete();
} else {
var bodyPublisher = publishers[index];
bodyPublisher.subscribe(this);
if (requestCount > 0) {
currentSubscription.request(requestCount);
requestCount = 0;
}
}
}
}
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy