Author: cyberdo
Date: 2006-02-18 16:46:38 +0000 (Sat, 18 Feb 2006)
New Revision: 8059

Added:
   trunk/freenet/src/pluginmanager/
   trunk/freenet/src/pluginmanager/FredPlugin.java
   trunk/freenet/src/pluginmanager/PluginHandler.java
   trunk/freenet/src/pluginmanager/PluginInfoWrapper.java
   trunk/freenet/src/pluginmanager/PluginManager.java
   trunk/freenet/src/pluginmanager/PluginNotFoundException.java
   trunk/freenet/src/pluginmanager/PluginRespirator.java
   trunk/freenet/src/pluginmanager/TestPlugin.java
Modified:
   trunk/freenet/src/freenet/node/Node.java
   trunk/freenet/src/freenet/node/TextModeClientInterface.java
   trunk/freenet/src/freenet/node/Version.java
Log:
449:
First version of the plugin manager!
3 basic sommands added. Example plugin in src/pluginmanager/TestPlugin.java
(PLUGLOAD:pluginmanager.TestPlugin).
should workfine for now. Only FCP-support ATM. No sandboxing.


Modified: trunk/freenet/src/freenet/node/Node.java
===================================================================
--- trunk/freenet/src/freenet/node/Node.java    2006-02-18 14:43:37 UTC (rev 
8058)
+++ trunk/freenet/src/freenet/node/Node.java    2006-02-18 16:46:38 UTC (rev 
8059)
@@ -25,6 +25,9 @@
 import java.util.HashSet;
 import java.util.Iterator;

+import pluginmanager.PluginManager;
+import pluginmanager.PluginRespirator;
+
 import snmplib.SNMPAgent;
 import snmplib.SNMPStarter;

@@ -199,6 +202,9 @@
     public final ClientRequestScheduler fetchScheduler;
     public final ClientRequestScheduler putScheduler;

+    // Things that's needed to keep track of
+    public final PluginManager pluginManager;
+    
     // Client stuff that needs to be configged - FIXME
     static final int MAX_ARCHIVE_HANDLERS = 200; // don't take up much RAM... 
FIXME
     static final long MAX_CACHED_ARCHIVE_DATA = 32*1024*1024; // make a fixed 
fraction of the store by default? FIXME
@@ -485,6 +491,19 @@
                        testnetHandler.start();
                if(statusUploader != null)
                        statusUploader.start();
+               
+               // And finally, Initialize the plugin manager
+               PluginManager pm = null;
+               try {
+                       HighLevelSimpleClient hlsc = new 
HighLevelSimpleClientImpl(this, 
+                                       archiveManager, tempBucketFactory, 
random, false, (short)0);
+                       PluginRespirator pluginRespirator = new 
PluginRespirator(hlsc);
+                       pm = new PluginManager(pluginRespirator);
+               } catch (Throwable e) {
+                       e.printStackTrace();
+                       System.err.println("THIS SHOULDN'T OCCUR!!!! (plugin 
system now disabled)");
+               }
+               pluginManager = pm;
                System.err.println("Created Node on port "+port);
     }


