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

View file

@ -27,7 +27,6 @@ package zutil.plugin;
import zutil.log.LogUtil; import zutil.log.LogUtil;
import zutil.parser.DataNode; import zutil.parser.DataNode;
import java.net.MalformedURLException;
import java.util.*; import java.util.*;
import java.util.logging.Level; import java.util.logging.Level;
import java.util.logging.Logger; import java.util.logging.Logger;
@ -43,6 +42,7 @@ public class PluginData {
private double pluginVersion; private double pluginVersion;
private String pluginName; private String pluginName;
private boolean enabled = true;
private HashMap<Class<?>, List<Class<?>>> classMap; private HashMap<Class<?>, List<Class<?>>> classMap;
private HashMap<Class, Object> objectMap; 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(){ public double getVersion(){
return pluginVersion; return pluginVersion;
} }
/**
* @return the name of the plugin
*/
public String getName(){ public String getName(){
return pluginName; 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){ public <T> Iterator<T> getObjectIterator(Class<T> intf){
if(!classMap.containsKey(intf)) if(!classMap.containsKey(intf))
return Collections.emptyIterator(); 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){ public Iterator<Class<?>> getClassIterator(Class<?> intf){
if(!classMap.containsKey(intf)) if(!classMap.containsKey(intf))
return Collections.emptyIterator(); return Collections.emptyIterator();
@ -122,27 +147,32 @@ public class PluginData {
objectMap.put(objClass, objClass.newInstance()); objectMap.put(objClass, objClass.newInstance());
return (T) objectMap.get(objClass); return (T) objectMap.get(objClass);
} catch (Exception e) { } catch (Exception e) {
log.log(Level.WARNING, null, e); log.log(Level.WARNING, "Unable to instantiate plugin class: " + objClass, e);
} }
return null; return null;
} }
/**
* @return true if the specified interface is defined by the plugin
*/
public boolean contains(Class<?> intf){ public boolean contains(Class<?> intf){
return classMap.containsKey(intf); return classMap.containsKey(intf);
} }
public String toString(){ 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 Iterator<Class<?>> classIt;
private T currentObj; private T currentObj;
public PluginObjectIterator(Iterator<Class<?>> it) { public PluginSingletonIterator(Iterator<Class<?>> it) {
classIt = it; classIt = it;
} }

View file

@ -31,17 +31,24 @@ import zutil.parser.DataNode;
import zutil.parser.json.JSONParser; import zutil.parser.json.JSONParser;
import java.io.File; import java.io.File;
import java.util.ArrayList; import java.util.*;
import java.util.HashMap;
import java.util.Iterator;
import java.util.NoSuchElementException;
import java.util.logging.Logger; import java.util.logging.Logger;
/** /**
* This class will search the file system for files * This class will search the file system for files with the name "plugin.json"
* with the name "plugin.json" that defines data * that defines data parameters for a plugin.
* parameters for a single plugin. * The class will only load the latest version of a specific plugin with the same name.
* The class will only load the latest version of the specific plugin. * <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 * @author Ziver
*/ */
@ -51,13 +58,15 @@ public class PluginManager<T> implements Iterable<PluginData>{
private HashMap<String, PluginData> plugins; 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(){ public PluginManager(){
this("./"); this("./");
} }
/**
* Constructor that will look for plugins in the specified directory.
*/
public PluginManager(String path){ public PluginManager(String path){
plugins = new HashMap<>(); plugins = new HashMap<>();
@ -71,7 +80,7 @@ public class PluginManager<T> implements Iterable<PluginData>{
for(FileSearcher.FileSearchItem file : search){ for(FileSearcher.FileSearchItem file : search){
try { try {
DataNode node = JSONParser.read(IOUtil.readContentAsString(file.getInputStream(), true)); 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); PluginData plugin = new PluginData(node);
if (!plugins.containsKey(plugin.getName())){ if (!plugins.containsKey(plugin.getName())){
@ -93,32 +102,104 @@ public class PluginManager<T> implements Iterable<PluginData>{
} }
} }
/**
* @return a Iterator of all enabled plugins.
*/
@Override @Override
public Iterator<PluginData> iterator() { 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) { 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<>(); ArrayList<K> list = new ArrayList<>();
while(it.hasNext()) while(it.hasNext())
list.add(it.next()); list.add(it.next());
return list; 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 Class<T> intf;
private Iterator<PluginData> pluginIt; private Iterator<PluginData> pluginIt;
private Iterator<Class<?>> classIt; private Iterator<Class<?>> classIt;
@ -150,20 +231,15 @@ public class PluginManager<T> implements Iterable<PluginData>{
throw new NoSuchElementException(); throw new NoSuchElementException();
return (Class<? extends T>) classIt.next(); 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 Class<T> intf;
private Iterator<PluginData> pluginIt; private Iterator<PluginData> pluginIt;
private Iterator<T> objectIt; private Iterator<T> objectIt;
PluginObjectIterator(Iterator<PluginData> it, Class<T> intf){ PluginSingletonIterator(Iterator<PluginData> it, Class<T> intf){
this.intf = intf; this.intf = intf;
this.pluginIt = it; this.pluginIt = it;
} }
@ -190,10 +266,5 @@ public class PluginManager<T> implements Iterable<PluginData>{
throw new NoSuchElementException(); throw new NoSuchElementException();
return objectIt.next(); return objectIt.next();
} }
@Override
public void remove() {
throw new RuntimeException("Iterator is ReadOnly");
}
} }
} }