Added ability to disable plugins, and renamed object iterator to singleton iterator.

This commit is contained in:
Ziver Koc 2020-06-25 19:05:12 +02:00
parent 57bd478e16
commit ef42d8aa6c
3 changed files with 163 additions and 47 deletions

View file

@ -115,7 +115,7 @@ public class MulticastDnsServer extends ThreadedUDPNetwork implements ThreadedUD
DnsPacket dnsPacket = DnsPacket.read(in);
// Just handle queries and no responses
if ( ! dnsPacket.getHeader().flagQueryResponse){
if ( ! dnsPacket.getHeader().flagQueryResponse) {
DnsPacket response = handleReceivedPacket(dnsPacket);
if (response != null){
ByteArrayOutputStream outBuffer = new ByteArrayOutputStream();
@ -140,12 +140,15 @@ public class MulticastDnsServer extends ThreadedUDPNetwork implements ThreadedUD
response.getHeader().setDefaultResponseData();
for (DnsPacketQuestion question : request.getQuestions()){
if (question.name == null) continue;
switch (question.type){
switch (question.type){
// Normal Domain Name Resolution
case DnsConstants.TYPE.A:
if (entries.containsKey(question.name)){
logger.finer("Received request for domain: " + question.name);
response.addAnswerRecord(entries.get(question.name));
} else {
logger.finest("Received request for unknown domain: " + question.name);
}
break;
@ -154,19 +157,31 @@ public class MulticastDnsServer extends ThreadedUDPNetwork implements ThreadedUD
if (question.name.startsWith("_service.")){
String postFix = question.name.substring(9);
for (String domain : entries.keySet()){
if (domain.endsWith(postFix))
if (domain.endsWith(postFix)) {
logger.finer("Received request for service: " + question.name);
response.addAnswerRecord(entries.get(domain));
} else {
logger.finest("Received request for unknown service: " + question.name);
}
}
} else if (entries.containsKey(question.name)){
logger.finer("Received request for service: " + question.name);
response.addAnswerRecord(entries.get(question.name));
} else {
logger.finer("Received request for unknown pointer: " + question.name);
}
break;
default:
logger.finest("Unknown request type: " + question.type);
}
}
if (response.getAnswerRecords().isEmpty() &&
response.getNameServers().isEmpty() &&
response.getAdditionalRecords().isEmpty())
response.getAdditionalRecords().isEmpty()) {
return null;
}
return response;
}
}

View file

@ -27,7 +27,6 @@ package zutil.plugin;
import zutil.log.LogUtil;
import zutil.parser.DataNode;
import java.net.MalformedURLException;
import java.util.*;
import java.util.logging.Level;
import java.util.logging.Logger;
@ -43,6 +42,7 @@ public class PluginData {
private double pluginVersion;
private String pluginName;
private boolean enabled = true;
private HashMap<Class<?>, List<Class<?>>> classMap;
private HashMap<Class, Object> objectMap;
@ -97,19 +97,44 @@ public class PluginData {
}
/**
* @return a version number for the plugin (specified in the plugin.json file
*/
public double getVersion(){
return pluginVersion;
}
/**
* @return the name of the plugin
*/
public String getName(){
return pluginName;
}
/**
* @return if this plugin is enabled
*/
public boolean isEnabled(){
return enabled;
}
/**
* Enables or disables this plugin
*/
public void setEnabled(boolean enabled){
this.enabled = enabled;
}
/**
* @return a Iterator for all singleton Object instance that implement the specified interface
*/
public <T> Iterator<T> getObjectIterator(Class<T> intf){
if(!classMap.containsKey(intf))
return Collections.emptyIterator();
return new PluginObjectIterator<>(classMap.get(intf).iterator());
return new PluginSingletonIterator<>(classMap.get(intf).iterator());
}
/**
* @return a Iterator for all classes implementing the interface by the plugin
*/
public Iterator<Class<?>> getClassIterator(Class<?> intf){
if(!classMap.containsKey(intf))
return Collections.emptyIterator();
@ -122,27 +147,32 @@ public class PluginData {
objectMap.put(objClass, objClass.newInstance());
return (T) objectMap.get(objClass);
} catch (Exception e) {
log.log(Level.WARNING, null, e);
log.log(Level.WARNING, "Unable to instantiate plugin class: " + objClass, e);
}
return null;
}
/**
* @return true if the specified interface is defined by the plugin
*/
public boolean contains(Class<?> intf){
return classMap.containsKey(intf);
}
public String toString(){
return getName()+"(ver: "+getVersion()+")";
return getName()+"(version: "+getVersion()+")";
}
private class PluginObjectIterator<T> implements Iterator<T>{
/**
* A Iterator that goes through all defined classes that implements
* a provided interface and returns a singleton instance of that class
*/
private class PluginSingletonIterator<T> implements Iterator<T>{
private Iterator<Class<?>> classIt;
private T currentObj;
public PluginObjectIterator(Iterator<Class<?>> it) {
public PluginSingletonIterator(Iterator<Class<?>> it) {
classIt = it;
}

View file

@ -31,17 +31,24 @@ import zutil.parser.DataNode;
import zutil.parser.json.JSONParser;
import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.NoSuchElementException;
import java.util.*;
import java.util.logging.Logger;
/**
* This class will search the file system for files
* with the name "plugin.json" that defines data
* parameters for a single plugin.
* The class will only load the latest version of the specific plugin.
* This class will search the file system for files with the name "plugin.json"
* that defines data parameters for a plugin.
* The class will only load the latest version of a specific plugin with the same name.
* <p>
* Example plugin.json content:<pre>
* {
* "version": 1.0,
* "name": "Nice name of Plugin",
* "interfaces": [
* {"plugin.interface.class": "plugin.implementation.class"},
* {"wa.server.plugin.WAFrontend": "wa.server.plugin.apache.ApacheFrontend"}
* ]
* }
* </pre>
*
* @author Ziver
*/
@ -51,13 +58,15 @@ public class PluginManager<T> implements Iterable<PluginData>{
private HashMap<String, PluginData> plugins;
public static <T> PluginManager<T> load(String path){
return new PluginManager<>(path);
}
/**
* Constructor that will look for plugins in the working directory.
*/
public PluginManager(){
this("./");
}
/**
* Constructor that will look for plugins in the specified directory.
*/
public PluginManager(String path){
plugins = new HashMap<>();
@ -71,7 +80,7 @@ public class PluginManager<T> implements Iterable<PluginData>{
for(FileSearcher.FileSearchItem file : search){
try {
DataNode node = JSONParser.read(IOUtil.readContentAsString(file.getInputStream(), true));
log.fine("Found plugin: "+file.getPath());
log.fine("Found plugin: " + file.getPath());
PluginData plugin = new PluginData(node);
if (!plugins.containsKey(plugin.getName())){
@ -93,32 +102,104 @@ public class PluginManager<T> implements Iterable<PluginData>{
}
}
/**
* @return a Iterator of all enabled plugins.
*/
@Override
public Iterator<PluginData> iterator() {
return plugins.values().iterator();
return new EnabledPluginIterator(toList(plugins.values().iterator()));
}
public <K> Iterator<K> getObjectIterator(Class<K> intf) {
return new PluginObjectIterator<>(plugins.values().iterator(), intf);
/**
* @return a Iterator for singleton Objects from all plugins that are enabled and
* has defined implementations of the given interface.
*/
public <K> Iterator<K> getSingletonIterator(Class<K> intf) {
return new PluginSingletonIterator<>(iterator(), intf);
}
/**
* @return a Iterator for classes from all plugins that are enabled and has defined
* implementations of the given interface.
*/
public <K> Iterator<Class<? extends K>> getClassIterator(Class<K> intf) {
return new PluginClassIterator<>(plugins.values().iterator(), intf);
return new PluginClassIterator<>(iterator(), intf);
}
public ArrayList<PluginData> toArray() {
return toGenericArray(iterator());
/**
* @return a Iterator of all plugins, independently on if they are enabled or disabled.
*/
public Iterator<PluginData> iteratorAll() {
return plugins.values().iterator();
}
public <K> ArrayList<K> toArray(Class<K> intf) {
return toGenericArray(getObjectIterator(intf));
/**
* @return a List of enabled plugins.
*/
public List<PluginData> toArray() {
return toList(iterator());
}
private <K> ArrayList<K> toGenericArray(Iterator<K> it) {
/**
* @return a list of enabled plugins that has specified the provided interface in their definition.
*/
public <K> List<K> toArray(Class<K> intf) {
return toList(getSingletonIterator(intf));
}
/**
* @return a List of all plugins, independently on if they are enabled or disabled.
*/
public List<PluginData> toArrayAll() {
return toList(iteratorAll());
}
private <K> List<K> toList(Iterator<K> it) {
ArrayList<K> list = new ArrayList<>();
while(it.hasNext())
list.add(it.next());
return list;
}
/**
* @return the PluginData representing the given plugin by name, returns null if
* there is no plugin by that name.
*/
public PluginData getPluginData(String pluginName) {
return plugins.get(pluginName);
}
public static class PluginClassIterator<T> implements Iterator<Class<? extends T>> {
/**
* A Iterator that only returns enabled plugins.
*/
protected static class EnabledPluginIterator implements Iterator<PluginData> {
private List<PluginData> pluginList;
private int nextIndex = 0;
EnabledPluginIterator(List<PluginData> pluginList) {
this.pluginList = pluginList;
}
@Override
public boolean hasNext() {
for (int i = nextIndex; i < pluginList.size(); i++) {
if (pluginList.get(i).isEnabled())
return true;
}
return false;
}
@Override
public PluginData next() {
if(!hasNext())
throw new NoSuchElementException();
return pluginList.get(nextIndex++);
}
}
protected static class PluginClassIterator<T> implements Iterator<Class<? extends T>> {
private Class<T> intf;
private Iterator<PluginData> pluginIt;
private Iterator<Class<?>> classIt;
@ -150,20 +231,15 @@ public class PluginManager<T> implements Iterable<PluginData>{
throw new NoSuchElementException();
return (Class<? extends T>) classIt.next();
}
@Override
public void remove() {
throw new RuntimeException("Iterator is ReadOnly");
}
}
public static class PluginObjectIterator<T> implements Iterator<T> {
protected static class PluginSingletonIterator<T> implements Iterator<T> {
private Class<T> intf;
private Iterator<PluginData> pluginIt;
private Iterator<T> objectIt;
PluginObjectIterator(Iterator<PluginData> it, Class<T> intf){
PluginSingletonIterator(Iterator<PluginData> it, Class<T> intf){
this.intf = intf;
this.pluginIt = it;
}
@ -190,10 +266,5 @@ public class PluginManager<T> implements Iterable<PluginData>{
throw new NoSuchElementException();
return objectIt.next();
}
@Override
public void remove() {
throw new RuntimeException("Iterator is ReadOnly");
}
}
}