Modified: trunk/freenet/src/freenet/node/TextModeClientInterface.java
===================================================================
--- trunk/freenet/src/freenet/node/TextModeClientInterface.java 2006-02-18 
14:43:37 UTC (rev 8058)
+++ trunk/freenet/src/freenet/node/TextModeClientInterface.java 2006-02-18 
16:46:38 UTC (rev 8059)
@@ -98,6 +98,9 @@
         System.out.println("MAKESSK - Create an SSK keypair.");
         System.out.println("PUTSSK:<insert uri>;<url to redirect to> - Insert 
an SSK redirect to a file already inserted.");
         System.out.println("PUTSSKDIR:<insert uri>#<path>[#<defaultfile>] - 
Insert an entire directory to an SSK.");
+        System.out.println("PLUGLOAD: <pkg.classname>[@file:<jarfile.jar>] - 
Load plugin.");
+        System.out.println("PLUGLIST - List all loaded plugins.");
+        System.out.println("PLUGKILL: <pluginID> - Unload the plugin with the 
given ID (see PLUGLIST).");
 //        System.out.println("PUBLISH:<name> - create a publish/subscribe 
stream called <name>");
 //        System.out.println("PUSH:<name>:<text> - publish a single line of 
text to the stream named");
 //        System.out.println("SUBSCRIBE:<key> - subscribe to a 
publish/subscribe stream by key");
@@ -500,6 +503,13 @@
         } else if(uline.startsWith("DISCONNECT:")) {
                String ipAndPort = line.substring("DISCONNECT:".length());
                disconnect(ipAndPort.trim());
+               
+        } else if(uline.startsWith("PLUGLOAD:")) {
+               
n.pluginManager.startPlugin(line.substring("PLUGLOAD:".length()).trim());
+        } else if(uline.startsWith("PLUGLIST")) {
+               n.pluginManager.dumpPlugins();
+        } else if(uline.startsWith("PLUGKILL:")) {
+               
n.pluginManager.killPlugin(line.substring("PLUGKILL:".length()).trim());
         } else {
                if(uline.length() > 0)
                        printHeader();

Modified: trunk/freenet/src/freenet/node/Version.java
===================================================================
--- trunk/freenet/src/freenet/node/Version.java 2006-02-18 14:43:37 UTC (rev 
8058)
+++ trunk/freenet/src/freenet/node/Version.java 2006-02-18 16:46:38 UTC (rev 
8059)
@@ -20,7 +20,7 @@
        public static final String protocolVersion = "1.0";

        /** The build number of the current revision */
-       private static final int buildNumber = 448;
+       private static final int buildNumber = 449;

        /** Oldest build of Fred we will talk to */
        private static final int lastGoodBuild = 403;

Added: trunk/freenet/src/pluginmanager/FredPlugin.java
===================================================================
--- trunk/freenet/src/pluginmanager/FredPlugin.java     2006-02-18 14:43:37 UTC 
(rev 8058)
+++ trunk/freenet/src/pluginmanager/FredPlugin.java     2006-02-18 16:46:38 UTC 
(rev 8059)
@@ -0,0 +1,6 @@
+package pluginmanager;
+
+public interface FredPlugin {
+       public void terminate();
+       public void runPlugin(PluginRespirator pr);
+}

Added: trunk/freenet/src/pluginmanager/PluginHandler.java
===================================================================
--- trunk/freenet/src/pluginmanager/PluginHandler.java  2006-02-18 14:43:37 UTC 
(rev 8058)
+++ trunk/freenet/src/pluginmanager/PluginHandler.java  2006-02-18 16:46:38 UTC 
(rev 8059)
@@ -0,0 +1,64 @@
+package pluginmanager;
+
+/**
+ * Methods to handle a specific plugin (= set it up and start it)
+ * 
+ * @author cyberdo
+ */
+public class PluginHandler {
+
+       /**
+        * Will get all needed info from the plugin, put it into the Wrapper. 
Then
+        * the Pluginstarter will be greated, and the plugin fedto it, starting 
the
+        * plugin.
+        * 
+        * the pluginInfoWrapper will then be returned
+        * 
+        * @param plug
+        */
+       public static PluginInfoWrapper startPlugin(PluginManager pm, 
FredPlugin plug, PluginRespirator pr) {
+               PluginStarter ps = new PluginStarter(pr);
+               PluginInfoWrapper pi = new PluginInfoWrapper();
+               pi.putPluginThread(plug, ps);
+               ps.setPlugin(pm, plug);
+               ps.start();
+               return pi;
+       }
+       
+       private static class PluginStarter extends Thread {
+               private Object plugin = null;
+               private PluginRespirator pr;
+               private PluginManager pm = null;
+               
+               public PluginStarter(PluginRespirator pr) {
+                       this.pr = pr;
+               }
+               
+               public void setPlugin(PluginManager pm, Object plugin) {
+                       this.plugin = plugin;
+                       this.pm = pm;
+               }
+               
+               public void run() {
+                       int seconds = 120; // give up after 2 min
+                       while (plugin == null) {
+                               // 1s polling
+                               try {
+                                       Thread.sleep(1000);
+                               } catch (InterruptedException e) {
+                               }
+                               if (seconds-- <= 0)
+                                       return;
+                       }
+                       
+                       if (plugin instanceof FredPlugin)
+                               ((FredPlugin)plugin).runPlugin(pr);
+                       
+                       // If not FredPlugin, then the whole thing is aborted,
+                       // and then this method will return, killing the thread
+                       
+                       pm.removePlugin(this);
+               }
+               
+       }
+}

Added: trunk/freenet/src/pluginmanager/PluginInfoWrapper.java
===================================================================
--- trunk/freenet/src/pluginmanager/PluginInfoWrapper.java      2006-02-18 
14:43:37 UTC (rev 8058)
+++ trunk/freenet/src/pluginmanager/PluginInfoWrapper.java      2006-02-18 
16:46:38 UTC (rev 8059)
@@ -0,0 +1,50 @@
+package pluginmanager;
+
+import java.util.Date;
+
+public class PluginInfoWrapper {
+       // Parameters to make the object OTP
+       private boolean fedPluginThread = false;
+       // Public since only PluginHandler will know about it
+       private String className;
+       private Thread thread;
+       private long start;
+       private String threadName;
+       private FredPlugin plug;
+       //public String 
+       
+       public void putPluginThread(FredPlugin plug, Thread ps) {
+               if (fedPluginThread) return;
+               
+               className = plug.getClass().toString();
+               thread = ps;
+               this.plug = plug;
+               threadName = "p" + className.replaceAll("^class ", "") + "_" + 
ps.hashCode();
+               start = System.currentTimeMillis();
+               ps.setName(threadName);
+               
+               fedPluginThread = true;
+       }
+       
+       public String toString() {
+               return "ID: \"" +threadName + "\", Name: "+ className +" 
Started: " + (new Date(start)).toString();
+       }
+       
+       public String getThreadName() {
+               return threadName;
+       }
+       
+/*     public FredPlugin getPlugin(){
+               return plug;
+       }
+       */
+       public void stopPlugin() {
+               plug.terminate();
+               //thread.interrupt();
+       }
+       
+       public boolean sameThread(Thread t){
+               return (t == thread);
+       }
+       
+}

Added: trunk/freenet/src/pluginmanager/PluginManager.java
===================================================================
--- trunk/freenet/src/pluginmanager/PluginManager.java  2006-02-18 14:43:37 UTC 
(rev 8058)
+++ trunk/freenet/src/pluginmanager/PluginManager.java  2006-02-18 16:46:38 UTC 
(rev 8059)
@@ -0,0 +1,143 @@
+package pluginmanager;
+
+import java.net.URL;
+import java.net.URLClassLoader;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.Iterator;
+
+import freenet.client.HighLevelSimpleClient;
+
+public class PluginManager {
+
+       /*
+        * 
+        * TODO: Synchronize
+        * TODO: Synchronize
+        * TODO: Synchronize
+        * TODO: Synchronize
+        * TODO: Synchronize
+        * 
+        */
+       
+       
+       private static HashMap pluginInfo;
+       private static PluginManager pluginManager = null;
+       private PluginRespirator pluginRespirator = null;
+       
+       public PluginManager(PluginRespirator pluginRespirator) {
+               pluginInfo = new HashMap();
+               
+               this.pluginRespirator = pluginRespirator;
+               //StartPlugin("misc at file:plugin.jar");
+               
+               // Needed to include plugin in jar-files
+               if (new Date().equals(null))
+                       System.err.println(new TestPlugin());
+       }
+       
+       public void startPlugin(String filename) {
+               FredPlugin plug;
+               try {
+                       plug = LoadPlugin(filename);
+                       PluginInfoWrapper pi = PluginHandler.startPlugin(this, 
plug, pluginRespirator);
+                       pluginInfo.put(pi.getThreadName(), pi);
+               } catch (PluginNotFoundException e) {
+                       e.printStackTrace();
+               }
+       }
+       
+       public void removePlugin(Thread t) {
+               Object removeKey = null;
+               {
+                       Iterator it = pluginInfo.keySet().iterator();
+                       while (it.hasNext()) {
+                               Object key = it.next();
+                               PluginInfoWrapper pi = (PluginInfoWrapper) 
pluginInfo.get(key);
+                               if (pi.sameThread(t))
+                                       removeKey = key;
+                       }
+               }
+               if (removeKey != null)
+                       pluginInfo.remove(removeKey);
+       }
+
+       public void dumpPlugins() {
+               Iterator it = pluginInfo.keySet().iterator();
+               while (it.hasNext()) {
+                       PluginInfoWrapper pi = (PluginInfoWrapper) 
pluginInfo.get(it.next());
+                       System.out.println(pi);
+               }
+       }
+       
+       public void killPlugin(String name) {
+               Iterator it = pluginInfo.keySet().iterator();
+               while (it.hasNext()) {
+                       PluginInfoWrapper pi = (PluginInfoWrapper) 
pluginInfo.get(it.next());
+                       if (pi.getThreadName().equals(name))
+                       {
+                               pi.stopPlugin();
+                       }
+               }
+       }
+       
+       
+       /**
+        * Method to load a plugin from the given path and return is as an 
object.
+        * Will accept filename to be of one of the following forms:
+        * "classname" to load a class from the current classpath
+        * "classame at file:/path/to/jarfile.jar" to load class from an other 
jarfile.
+        * 
+        * @param filename      The filename to load from
+        * @return                      An instanciated object of the plugin
+        * @throws PluginNotFoundException      If anything goes wrong.
+        */
+       private FredPlugin LoadPlugin(String filename) throws 
PluginNotFoundException {
+        Class cls = null;
+        
+        if (filename.indexOf("@file:") >= 0) {
+            // Open from extern file
+            try {
+                // Load the jar-file
+                String[] parts = filename.split("@file:");
+                if (parts.length != 2) {
+                       throw new PluginNotFoundException("Could not split at 
\"@file:\".");
+                }
+                
+                // Load the class inside file
+                URL[] serverURLs = new URL[]{new URL("file:" + parts[1])};
+                ClassLoader cl = new URLClassLoader(serverURLs);
+                cls = cl.loadClass(parts[0]);
+            } catch (Exception e) {
+                throw new PluginNotFoundException("Initialization error:"
+                               + filename, e);
+            }
+        } else {
+            // Load class
+            try {
+                cls = Class.forName(filename);
+            } catch (ClassNotFoundException e) {
+               throw new PluginNotFoundException(filename);
+            }
+        }
+        
+        if(cls == null)
+               throw new PluginNotFoundException("Unknown error");
+        
+        // Class loaded... Objectize it!
+        Object o = null;
+        try {
+            o = cls.newInstance();
+        } catch (Exception e) {
+               throw new PluginNotFoundException("Could not re-create plugin:" 
+
+                               filename, e);
+        }
+        
+        // See if we have the right type
+        if (!(o instanceof FredPlugin)) {
+               throw new PluginNotFoundException("Not a plugin: " + filename);
+        }
+        
+        return (FredPlugin)o;
+       }
+}

Added: trunk/freenet/src/pluginmanager/PluginNotFoundException.java
===================================================================
--- trunk/freenet/src/pluginmanager/PluginNotFoundException.java        
2006-02-18 14:43:37 UTC (rev 8058)
+++ trunk/freenet/src/pluginmanager/PluginNotFoundException.java        
2006-02-18 16:46:38 UTC (rev 8059)
@@ -0,0 +1,25 @@
+package pluginmanager;
+
+public class PluginNotFoundException extends Exception {
+
+       public PluginNotFoundException() {
+               super();
+               // TODO Auto-generated constructor stub
+       }
+
+       public PluginNotFoundException(String arg0) {
+               super(arg0);
+               // TODO Auto-generated constructor stub
+       }
+
+       public PluginNotFoundException(String arg0, Throwable arg1) {
+               super(arg0, arg1);
+               // TODO Auto-generated constructor stub
+       }
+
+       public PluginNotFoundException(Throwable arg0) {
+               super(arg0);
+               // TODO Auto-generated constructor stub
+       }
+
+}

Added: trunk/freenet/src/pluginmanager/PluginRespirator.java
===================================================================
--- trunk/freenet/src/pluginmanager/PluginRespirator.java       2006-02-18 
14:43:37 UTC (rev 8058)
+++ trunk/freenet/src/pluginmanager/PluginRespirator.java       2006-02-18 
16:46:38 UTC (rev 8059)
@@ -0,0 +1,17 @@
+package pluginmanager;
+
+import freenet.client.HighLevelSimpleClient;
+import freenet.client.HighLevelSimpleClientImpl;
+import freenet.node.Node;
+
+public class PluginRespirator {
+       private HighLevelSimpleClient hlsc = null;
+       
+       public PluginRespirator(HighLevelSimpleClient hlsc) {
+               this.hlsc = hlsc;
+       }
+       
+       public HighLevelSimpleClient getHLSimpleClient() {
+               return hlsc;
+       }
+}

Added: trunk/freenet/src/pluginmanager/TestPlugin.java
===================================================================
--- trunk/freenet/src/pluginmanager/TestPlugin.java     2006-02-18 14:43:37 UTC 
(rev 8058)
+++ trunk/freenet/src/pluginmanager/TestPlugin.java     2006-02-18 16:46:38 UTC 
(rev 8059)
@@ -0,0 +1,38 @@
+package pluginmanager;
+
+import java.net.MalformedURLException;
+import java.util.Date;
+
+import freenet.client.FetchException;
+import freenet.client.FetchResult;
+import freenet.keys.FreenetURI;
+
+public class TestPlugin implements FredPlugin {
+       boolean goon = true;
+       public void terminate() {
+               goon = false;
+       }
+
+       public void runPlugin(PluginRespirator pr) {
+               int i = (int)System.currentTimeMillis()%1000;
+               while(goon) {
+                       System.err.println("This is a threaded test-plugin (" + 
+                                       i + "). " +
+                                       "Time is now: " + (new Date()));
+                       FetchResult fr;
+                       try {
+                               fr = pr.getHLSimpleClient().fetch(new 
FreenetURI("freenet:CHK at 
j-v1zc0cuN3wlaCpxlKd6vT6c1jAnT9KiscVjfzLu54,q9FIlJSh8M1I1ymRBz~A0fsIcGkvUYZahZb5j7uepLA,AAEA--8"));
+                               System.err.println("  Got data from key, length 
= " + fr.size() + " Message: "
+                                               + new 
String(fr.asByteArray()).trim());
+                       } catch (Exception e) {
+                       }
+                       try {
+                               Thread.sleep(10000);
+                       } catch (InterruptedException e) {
+                               // TODO Auto-generated catch block
+                               e.printStackTrace();
+                       }
+               }
+       }
+
+}


Reply via email to