-
Notifications
You must be signed in to change notification settings - Fork 113
/
GraphQLQueryInvoker.java
135 lines (113 loc) · 6.03 KB
/
GraphQLQueryInvoker.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
package graphql.servlet;
import graphql.ExecutionInput;
import graphql.ExecutionResult;
import graphql.GraphQL;
import graphql.execution.instrumentation.ChainedInstrumentation;
import graphql.execution.instrumentation.Instrumentation;
import graphql.execution.instrumentation.SimpleInstrumentation;
import graphql.execution.instrumentation.dataloader.DataLoaderDispatcherInstrumentation;
import graphql.execution.preparsed.NoOpPreparsedDocumentProvider;
import graphql.execution.preparsed.PreparsedDocumentProvider;
import graphql.schema.GraphQLSchema;
import graphql.servlet.internal.ExecutionResultHandler;
import javax.security.auth.Subject;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.function.Supplier;
/**
* @author Andrew Potter
*/
public class GraphQLQueryInvoker {
private final Supplier<ExecutionStrategyProvider> getExecutionStrategyProvider;
private final Supplier<Instrumentation> getInstrumentation;
private final Supplier<PreparsedDocumentProvider> getPreparsedDocumentProvider;
protected GraphQLQueryInvoker(Supplier<ExecutionStrategyProvider> getExecutionStrategyProvider, Supplier<Instrumentation> getInstrumentation, Supplier<PreparsedDocumentProvider> getPreparsedDocumentProvider) {
this.getExecutionStrategyProvider = getExecutionStrategyProvider;
this.getInstrumentation = getInstrumentation;
this.getPreparsedDocumentProvider = getPreparsedDocumentProvider;
}
public ExecutionResult query(GraphQLSingleInvocationInput singleInvocationInput) {
return query(singleInvocationInput, singleInvocationInput.getExecutionInput());
}
public void query(GraphQLBatchedInvocationInput batchedInvocationInput, ExecutionResultHandler executionResultHandler) {
Iterator<ExecutionInput> executionInputIterator = batchedInvocationInput.getExecutionInputs().iterator();
while (executionInputIterator.hasNext()) {
ExecutionResult result = query(batchedInvocationInput, executionInputIterator.next());
executionResultHandler.accept(result, executionInputIterator.hasNext());
}
}
private GraphQL newGraphQL(GraphQLSchema schema, Object context) {
ExecutionStrategyProvider executionStrategyProvider = getExecutionStrategyProvider.get();
return GraphQL.newGraphQL(schema)
.queryExecutionStrategy(executionStrategyProvider.getQueryExecutionStrategy())
.mutationExecutionStrategy(executionStrategyProvider.getMutationExecutionStrategy())
.subscriptionExecutionStrategy(executionStrategyProvider.getSubscriptionExecutionStrategy())
.instrumentation(getInstrumentation(context))
.preparsedDocumentProvider(getPreparsedDocumentProvider.get())
.build();
}
protected Instrumentation getInstrumentation(Object context) {
if (context instanceof GraphQLContext) {
return ((GraphQLContext) context).getDataLoaderRegistry()
.map(registry -> {
List<Instrumentation> instrumentations = new ArrayList<>();
instrumentations.add(getInstrumentation.get());
instrumentations.add(new DataLoaderDispatcherInstrumentation(registry));
return new ChainedInstrumentation(instrumentations);
})
.map(Instrumentation.class::cast)
.orElse(getInstrumentation.get());
}
return getInstrumentation.get();
}
private ExecutionResult query(GraphQLInvocationInput invocationInput, ExecutionInput executionInput) {
if (Subject.getSubject(AccessController.getContext()) == null && invocationInput.getSubject().isPresent()) {
return Subject.doAs(invocationInput.getSubject().get(), (PrivilegedAction<ExecutionResult>) () -> {
try {
return query(invocationInput.getSchema(), executionInput);
} catch (Exception e) {
throw new RuntimeException(e);
}
});
}
return query(invocationInput.getSchema(), executionInput);
}
private ExecutionResult query(GraphQLSchema schema, ExecutionInput executionInput) {
return newGraphQL(schema, executionInput.getContext()).execute(executionInput);
}
public static Builder newBuilder() {
return new Builder();
}
public static class Builder {
private Supplier<ExecutionStrategyProvider> getExecutionStrategyProvider = DefaultExecutionStrategyProvider::new;
private Supplier<Instrumentation> getInstrumentation = () -> SimpleInstrumentation.INSTANCE;
private Supplier<PreparsedDocumentProvider> getPreparsedDocumentProvider = () -> NoOpPreparsedDocumentProvider.INSTANCE;
public Builder withExecutionStrategyProvider(ExecutionStrategyProvider provider) {
return withExecutionStrategyProvider(() -> provider);
}
public Builder withExecutionStrategyProvider(Supplier<ExecutionStrategyProvider> supplier) {
this.getExecutionStrategyProvider = supplier;
return this;
}
public Builder withInstrumentation(Instrumentation instrumentation) {
return withInstrumentation(() -> instrumentation);
}
public Builder withInstrumentation(Supplier<Instrumentation> supplier) {
this.getInstrumentation = supplier;
return this;
}
public Builder withPreparsedDocumentProvider(PreparsedDocumentProvider provider) {
return withPreparsedDocumentProvider(() -> provider);
}
public Builder withPreparsedDocumentProvider(Supplier<PreparsedDocumentProvider> supplier) {
this.getPreparsedDocumentProvider = supplier;
return this;
}
public GraphQLQueryInvoker build() {
return new GraphQLQueryInvoker(getExecutionStrategyProvider, getInstrumentation, getPreparsedDocumentProvider);
}
}
}