Skip to content

Commit 03489ba

Browse files
Rework bolt so uncertain operations like creating plugins return Optional
1 parent e965435 commit 03489ba

33 files changed

+268
-142
lines changed

Framework/Bolt/Bolt/src/main/java/org/peakaboo/framework/bolt/plugin/config/BoltConfigPluginDescriptor.java

+14-5
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import java.io.IOException;
44
import java.io.InputStream;
5+
import java.util.Optional;
56
import java.util.Scanner;
67
import java.util.logging.Level;
78

@@ -10,6 +11,7 @@
1011
import org.peakaboo.framework.bolt.plugin.core.PluginDescriptor;
1112
import org.peakaboo.framework.bolt.plugin.core.PluginRegistry;
1213
import org.peakaboo.framework.bolt.plugin.core.container.BoltContainer;
14+
import org.peakaboo.framework.bolt.plugin.core.exceptions.BoltException;
1315

1416
public class BoltConfigPluginDescriptor<T extends BoltConfigPlugin> implements PluginDescriptor<T> {
1517

@@ -20,13 +22,20 @@ public class BoltConfigPluginDescriptor<T extends BoltConfigPlugin> implements P
2022
private PluginRegistry<T> registry;
2123
private int weight = PluginDescriptor.WEIGHT_MEDIUM;
2224

23-
public BoltConfigPluginDescriptor(PluginRegistry<T> registry, BoltConfigPluginBuilder<T> builder, Class<T> pluginClass, BoltConfigContainer<T> container, int weight) {
25+
public BoltConfigPluginDescriptor(PluginRegistry<T> registry, BoltConfigPluginBuilder<T> builder, Class<T> pluginClass, BoltConfigContainer<T> container, int weight) throws BoltException {
2426
this.builder = builder;
2527
this.pluginClass = pluginClass;
2628
this.container = container;
2729
this.registry = registry;
2830
this.weight = weight;
29-
this.reference = create();
31+
32+
var creation = create();
33+
if (creation.isPresent()) {
34+
this.reference = creation.get();
35+
} else {
36+
throw new BoltException("Coult not create reference instance for plugin " + pluginClass.getName());
37+
}
38+
3039
}
3140

3241
@Override
@@ -40,7 +49,7 @@ public Class<T> getPluginClass() {
4049
}
4150

4251
@Override
43-
public T create() {
52+
public Optional<T> create() {
4453

4554
try (InputStream stream = container.openStream()) {
4655

@@ -54,10 +63,10 @@ public T create() {
5463
throw new IOException("Could not read file contents");
5564
}
5665
s.close();
57-
return plugin;
66+
return Optional.of(plugin);
5867
} catch (IOException e) {
5968
Bolt.logger().log(Level.FINE, "Could not create plugin instance: " + container.getSourceName(), e);
60-
return null;
69+
return Optional.empty();
6170
}
6271

6372

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
package org.peakaboo.framework.bolt.plugin.config.container;
2+
3+
import org.peakaboo.framework.bolt.plugin.config.BoltConfigPlugin;
4+
import org.peakaboo.framework.bolt.plugin.core.container.BoltContainer;
5+
import org.peakaboo.framework.bolt.plugin.core.issue.BoltBrokenContainerIssue;
6+
import org.peakaboo.framework.bolt.plugin.java.BoltJavaPlugin;
7+
import org.peakaboo.framework.bolt.plugin.java.container.BoltJarContainer;
8+
9+
public class BoltBrokenConfigfileIssue<T extends BoltConfigPlugin> extends BoltBrokenContainerIssue<T> {
10+
11+
private String message;
12+
13+
public BoltBrokenConfigfileIssue(BoltConfigContainer<T> container, String message) {
14+
super(container);
15+
this.message = message;
16+
}
17+
18+
@Override
19+
public String title() {
20+
return "Broken Configfile Container";
21+
}
22+
23+
@Override
24+
public String description() {
25+
return "Could not read plugin configfile " + shortSource() + ": " + message;
26+
}
27+
28+
}

Framework/Bolt/Bolt/src/main/java/org/peakaboo/framework/bolt/plugin/config/container/BoltConfigContainer.java

+20-5
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import java.io.IOException;
44
import java.io.InputStream;
55
import java.net.URL;
6+
import java.util.ArrayList;
67
import java.util.List;
78

89
import org.peakaboo.framework.bolt.plugin.config.BoltConfigPlugin;
@@ -12,12 +13,18 @@
1213
import org.peakaboo.framework.bolt.plugin.core.PluginDescriptor;
1314
import org.peakaboo.framework.bolt.plugin.core.PluginRegistry;
1415
import org.peakaboo.framework.bolt.plugin.core.container.BoltURLContainer;
16+
import org.peakaboo.framework.bolt.plugin.core.exceptions.BoltException;
1517
import org.peakaboo.framework.bolt.plugin.core.issue.BoltIssue;
1618

19+
/**
20+
* Implementation of the BoltContainer interface which handles loading a
21+
* single config plugin from a file.
22+
*/
1723
public class BoltConfigContainer<T extends BoltConfigPlugin> extends BoltURLContainer<T>{
1824

1925
private BoltPluginSet<T> plugins;
2026
private PluginRegistry<T> manager;
27+
private List<BoltIssue<T>> issues;
2128

2229
public BoltConfigContainer(PluginRegistry<T> manager, URL url, Class<T> pluginClass, BoltConfigPluginBuilder<T> builder, boolean deletable) {
2330
super(url, deletable);
@@ -26,24 +33,32 @@ public BoltConfigContainer(PluginRegistry<T> manager, URL url, Class<T> pluginCl
2633
}
2734
this.url = url;
2835
this.manager = manager;
36+
this.issues = new ArrayList<>();
2937

3038
plugins = new BoltPluginSet<>(manager);
31-
BoltConfigPluginDescriptor<T> plugin = new BoltConfigPluginDescriptor<>(this.manager, builder, pluginClass, this, PluginDescriptor.WEIGHT_MEDIUM);
32-
plugins.addPlugin(plugin);
39+
try {
40+
BoltConfigPluginDescriptor<T> plugin = new BoltConfigPluginDescriptor<>(this.manager, builder, pluginClass, this, PluginDescriptor.WEIGHT_MEDIUM);
41+
plugins.addPlugin(plugin);
42+
} catch (BoltException e) {
43+
issues.add(new BoltBrokenConfigfileIssue<>(this, "Could not load plugin from file"));
44+
}
3345
}
3446

3547
public InputStream openStream() throws IOException {
3648
return url.openStream();
3749
}
3850

3951
@Override
40-
public List<PluginDescriptor<? extends T>> getPlugins() {
52+
public List<PluginDescriptor<T>> getPlugins() {
4153
return plugins.getPlugins();
4254
}
4355

4456
@Override
45-
public List<BoltIssue<? extends T>> getIssues() {
46-
return plugins.getIssues();
57+
public List<BoltIssue<T>> getIssues() {
58+
var list = new ArrayList<BoltIssue<T>>();
59+
list.addAll(plugins.getIssues());
60+
list.addAll(issues);
61+
return list;
4762
}
4863

4964
@Override

Framework/Bolt/Bolt/src/main/java/org/peakaboo/framework/bolt/plugin/core/BoltPluginRegistry.java

+11-11
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import java.util.HashMap;
66
import java.util.List;
77
import java.util.Map;
8+
import java.util.Optional;
89
import java.util.stream.Collectors;
910

1011
import org.peakaboo.framework.bolt.plugin.core.container.BoltContainer;
@@ -77,29 +78,29 @@ public String getAssetPath() {
7778
}
7879

7980
@Override
80-
public final synchronized List<PluginDescriptor<? extends P>> getPlugins() {
81+
public final synchronized List<PluginDescriptor<P>> getPlugins() {
8182
load();
8283
return plugins.getPlugins();
8384
}
8485

8586
@Override
86-
public List<BoltIssue<? extends P>> getIssues() {
87+
public List<BoltIssue<P>> getIssues() {
8788
/*
8889
* Here we not only return the issues generated by containers during loading,
8990
* but we also return issues detected from a higher-level view such as one
9091
* container having only out-of-date plugins, which we can't know until we see
9192
* all the containers at once. This later set is constructed on the fly so that
9293
* we're always generating issues based on the current set of containers.
9394
*/
94-
List<BoltIssue<? extends P>> allIssues = new ArrayList<>();
95+
List<BoltIssue<P>> allIssues = new ArrayList<>();
9596
allIssues.addAll(plugins.getIssues());
9697
allIssues.addAll(findIssues());
9798
return allIssues;
9899
}
99100

100101

101-
private List<BoltIssue<? extends P>> findIssues() {
102-
List<BoltIssue<? extends P>> found = new ArrayList<>();
102+
private List<BoltIssue<P>> findIssues() {
103+
List<BoltIssue<P>> found = new ArrayList<>();
103104

104105
//check if a container contains only outdated plugins
105106
for (BoltContainer<P> container : containers) {
@@ -108,10 +109,10 @@ private List<BoltIssue<? extends P>> findIssues() {
108109
//we're not responsible for detecting empty containers
109110
if (container.isEmpty()) { continue; }
110111

111-
for (PluginDescriptor<? extends P> plugin : container.getPlugins()) {
112+
for (PluginDescriptor<P> plugin : container.getPlugins()) {
112113
//look up the newest version of this plugin by UUID
113-
PluginDescriptor<? extends P> newest = getByUUID(plugin.getUUID());
114-
if (newest.isNewerThan(plugin)) {
114+
Optional<PluginDescriptor<P>> lookup = getByUUID(plugin.getUUID());
115+
if (lookup.isPresent() && lookup.get().isNewerThan(plugin)) {
115116
outdated = true;
116117
}
117118
}
@@ -125,9 +126,8 @@ private List<BoltIssue<? extends P>> findIssues() {
125126

126127

127128
@Override
128-
@SuppressWarnings("unchecked")
129-
public void addLoader(BoltLoader<? extends P> loader) {
130-
loaders.add((BoltLoader<P>) loader);
129+
public void addLoader(BoltLoader<P> loader) {
130+
loaders.add(loader);
131131
}
132132

133133
private List<BoltManagedLoader<P>> managedLoaders() {

Framework/Bolt/Bolt/src/main/java/org/peakaboo/framework/bolt/plugin/core/BoltPluginSet.java

+12-11
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,8 @@
1414
public class BoltPluginSet<T extends BoltPlugin> implements PluginCollection<T> {
1515

1616
//Anything modifying this plugins list should call sort() afterwards
17-
private ArrayList<PluginDescriptor<? extends T>> plugins = new ArrayList<>();
18-
private ArrayList<BoltIssue<? extends T>> issues = new ArrayList<>();
17+
private ArrayList<PluginDescriptor<T>> plugins = new ArrayList<>();
18+
private ArrayList<BoltIssue<T>> issues = new ArrayList<>();
1919

2020
private PluginRegistry<T> manager;
2121

@@ -24,19 +24,20 @@ public BoltPluginSet(PluginRegistry<T> manager) {
2424
}
2525

2626
@Override
27-
public List<PluginDescriptor<? extends T>> getPlugins() {
27+
public List<PluginDescriptor<T>> getPlugins() {
2828
return Collections.unmodifiableList(plugins);
2929
}
3030

31-
public void addPlugin(PluginDescriptor<? extends T> plugin) {
31+
public void addPlugin(PluginDescriptor<T> plugin) {
3232
if (plugins.contains(plugin)) {
3333
return;
3434
}
3535
String uuid = plugin.getUUID();
36-
if (this.hasUUID(uuid)) {
36+
var lookup = this.getByUUID(uuid);
37+
if (lookup.isPresent()) {
3738
//there is already a plugin with the same UUID.
3839
//we have to choose which of these to load
39-
PluginDescriptor<? extends T> existingPlugin = this.getByUUID(uuid);
40+
PluginDescriptor<T> existingPlugin = lookup.get();
4041

4142
if (plugin.isUpgradeFor(existingPlugin)) {
4243
plugins.remove(existingPlugin);
@@ -54,24 +55,24 @@ public void addPlugin(PluginDescriptor<? extends T> plugin) {
5455

5556
}
5657

57-
public void loadFrom(PluginCollection<? extends T> pluginset) {
58-
for (PluginDescriptor<? extends T> t : pluginset.getPlugins()) {
58+
public void loadFrom(PluginCollection<T> pluginset) {
59+
for (var t : pluginset.getPlugins()) {
5960
addPlugin(t);
6061
}
61-
for (BoltIssue<? extends T> i : pluginset.getIssues()) {
62+
for (var i : pluginset.getIssues()) {
6263
addIssue(i);
6364
}
6465
}
6566

6667

6768

68-
public List<BoltIssue<? extends T>> getIssues() {
69+
public List<BoltIssue<T>> getIssues() {
6970
return Collections.unmodifiableList(issues);
7071
}
7172

7273

7374

74-
public void addIssue(BoltIssue<? extends T> issue) {
75+
public void addIssue(BoltIssue<T> issue) {
7576
issues.add(issue);
7677
}
7778

Framework/Bolt/Bolt/src/main/java/org/peakaboo/framework/bolt/plugin/core/PluginCollection.java

+35-16
Original file line numberDiff line numberDiff line change
@@ -12,34 +12,39 @@
1212
* Interface for exposing a set of {@link BoltPlugin}s and {@link BoltIssue}s
1313
* in a read-only way.
1414
*/
15-
public interface PluginCollection<T extends BoltPlugin> extends Iterable<PluginDescriptor<? extends T>> {
15+
public interface PluginCollection<T extends BoltPlugin> extends Iterable<PluginDescriptor<T>> {
1616

17-
List<PluginDescriptor<? extends T>> getPlugins();
17+
List<PluginDescriptor<T>> getPlugins();
1818

19-
default Iterator<PluginDescriptor<? extends T>> iterator() {
19+
default Iterator<PluginDescriptor<T>> iterator() {
2020
return getPlugins().iterator();
2121
}
2222

23-
List<BoltIssue<? extends T>> getIssues();
23+
List<BoltIssue<T>> getIssues();
2424

2525
default List<T> newInstances() {
26-
List<T> insts = getPlugins().stream().map(p -> p.create()).collect(Collectors.toList());
26+
List<T> insts = getPlugins()
27+
.stream()
28+
.map(p -> p.create())
29+
.filter(Optional::isPresent)
30+
.map(Optional::get)
31+
.collect(Collectors.toList());
2732
Collections.sort(insts, (f1, f2) -> f1.pluginName().compareTo(f1.pluginName()));
2833
return insts;
2934
}
3035

3136
PluginRegistry<T> getManager();
3237

33-
default PluginDescriptor<? extends T> getByUUID(String uuid) {
34-
for (PluginDescriptor<? extends T> plugin : getPlugins()) {
38+
default Optional<PluginDescriptor<T>> getByUUID(String uuid) {
39+
for (PluginDescriptor<T> plugin : getPlugins()) {
3540
if (plugin.getUUID().equals(uuid)) {
36-
return plugin;
41+
return Optional.of(plugin);
3742
}
3843
}
39-
return null;
44+
return Optional.empty();
4045
}
4146

42-
default Optional<PluginDescriptor<? extends T>> getByClass(Class<? extends T> cls) {
47+
default Optional<PluginDescriptor<T>> getByClass(Class<? extends T> cls) {
4348
synchronized(this) {
4449
for (var plugin : getPlugins()) {
4550
if (plugin.getReferenceInstance().getClass().equals(cls)) {
@@ -51,7 +56,7 @@ default Optional<PluginDescriptor<? extends T>> getByClass(Class<? extends T> cl
5156
}
5257

5358
default boolean hasUUID(String uuid) {
54-
return getByUUID(uuid) != null;
59+
return getByUUID(uuid).isPresent();
5560
}
5661

5762
default int size() {
@@ -72,17 +77,31 @@ default boolean isEmpty() {
7277
* @param other the other collection to compare against
7378
* @return true if this collection is a proper upgrade for the other, false otherwise
7479
*/
75-
default boolean isUpgradeFor(PluginCollection<? extends T> other) {
80+
default boolean isUpgradeFor(PluginCollection<T> other) {
7681
//get all the UUIDs from the other plugin set
7782
List<String> otherUUIDs = other.getPlugins().stream().map(p -> p.getUUID()).collect(Collectors.toList());
7883

84+
// For every uuid in THEIR collection, we wee if OUR collection
85+
// also has that uuid. If we do, we must check if OUR matching
86+
// plugin is an upgrade for THEIR plugin
7987
//if this set is missing any of the UUIDs, it's not an upgrade
80-
for (String otherUUID : otherUUIDs) {
81-
if (!this.hasUUID(otherUUID)) {
88+
for (String uuid : otherUUIDs) {
89+
90+
// Try to get OUR plugin for this uuid
91+
var ourLookup = this.getByUUID(uuid);
92+
if (ourLookup.isEmpty()) {
8293
return false;
8394
}
84-
boolean isUpgrade = this.getByUUID(otherUUID).isUpgradeFor(other.getByUUID(otherUUID));
85-
if (!isUpgrade) {
95+
var ourPlugin = ourLookup.get();
96+
97+
// Try to get THEIR plugin for this uuid
98+
var theirLookup = other.getByUUID(uuid);
99+
if (theirLookup.isEmpty()) {
100+
return false;
101+
}
102+
var theirPlugin = theirLookup.get();
103+
104+
if ( ! ourPlugin.isUpgradeFor(theirPlugin) ) {
86105
return false;
87106
}
88107
}

0 commit comments

Comments
 (0)