Plugin Structure
All plug-ins run in the PluginCore inherit from the class PluginCore.Plugin, this object provides basic functionality leaving the programmer to fill in the abstract methods. Lets go into more detail on what each of the abstract methods does in the plugin.
Constructor
In the constructor must be a zero argument constructor, this is because of how plugins are loaded. Inside of the constructor though the programmer is free to do what they want, so long as it does not involve a call to the frameworkCore object, as this will not have been initialized yet. The plug-in should have its internal name set in the constructor. This should be done for each plugin (unless it is inheriting a constructor from another plugin and wishes to keep that name, but that is an advanced use). To set the plug-in name set the variable pluginName, for instance if the full name of the plugin was ipMedia.Client.plugins.My FavoritePlugin then you could set the name like this: pluginName = "MyFavoritePlugin"
Abstract Methods
public abstract void run();
The run method is inherited from the Thread class, which Plugin inherits from, and contains the code that will be run as the main loop of the plug-in. Any calls that are made from this method will happen in the plug-ins own thread, even when messages are sent to other plug-ins the processing on that plug-in will occur in this plug-ins thread. If any other initialization is to occur after the constructor, specifically anything that requires calls to other the frameworkCore object. It is in this method that the work will be done, at least one plug-in must have a run() method filled out for the program to run.
It is not necessary to have anything in the run method for all plug-ins, many plug-ins provide service through there send() method alone, responding to requests from other plug-ins. It is possible to also save messages in a queue and read that queue from this method, that would result in the processing to handle the message occurring in the plug-ins own thread, this can be important if plug-ins are being used to spread processing across multiple threads.
public abstract void shutdown();
The shutdown method is called by the PluginCore when it is trying to shutdown a plug-in, the method itself does nothing but identify intent to terminate the plug-in. If the plug-in has ongoing processing in the run() method this method should set a variable that the run method periodically checks, and when it is set the plug-in should begin to shut itself down in a orderly manner, in preparation for a Thread.join() event in its future.
public abstract int receive( Message msgIn );
This method handles all incoming Message objects to the plug-in. When a plug-in makes a call to frameworkCore.postMessage( Message theMessage ); the PluginCore will find the message that is identified by the destination address and call its send() method with the provided Message object. Thus it is in this method that a plug-in will implement its message contract with the rest of the program, documenting how a plug-in responds to messages is a incredibly important part of the process as the interactions of different plug-ins can get quite complex quite rapidly. It is important to remember that every method call made in the send() method occurs in another plug-ins thread, so any major processing that should occur in parallel must occur by setting a variable that triggers the processing in the run() method, as control will not return to the calling plug-in until this method returns.
public abstract Object[] savePluginState( );
If the program is going to support swapping of plug-ins then this plug-in must be written, if there is no plans it is best to put a error message in it that this method has not been written and return null. This method should save all the variables that make up the state of the plug-in, the 0th element should be the fully qualified name of the plug-in that generated the array, that way when another plug-in receives this array it can quickly determine weather or not it can set its state off of this array. Fill the array with the variables to save and return it, it will then be used by the core to call a setPluginState().
public abstract boolean setPluginState( Object[] stateVec );
This method takes in the object array that is generated by the savePluginState method, it will use it to set the local variables that make up the objects state. The first thing that this method should do is check the 0th element of the array, that will contain the fully qualified name of the plug-in that generated the array, telling this plug-in what format to expect the data to be in and hopefully allowing the plug-in to identify if it can even initialize itself off this array. If it cannot then print a error and return false. If this method is being called then the plug-in is replacing another plug-in in the system, depending on what plug-in is being replaced, and what the current plug-in does there may be resources already initialized in the system that should be used instead of initializing new resources, these concerns should be taken into account when preparing plug-ins with this method.
Provided Methods
There are also a number of inherited non-abstract methods in the Plugin object
that are useful to the programmer.
protected void printDebug( String debugMsg )
This provides a standardized debug output method for all plug-ins, it will only print the message if the DEBUG variable is 'true' otherwise it will print nothing. When it does print a message it does so to System.out and appends to the beginning of the message the plug-ins name and id, then the debug message provided. This will help identify what output is coming from where, even with multiple instances of the same plug-in running.
protected void printError( String errorMsg )
This is a standardized error output for the plug-in system, it is always printed and will output to System.err appending "Error occurred in", the plugins id and the error message.
public boolean safeJoin( int timer )
The safeJoin method is a wrapper method for the Thread.join( ) call, it has exception handling, so if a exception occurs this method will return false. The timer value is the time that the thread is to wait for the thread to join in milliseconds, with 0 meaning wait forever.
public boolean safeSleep( int timeToSleep )
This method is a wrapper call to Thread.sleep( ) with exception handling, if a exception is thrown this method will return false. The timeToSleep variable is how long the thread is to sleep in milliseconds.