Mike,
we have this entire big thing in the queue for 3.0 - switching
CayenneModeler to a plugin engine. If you search the mailing list,
you'll find long heated discussions about it throughout the summer.
So I suggest to avoid checking in any ad hoc plugin functionality
until the engine is in place. Or even better - let's get the plugin
engine going for real.
Andrus
On Sep 29, 2006, at 3:34 PM, Mike Kienenberger wrote:
I needed to add a new feature to Cayenne Modeler yesterday. The
primary impact was the addition of a new menu item which called my own
code.
Today, I went through and tried to figure out a reasonable way of
making such an extension built-in to Cayenne, so I don't have to
maintain it with patches.
I'm not completely happy with what I have come up with, primarily
because it only supports one extension set, but this is what I've done
so far. I read a cayenneActionPluginFactory class from a system
property (yes, the property needs to be fully-qualified) as a method
on Application. Application seemed easily accessible and no worse
than anything else, but maybe a separate
CayenneActionPluginFactoryManager would make more sense.
If a plugin is found, I create a new Extensions top-level menu and
stick the actions into it in CayenneModelerFrame. In ActionManager's
constructor, I register the actions, and add any to the DOMAIN_ACTIONS
list that are domain actions (also should provide ways to do the same
for project, datamap, objEntity, dbEntity, Special, etc.)
That's the majority of the changes to support this. What I'd ideally
like to have happen is to figure out a way to support any number of
CayenneActionPluginFactory objects, and have the registration
automatic (maybe check each jar for a CayenneActionPluginFactory
config file?), but I don't know if the second option is realistic. I
suppose the first option could be handled by making the system
property a list of comma-separated classes rather than a single class.
public interface CayenneActionPlugin {
public String getActionName();
public CayenneAction createCayenneAction(Application application);
public boolean isDomainAction();
}
public interface CayenneActionPluginFactory {
public List getCayenneActionPluginList();
}
static CayenneActionPluginFactory cayenneActionPluginFactory =
null;
public CayenneActionPluginFactory getCayenneActionPluginFactory()
{
// TODO: retrieve somehow and allow multiple factories.
if (null == cayenneActionPluginFactory)
{
String pluginName =
System.getProperty("cayenneActionPluginFactory");
if (null != pluginName)
{
try {
cayenneActionPluginFactory =
(CayenneActionPluginFactory)Class.forName(pluginName).newInstance();
}
catch (InstantiationException e) {
logObj.error("InstantiationException error
instantiating cayenneActionPluginFactory", e);
}
catch (IllegalAccessException e) {
logObj.error("IllegalAccessException error
instantiating cayenneActionPluginFactory", e);
}
catch (ClassNotFoundException e) {
logObj.error("ClassNotFoundException error
instantiating cayenneActionPluginFactory", e);
}
}
}
return cayenneActionPluginFactory;
}