forked from halo-dev/halo
-
Notifications
You must be signed in to change notification settings - Fork 1
/
DefaultExtensionGetter.java
109 lines (97 loc) · 4.68 KB
/
DefaultExtensionGetter.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
package run.halo.app.plugin.extensionpoint;
import java.util.Comparator;
import java.util.List;
import java.util.Set;
import java.util.stream.Stream;
import lombok.RequiredArgsConstructor;
import org.pf4j.ExtensionPoint;
import org.springframework.context.ApplicationContext;
import org.springframework.core.annotation.AnnotationAwareOrderComparator;
import org.springframework.lang.NonNull;
import org.springframework.stereotype.Component;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import run.halo.app.extension.ReactiveExtensionClient;
import run.halo.app.infra.SystemConfigurableEnvironmentFetcher;
import run.halo.app.infra.SystemSetting.ExtensionPointEnabled;
import run.halo.app.plugin.HaloPluginManager;
@Component
@RequiredArgsConstructor
public class DefaultExtensionGetter implements ExtensionGetter {
private final SystemConfigurableEnvironmentFetcher systemConfigFetcher;
private final HaloPluginManager pluginManager;
private final ApplicationContext applicationContext;
private final ReactiveExtensionClient client;
@Override
public <T extends ExtensionPoint> Mono<T> getEnabledExtension(Class<T> extensionPoint) {
return systemConfigFetcher.fetch(ExtensionPointEnabled.GROUP, ExtensionPointEnabled.class)
.switchIfEmpty(Mono.just(ExtensionPointEnabled.EMPTY))
.mapNotNull(enabled -> {
var implClassNames = enabled.getOrDefault(extensionPoint.getName(), Set.of());
List<T> allExtensions = getAllExtensions(extensionPoint);
if (allExtensions.isEmpty()) {
return null;
}
return allExtensions
.stream()
.filter(impl -> implClassNames.contains(impl.getClass().getName()))
.findFirst()
// Fallback to local implementation of the extension point.
// This will happen when no proper configuration is found.
.orElseGet(() -> allExtensions.get(0));
});
}
@Override
public <T extends ExtensionPoint> Flux<T> getEnabledExtensions(Class<T> extensionPoint) {
return systemConfigFetcher.fetch(ExtensionPointEnabled.GROUP, ExtensionPointEnabled.class)
.switchIfEmpty(Mono.just(ExtensionPointEnabled.EMPTY))
.flatMapMany(enabled -> {
var implClassNames = enabled.getOrDefault(extensionPoint.getName(), Set.of());
var extensions = pluginManager.getExtensions(extensionPoint)
.stream()
.filter(impl -> implClassNames.contains(impl.getClass().getName()))
.toList();
if (extensions.isEmpty()) {
extensions = applicationContext.getBeanProvider(extensionPoint)
.orderedStream()
// we only fetch one implementation here
.limit(1)
.toList();
}
return Flux.fromIterable(extensions);
});
}
@Override
public <T extends ExtensionPoint> Flux<T> getEnabledExtensionByDefinition(
Class<T> extensionPoint) {
return fetchExtensionPointDefinition(extensionPoint)
.flatMapMany(extensionPointDefinition -> {
ExtensionPointDefinition.ExtensionPointType type =
extensionPointDefinition.getSpec().getType();
if (type == ExtensionPointDefinition.ExtensionPointType.SINGLETON) {
return getEnabledExtension(extensionPoint).flux();
}
// TODO If the type is sortable, may need to process the returned order.
return Flux.fromIterable(getAllExtensions(extensionPoint));
});
}
@NonNull
<T extends ExtensionPoint> List<T> getAllExtensions(Class<T> extensionPoint) {
Stream<T> pluginExtsStream = pluginManager.getExtensions(extensionPoint)
.stream();
Stream<T> systemExtsStream = applicationContext.getBeanProvider(extensionPoint)
.orderedStream();
return Stream.concat(systemExtsStream, pluginExtsStream)
.sorted(new AnnotationAwareOrderComparator())
.toList();
}
Mono<ExtensionPointDefinition> fetchExtensionPointDefinition(
Class<? extends ExtensionPoint> extensionPoint) {
// TODO Optimize query
return client.list(ExtensionPointDefinition.class, definition ->
extensionPoint.getName().equals(definition.getSpec().getClassName()),
Comparator.comparing(definition -> definition.getMetadata().getCreationTimestamp())
)
.next();
}
}