Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mobile
Path: blob/master/src/java.net.http/share/classes/jdk/internal/net/http/PushGroup.java
41171 views
1
/*
2
* Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved.
3
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4
*
5
* This code is free software; you can redistribute it and/or modify it
6
* under the terms of the GNU General Public License version 2 only, as
7
* published by the Free Software Foundation. Oracle designates this
8
* particular file as subject to the "Classpath" exception as provided
9
* by Oracle in the LICENSE file that accompanied this code.
10
*
11
* This code is distributed in the hope that it will be useful, but WITHOUT
12
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14
* version 2 for more details (a copy is included in the LICENSE file that
15
* accompanied this code).
16
*
17
* You should have received a copy of the GNU General Public License version
18
* 2 along with this work; if not, write to the Free Software Foundation,
19
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20
*
21
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22
* or visit www.oracle.com if you need additional information or have any
23
* questions.
24
*/
25
26
package jdk.internal.net.http;
27
28
import java.security.AccessControlContext;
29
import java.util.Objects;
30
import java.util.concurrent.CompletableFuture;
31
import java.net.http.HttpRequest;
32
import java.net.http.HttpResponse;
33
import java.net.http.HttpResponse.BodyHandler;
34
import java.net.http.HttpResponse.PushPromiseHandler;
35
import java.util.concurrent.Executor;
36
37
import jdk.internal.net.http.common.MinimalFuture;
38
import jdk.internal.net.http.common.Log;
39
40
/**
41
* One PushGroup object is associated with the parent Stream of the pushed
42
* Streams. This keeps track of all common state associated with the pushes.
43
*/
44
class PushGroup<T> {
45
private final HttpRequest initiatingRequest;
46
47
final CompletableFuture<Void> noMorePushesCF;
48
49
volatile Throwable error; // any exception that occurred during pushes
50
51
// user's subscriber object
52
final PushPromiseHandler<T> pushPromiseHandler;
53
54
private final Executor executor;
55
56
int numberOfPushes;
57
int remainingPushes;
58
boolean noMorePushes = false;
59
60
PushGroup(PushPromiseHandler<T> pushPromiseHandler,
61
HttpRequestImpl initiatingRequest,
62
Executor executor) {
63
this(pushPromiseHandler, initiatingRequest, new MinimalFuture<>(), executor);
64
}
65
66
// Check mainBodyHandler before calling nested constructor.
67
private PushGroup(HttpResponse.PushPromiseHandler<T> pushPromiseHandler,
68
HttpRequestImpl initiatingRequest,
69
CompletableFuture<HttpResponse<T>> mainResponse,
70
Executor executor) {
71
this.noMorePushesCF = new MinimalFuture<>();
72
this.pushPromiseHandler = pushPromiseHandler;
73
this.initiatingRequest = initiatingRequest;
74
this.executor = executor;
75
}
76
77
interface Acceptor<T> {
78
BodyHandler<T> bodyHandler();
79
CompletableFuture<HttpResponse<T>> cf();
80
boolean accepted();
81
}
82
83
private static class AcceptorImpl<T> implements Acceptor<T> {
84
private final Executor executor;
85
private volatile HttpResponse.BodyHandler<T> bodyHandler;
86
private volatile CompletableFuture<HttpResponse<T>> cf;
87
88
AcceptorImpl(Executor executor) {
89
this.executor = executor;
90
}
91
92
CompletableFuture<HttpResponse<T>> accept(BodyHandler<T> bodyHandler) {
93
Objects.requireNonNull(bodyHandler);
94
if (this.bodyHandler != null)
95
throw new IllegalStateException("non-null bodyHandler");
96
this.bodyHandler = bodyHandler;
97
cf = new MinimalFuture<>();
98
return cf.whenCompleteAsync((r,t) -> {}, executor);
99
}
100
101
@Override public BodyHandler<T> bodyHandler() { return bodyHandler; }
102
103
@Override public CompletableFuture<HttpResponse<T>> cf() { return cf; }
104
105
@Override public boolean accepted() { return cf != null; }
106
}
107
108
Acceptor<T> acceptPushRequest(HttpRequest pushRequest) {
109
AcceptorImpl<T> acceptor = new AcceptorImpl<>(executor);
110
try {
111
pushPromiseHandler.applyPushPromise(initiatingRequest, pushRequest, acceptor::accept);
112
} catch (Throwable t) {
113
if (acceptor.accepted()) {
114
CompletableFuture<?> cf = acceptor.cf();
115
cf.completeExceptionally(t);
116
}
117
throw t;
118
}
119
120
synchronized (this) {
121
if (acceptor.accepted()) {
122
numberOfPushes++;
123
remainingPushes++;
124
}
125
return acceptor;
126
}
127
}
128
129
// This is called when the main body response completes because it means
130
// no more PUSH_PROMISEs are possible
131
132
synchronized void noMorePushes(boolean noMore) {
133
noMorePushes = noMore;
134
checkIfCompleted();
135
noMorePushesCF.complete(null);
136
}
137
138
synchronized CompletableFuture<Void> pushesCF() {
139
return noMorePushesCF;
140
}
141
142
synchronized boolean noMorePushes() {
143
return noMorePushes;
144
}
145
146
synchronized void pushCompleted() {
147
remainingPushes--;
148
checkIfCompleted();
149
}
150
151
synchronized void checkIfCompleted() {
152
if (Log.trace()) {
153
Log.logTrace("PushGroup remainingPushes={0} error={1} noMorePushes={2}",
154
remainingPushes,
155
(error==null)?error:error.getClass().getSimpleName(),
156
noMorePushes);
157
}
158
if (remainingPushes == 0 && error == null && noMorePushes) {
159
if (Log.trace()) {
160
Log.logTrace("push completed");
161
}
162
}
163
}
164
165
synchronized void pushError(Throwable t) {
166
if (t == null) {
167
return;
168
}
169
this.error = t;
170
}
171
}
172
173