-
-
Notifications
You must be signed in to change notification settings - Fork 9.8k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Signed-off-by: John Niang <[email protected]>
- Loading branch information
Showing
4 changed files
with
126 additions
and
156 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
110 changes: 110 additions & 0 deletions
110
application/src/main/java/run/halo/app/theme/finders/DefaultFinderRegistry.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,110 @@ | ||
package run.halo.app.theme.finders; | ||
|
||
import java.util.ArrayList; | ||
import java.util.List; | ||
import java.util.Map; | ||
import java.util.concurrent.ConcurrentHashMap; | ||
import org.springframework.beans.factory.InitializingBean; | ||
import org.springframework.context.ApplicationContext; | ||
import org.springframework.stereotype.Component; | ||
|
||
/** | ||
* Finder registry for class annotated with {@link Finder}. | ||
* | ||
* @author guqing | ||
* @since 2.0.0 | ||
*/ | ||
@Component | ||
public class DefaultFinderRegistry implements FinderRegistry, InitializingBean { | ||
private final Map<String, List<String>> pluginFindersLookup = new ConcurrentHashMap<>(); | ||
private final Map<String, Object> finders = new ConcurrentHashMap<>(64); | ||
|
||
private final ApplicationContext applicationContext; | ||
|
||
public DefaultFinderRegistry(ApplicationContext applicationContext) { | ||
this.applicationContext = applicationContext; | ||
} | ||
|
||
Object get(String name) { | ||
return finders.get(name); | ||
} | ||
|
||
/** | ||
* Given a name, register a Finder for it. | ||
* | ||
* @param name the canonical name | ||
* @param finder the finder to be registered | ||
* @throws IllegalStateException if the name is already existing | ||
*/ | ||
void putFinder(String name, Object finder) { | ||
if (finders.containsKey(name)) { | ||
throw new IllegalStateException( | ||
"Finder with name '" + name + "' is already registered"); | ||
} | ||
finders.put(name, finder); | ||
} | ||
|
||
/** | ||
* Register a finder. | ||
* | ||
* @param finder register a finder that annotated with {@link Finder} | ||
* @return the name of the finder | ||
*/ | ||
String putFinder(Object finder) { | ||
var name = getFinderName(finder); | ||
this.putFinder(name, finder); | ||
return name; | ||
} | ||
|
||
private String getFinderName(Object finder) { | ||
var annotation = finder.getClass().getAnnotation(Finder.class); | ||
if (annotation == null) { | ||
// should never happen | ||
throw new IllegalStateException("Finder must be annotated with @Finder"); | ||
} | ||
String name = annotation.value(); | ||
if (name == null) { | ||
name = finder.getClass().getSimpleName(); | ||
} | ||
return name; | ||
} | ||
|
||
public void removeFinder(String name) { | ||
finders.remove(name); | ||
} | ||
|
||
public Map<String, Object> getFinders() { | ||
return Map.copyOf(finders); | ||
} | ||
|
||
@Override | ||
public void afterPropertiesSet() { | ||
// initialize finders from application context | ||
applicationContext.getBeansWithAnnotation(Finder.class) | ||
.forEach((beanName, finder) -> { | ||
var finderName = getFinderName(finder); | ||
this.putFinder(finderName, finder); | ||
}); | ||
} | ||
|
||
@Override | ||
public void register(String pluginId, ApplicationContext pluginContext) { | ||
pluginContext.getBeansWithAnnotation(Finder.class) | ||
.forEach((beanName, finder) -> { | ||
var finderName = getFinderName(finder); | ||
this.putFinder(finderName, finder); | ||
pluginFindersLookup | ||
.computeIfAbsent(pluginId, ignored -> new ArrayList<>()) | ||
.add(finderName); | ||
}); | ||
} | ||
|
||
@Override | ||
public void unregister(String pluginId) { | ||
var finderNames = pluginFindersLookup.remove(pluginId); | ||
if (finderNames != null) { | ||
finderNames.forEach(finders::remove); | ||
} | ||
} | ||
|
||
} |
136 changes: 4 additions & 132 deletions
136
application/src/main/java/run/halo/app/theme/finders/FinderRegistry.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,148 +1,20 @@ | ||
package run.halo.app.theme.finders; | ||
|
||
import java.util.ArrayList; | ||
import java.util.List; | ||
import java.util.Map; | ||
import java.util.concurrent.ConcurrentHashMap; | ||
import org.springframework.beans.factory.InitializingBean; | ||
import org.springframework.context.ApplicationContext; | ||
import org.springframework.context.event.EventListener; | ||
import org.springframework.stereotype.Component; | ||
import run.halo.app.plugin.SpringPlugin; | ||
import run.halo.app.plugin.event.HaloPluginStartedEvent; | ||
import run.halo.app.plugin.event.HaloPluginStoppedEvent; | ||
|
||
/** | ||
* Finder registry for class annotated with {@link Finder}. | ||
* | ||
* @author guqing | ||
* @since 2.0.0 | ||
*/ | ||
@Component | ||
public class FinderRegistry implements InitializingBean { | ||
private final Map<String, List<String>> pluginFindersLookup = new ConcurrentHashMap<>(); | ||
private final Map<String, Object> finders = new ConcurrentHashMap<>(64); | ||
public interface FinderRegistry { | ||
|
||
private final ApplicationContext applicationContext; | ||
Map<String, Object> getFinders(); | ||
|
||
public FinderRegistry(ApplicationContext applicationContext) { | ||
this.applicationContext = applicationContext; | ||
} | ||
void register(String pluginId, ApplicationContext pluginContext); | ||
|
||
Object get(String name) { | ||
return finders.get(name); | ||
} | ||
void unregister(String pluginId); | ||
|
||
/** | ||
* Given a name, register a Finder for it. | ||
* | ||
* @param name the canonical name | ||
* @param finder the finder to be registered | ||
* @throws IllegalStateException if the name is already existing | ||
*/ | ||
public void registerFinder(String name, Object finder) { | ||
if (finders.containsKey(name)) { | ||
throw new IllegalStateException( | ||
"Finder with name '" + name + "' is already registered"); | ||
} | ||
finders.put(name, finder); | ||
} | ||
|
||
/** | ||
* Register a finder. | ||
* | ||
* @param finder register a finder that annotated with {@link Finder} | ||
* @return the name of the finder | ||
*/ | ||
public String registerFinder(Object finder) { | ||
Finder annotation = finder.getClass().getAnnotation(Finder.class); | ||
if (annotation == null) { | ||
throw new IllegalStateException("Finder must be annotated with @Finder"); | ||
} | ||
String name = annotation.value(); | ||
if (name == null) { | ||
name = finder.getClass().getSimpleName(); | ||
} | ||
this.registerFinder(name, finder); | ||
return name; | ||
} | ||
|
||
public void removeFinder(String name) { | ||
finders.remove(name); | ||
} | ||
|
||
public Map<String, Object> getFinders() { | ||
return Map.copyOf(finders); | ||
} | ||
|
||
@Override | ||
public void afterPropertiesSet() throws Exception { | ||
// initialize finders from application context | ||
applicationContext.getBeansWithAnnotation(Finder.class) | ||
.forEach((k, v) -> { | ||
registerFinder(v); | ||
}); | ||
} | ||
|
||
/** | ||
* Register finders for a plugin. | ||
* | ||
* @param event plugin started event | ||
*/ | ||
@EventListener(HaloPluginStartedEvent.class) | ||
public void onPluginStarted(HaloPluginStartedEvent event) { | ||
var plugin = event.getPlugin().getPlugin(); | ||
var pluginId = event.getPlugin().getPluginId(); | ||
if (plugin instanceof SpringPlugin springPlugin) { | ||
var context = springPlugin.getApplicationContext(); | ||
context.getBeansWithAnnotation(Finder.class) | ||
.forEach((beanName, finderObject) -> { | ||
// register finder | ||
String finderName = registerFinder(finderObject); | ||
// add to plugin finder lookup | ||
pluginFindersLookup.computeIfAbsent(pluginId, k -> new ArrayList<>()) | ||
.add(finderName); | ||
}); | ||
} | ||
} | ||
|
||
/** | ||
* Remove finders registered by the plugin. | ||
* | ||
* @param event plugin stopped event | ||
*/ | ||
@EventListener(HaloPluginStoppedEvent.class) | ||
public void onPluginStopped(HaloPluginStoppedEvent event) { | ||
String pluginId = event.getPlugin().getPluginId(); | ||
boolean containsKey = pluginFindersLookup.containsKey(pluginId); | ||
if (!containsKey) { | ||
return; | ||
} | ||
pluginFindersLookup.get(pluginId).forEach(this::removeFinder); | ||
} | ||
|
||
public void register(String pluginId, ApplicationContext pluginContext) { | ||
pluginContext.getBeansWithAnnotation(Finder.class) | ||
.forEach((beanName, finder) -> { | ||
var finderName = registerFinder(finder); | ||
pluginFindersLookup.computeIfAbsent(pluginId, igored -> new ArrayList<>()) | ||
.add(finderName); | ||
}); | ||
} | ||
|
||
public void unregister(String pluginId) { | ||
pluginFindersLookup.getOrDefault(pluginId, List.of()) | ||
.forEach(this::removeFinder); | ||
} | ||
|
||
/** | ||
* Only for test. | ||
* | ||
* @param pluginId plugin id | ||
* @param finderName finder name | ||
*/ | ||
void addPluginFinder(String pluginId, String finderName) { | ||
pluginFindersLookup.computeIfAbsent(pluginId, k -> new ArrayList<>()) | ||
.add(finderName); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters