diff --git a/conf-sso/dynamo.xml b/conf-sso/dynamo.xml
index 58f22ec..b95984b 100644
--- a/conf-sso/dynamo.xml
+++ b/conf-sso/dynamo.xml
@@ -48,8 +48,9 @@
-
-
+
${code.path}/modules
+
diff --git a/conf/venice-db-init-mysql.sql b/conf/venice-db-init-mysql.sql
index af6033b..0999f88 100644
--- a/conf/venice-db-init-mysql.sql
+++ b/conf/venice-db-init-mysql.sql
@@ -339,6 +339,14 @@ CREATE TABLE ndx_locks (
PRIMARY KEY (ndxid, name)
);
+# Table indicating which modules have been installed.
+CREATE TABLE modinstall (
+ filename VARCHAR(255) BINARY NOT NULL PRIMARY KEY, # file name relative to module directory
+ mod_nsid INT NOT NULL, # namespaceID of module name
+ mod_name VARCHAR(255) BINARY NOT NULL, # module name within namespace
+ UNIQUE INDEX by_name (mod_nsid, mod_name)
+);
+
############################ following this line are Venice-specific tables ############################
# The table which defines menus.
diff --git a/src/dynamo-framework/com/silverwrist/dynamo/iface/Module.java b/src/dynamo-framework/com/silverwrist/dynamo/iface/Module.java
index 31148df..ff6d345 100644
--- a/src/dynamo-framework/com/silverwrist/dynamo/iface/Module.java
+++ b/src/dynamo-framework/com/silverwrist/dynamo/iface/Module.java
@@ -18,6 +18,7 @@
package com.silverwrist.dynamo.iface;
import java.security.Principal;
+import com.silverwrist.dynamo.except.DatabaseException;
import com.silverwrist.dynamo.except.ModuleException;
import com.silverwrist.dynamo.util.QualifiedNameKey;
@@ -25,9 +26,9 @@ public interface Module
{
public QualifiedNameKey getModuleID();
- public void install(ServiceProvider services, Principal installer) throws ModuleException;
+ public void install(Principal installer) throws DatabaseException, ModuleException;
- public void uninstall(ServiceProvider services, Principal uninstaller) throws ModuleException;
+ public void uninstall(Principal uninstaller) throws DatabaseException, ModuleException;
public DynamicObject getProvidedObject(String namespace, String name) throws ModuleException;
diff --git a/src/dynamo-framework/com/silverwrist/dynamo/module/InstallServiceManager.java b/src/dynamo-framework/com/silverwrist/dynamo/module/InstallServiceManager.java
new file mode 100644
index 0000000..152a5b9
--- /dev/null
+++ b/src/dynamo-framework/com/silverwrist/dynamo/module/InstallServiceManager.java
@@ -0,0 +1,256 @@
+/*
+ * The contents of this file are subject to the Mozilla Public License Version 1.1
+ * (the "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at .
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis, WITHOUT
+ * WARRANTY OF ANY KIND, either express or implied. See the License for the specific
+ * language governing rights and limitations under the License.
+ *
+ * The Original Code is the Venice Web Communities System.
+ *
+ * The Initial Developer of the Original Code is Eric J. Bowersox ,
+ * for Silverwrist Design Studios. Portions created by Eric J. Bowersox are
+ * Copyright (C) 2003 Eric J. Bowersox/Silverwrist Design Studios. All Rights Reserved.
+ *
+ * Contributor(s):
+ */
+package com.silverwrist.dynamo.module;
+
+import java.util.*;
+import com.silverwrist.dynamo.except.*;
+import com.silverwrist.dynamo.iface.*;
+import com.silverwrist.dynamo.util.*;
+
+class InstallServiceManager
+{
+ /*--------------------------------------------------------------------------------
+ * Internal class implementing the install service provider
+ *--------------------------------------------------------------------------------
+ */
+
+ private class Services extends BaseDelegatingServiceProvider
+ {
+ /*====================================================================
+ * Constructors
+ *====================================================================
+ */
+
+ Services()
+ {
+ super("Module Initialization Services");
+
+ } // end constructor
+
+ Services(ServiceProvider delegate)
+ {
+ super("Module Initialization Services",delegate);
+
+ } // end constructor
+
+ /*====================================================================
+ * Overrides from class BaseDelegatingServiceProvider
+ *====================================================================
+ */
+
+ /**
+ * Queries this object for a specified service.
+ *
+ * @param klass The class of the object that should be returned as a service.
+ * @return A service object. The service object is guaranteed to be of the class
+ * specified by klass
; that is, if queryService(klass)
+ * yields some object x
, then the expression klass.isInstance(x)
+ * is true.
+ * @exception com.silverwrist.dynamo.except.NoSuchServiceException If no service is available in
+ * the specified class.
+ */
+ public Object queryService(Class klass)
+ {
+ Object rc = m_service_cache.get(klass);
+ if (rc!=null)
+ return rc;
+
+ for (int i=(m_service_hooks.size()-1); i>=0; i--)
+ { // call the hooks
+ try
+ { // get hooks in reverse order of installation and try them
+ ServiceProvider sp = (ServiceProvider)(m_service_hooks.get(i));
+ rc = sp.queryService(klass);
+ m_service_cache.put(klass,rc);
+ return rc;
+
+ } // end try
+ catch (NoSuchServiceException e)
+ { // cycle around and keep trying
+ } // end catch
+
+ } // end for
+
+ rc = m_services.get(klass);
+ if (rc!=null)
+ { // cache the service
+ m_service_cache.put(klass,rc);
+ return rc;
+
+ } // end if
+
+ return super.queryService(klass);
+
+ } // end queryService
+
+ /**
+ * Queries this object for a specified service.
+ *
+ * @param klass The class of the object that should be returned as a service.
+ * @param serviceid ID for the service to be requested, to further discriminate between requests.
+ * @return A service object. The service object is guaranteed to be of the class
+ * specified by klass
; that is, if queryService(klass)
+ * yields some object x
, then the expression klass.isInstance(x)
+ * is true.
+ * @exception com.silverwrist.dynamo.except.NoSuchServiceException If no service is available in
+ * the specified class.
+ */
+ public Object queryService(Class klass, String serviceid)
+ {
+ ServiceKey key = new ServiceKey(klass,serviceid);
+ Object rc = m_service_cache.get(key);
+ if (rc!=null)
+ return rc;
+
+ for (int i=(m_service_hooks.size()-1); i>=0; i--)
+ { // call the hooks
+ try
+ { // get hooks in reverse order of installation and try them
+ ServiceProvider sp = (ServiceProvider)(m_service_hooks.get(i));
+ rc = sp.queryService(klass,serviceid);
+ m_service_cache.put(key,rc);
+ return rc;
+
+ } // end try
+ catch (NoSuchServiceException e)
+ { // cycle around and keep trying
+ } // end catch
+
+ } // end for
+
+ try
+ { // call through to superclass
+ return super.queryService(klass,serviceid);
+
+ } // end try
+ catch (NoSuchServiceException e)
+ { // OK, try it without the service ID
+ rc = queryService(klass);
+ m_service_cache.put(key,rc);
+ return rc;
+
+ } // end catch
+
+ } // end queryService
+
+ } // end class Services
+
+ /*--------------------------------------------------------------------------------
+ * Internal class for removing hooks
+ *--------------------------------------------------------------------------------
+ */
+
+ private class RemoveHook implements ComponentShutdown
+ {
+ /*====================================================================
+ * Attributes
+ *====================================================================
+ */
+
+ private ServiceProvider m_sp;
+
+ /*====================================================================
+ * Constructor
+ *====================================================================
+ */
+
+ RemoveHook(ServiceProvider sp)
+ {
+ m_sp = sp;
+
+ } // end constructor
+
+ /*====================================================================
+ * Implementations from interface ComponentShutdown
+ *====================================================================
+ */
+
+ public void shutdown()
+ {
+ m_service_hooks.remove(m_sp);
+ m_service_cache.clear();
+
+ } // end shutdown
+
+ } // end class RemoveHook
+
+ /*--------------------------------------------------------------------------------
+ * Attributes
+ *--------------------------------------------------------------------------------
+ */
+
+ private Hashtable m_services = new Hashtable();
+ private Vector m_service_hooks = new Vector();
+ private Hashtable m_service_cache = new Hashtable();
+ private ServiceProvider m_base = null;
+
+ /*--------------------------------------------------------------------------------
+ * Constructor
+ *--------------------------------------------------------------------------------
+ */
+
+ InstallServiceManager()
+ { // do nothing
+ } // end constructor
+
+ /*--------------------------------------------------------------------------------
+ * External operations
+ *--------------------------------------------------------------------------------
+ */
+
+ void addService(Class klass, Object svc)
+ {
+ m_services.put(klass,svc);
+
+ } // end addService
+
+ synchronized ServiceProvider getServiceProvider()
+ {
+ if (m_base==null)
+ m_base = new Services();
+ return m_base;
+
+ } // end getServiceProvider
+
+ ServiceProvider getServiceProvider(ServiceProvider delegate)
+ {
+ if (delegate==null)
+ return this.getServiceProvider();
+ else
+ return new Services(delegate);
+
+ } // end getServiceProvider
+
+ ComponentShutdown hook(ServiceProvider sp)
+ {
+ m_service_hooks.add(sp);
+ m_service_cache.clear();
+ return new RemoveHook(sp);
+
+ } // end hook
+
+ void dispose()
+ {
+ m_services.clear();
+ m_service_hooks.clear();
+ m_service_cache.clear();
+ m_base = null;
+
+ } // end dispose
+
+} // end class InstallServiceManager
diff --git a/src/dynamo-framework/com/silverwrist/dynamo/module/ModuleDBOps.java b/src/dynamo-framework/com/silverwrist/dynamo/module/ModuleDBOps.java
new file mode 100644
index 0000000..b51924b
--- /dev/null
+++ b/src/dynamo-framework/com/silverwrist/dynamo/module/ModuleDBOps.java
@@ -0,0 +1,62 @@
+/*
+ * The contents of this file are subject to the Mozilla Public License Version 1.1
+ * (the "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at .
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis, WITHOUT
+ * WARRANTY OF ANY KIND, either express or implied. See the License for the specific
+ * language governing rights and limitations under the License.
+ *
+ * The Original Code is the Venice Web Communities System.
+ *
+ * The Initial Developer of the Original Code is Eric J. Bowersox ,
+ * for Silverwrist Design Studios. Portions created by Eric J. Bowersox are
+ * Copyright (C) 2003 Eric J. Bowersox/Silverwrist Design Studios. All Rights Reserved.
+ *
+ * Contributor(s):
+ */
+package com.silverwrist.dynamo.module;
+
+import java.util.*;
+import com.silverwrist.dynamo.db.OpsBase;
+import com.silverwrist.dynamo.except.*;
+import com.silverwrist.dynamo.iface.*;
+
+abstract class ModuleDBOps extends OpsBase
+{
+ /*--------------------------------------------------------------------------------
+ * Constructor
+ *--------------------------------------------------------------------------------
+ */
+
+ protected ModuleDBOps(DBConnectionPool pool)
+ {
+ super(pool);
+
+ } // end constructor
+
+ /*--------------------------------------------------------------------------------
+ * Abstract operations
+ *--------------------------------------------------------------------------------
+ */
+
+ abstract boolean isModuleInstalled(String filename) throws DatabaseException;
+
+ abstract Set getInstalledModules() throws DatabaseException;
+
+ abstract void markInstalled(String filename, int nsid, String name) throws DatabaseException;
+
+ abstract void unmarkInstalled(String filename) throws DatabaseException;
+
+ /*--------------------------------------------------------------------------------
+ * External static operations
+ *--------------------------------------------------------------------------------
+ */
+
+ static ModuleDBOps get(DBConnectionPool pool) throws ConfigException
+ {
+ return (ModuleDBOps)get(pool,ModuleDBOps.class.getClassLoader(),ModuleDBOps.class.getName() + "_","ModuleDBOps");
+
+ } // end get
+
+} // end class ModuleDBOps
diff --git a/src/dynamo-framework/com/silverwrist/dynamo/module/ModuleDBOps_mysql.java b/src/dynamo-framework/com/silverwrist/dynamo/module/ModuleDBOps_mysql.java
new file mode 100644
index 0000000..64542f1
--- /dev/null
+++ b/src/dynamo-framework/com/silverwrist/dynamo/module/ModuleDBOps_mysql.java
@@ -0,0 +1,186 @@
+/*
+ * The contents of this file are subject to the Mozilla Public License Version 1.1
+ * (the "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at .
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis, WITHOUT
+ * WARRANTY OF ANY KIND, either express or implied. See the License for the specific
+ * language governing rights and limitations under the License.
+ *
+ * The Original Code is the Venice Web Communities System.
+ *
+ * The Initial Developer of the Original Code is Eric J. Bowersox ,
+ * for Silverwrist Design Studios. Portions created by Eric J. Bowersox are
+ * Copyright (C) 2003 Eric J. Bowersox/Silverwrist Design Studios. All Rights Reserved.
+ *
+ * Contributor(s):
+ */
+package com.silverwrist.dynamo.module;
+
+import java.sql.*;
+import java.util.*;
+import com.silverwrist.util.*;
+import com.silverwrist.dynamo.except.*;
+import com.silverwrist.dynamo.iface.*;
+
+public class ModuleDBOps_mysql extends ModuleDBOps
+{
+ /*--------------------------------------------------------------------------------
+ * Constructor
+ *--------------------------------------------------------------------------------
+ */
+
+ public ModuleDBOps_mysql(DBConnectionPool pool)
+ {
+ super(pool);
+
+ } // end constructor
+
+ /*--------------------------------------------------------------------------------
+ * Abstract implementations from class ModuleDBOps
+ *--------------------------------------------------------------------------------
+ */
+
+ boolean isModuleInstalled(String filename) throws DatabaseException
+ {
+ Connection conn = null;
+ PreparedStatement stmt = null;
+ ResultSet rs = null;
+ try
+ { // get a connection
+ conn = getConnection();
+
+ // prepare and execute the query
+ stmt = conn.prepareStatement("SELECT mod_nsid FROM modinstall WHERE filename = ?;");
+ stmt.setString(1,filename);
+ rs = stmt.executeQuery();
+ return rs.next();
+
+ } // end try
+ catch (SQLException e)
+ { // translate to a general DatabaseException
+ throw generalException(e);
+
+ } // end catch
+ finally
+ { // shut everything down
+ SQLUtils.shutdown(rs);
+ SQLUtils.shutdown(stmt);
+ SQLUtils.shutdown(conn);
+
+ } // end finally
+
+ } // end isModuleInstalled
+
+ Set getInstalledModules() throws DatabaseException
+ {
+ Connection conn = null;
+ PreparedStatement stmt = null;
+ ResultSet rs = null;
+ try
+ { // get a connection
+ conn = getConnection();
+
+ // prepare and execute the query
+ stmt = conn.prepareStatement("SELECT filename FROM modinstall ORDER BY filename;");
+ rs = stmt.executeQuery();
+
+ // output the set in sorted order
+ TreeSet rc = new TreeSet();
+ while (rs.next())
+ rc.add(rs.getString(1));
+ return Collections.unmodifiableSet(rc);
+
+ } // end try
+ catch (SQLException e)
+ { // translate to a general DatabaseException
+ throw generalException(e);
+
+ } // end catch
+ finally
+ { // shut everything down
+ SQLUtils.shutdown(rs);
+ SQLUtils.shutdown(stmt);
+ SQLUtils.shutdown(conn);
+
+ } // end finally
+
+ } // end getInstalledModules
+
+ void markInstalled(String filename, int nsid, String name) throws DatabaseException
+ {
+ Connection conn = null;
+ PreparedStatement stmt = null;
+ Statement stmt2 = null;
+ ResultSet rs = null;
+ try
+ { // get a connection
+ conn = getConnection();
+
+ // lock the database table
+ stmt2 = conn.createStatement();
+ stmt2.executeUpdate("LOCK TABLES modinstall WRITE;");
+
+ // execute the update
+ stmt = conn.prepareStatement("INSERT INTO modinstall (filename, mod_nsid, mod_name) VALUES (?, ?, ?);");
+ stmt.setString(1,filename);
+ stmt.setInt(2,nsid);
+ stmt.setString(3,name);
+ stmt.executeUpdate();
+
+ } // end try
+ catch (SQLException e)
+ { // translate to a general DatabaseException
+ throw generalException(e);
+
+ } // end catch
+ finally
+ { // shut everything down
+ MySQLUtils.unlockTables(conn);
+ SQLUtils.shutdown(rs);
+ SQLUtils.shutdown(stmt);
+ SQLUtils.shutdown(stmt2);
+ SQLUtils.shutdown(conn);
+
+ } // end finally
+
+ } // end markInstalled
+
+ void unmarkInstalled(String filename) throws DatabaseException
+ {
+ Connection conn = null;
+ PreparedStatement stmt = null;
+ Statement stmt2 = null;
+ ResultSet rs = null;
+ try
+ { // get a connection
+ conn = getConnection();
+
+ // lock the database table
+ stmt2 = conn.createStatement();
+ stmt2.executeUpdate("LOCK TABLES modinstall WRITE;");
+
+ // execute the update
+ stmt = conn.prepareStatement("DELETE FROM modinstall WHERE filename = ?;");
+ stmt.setString(1,filename);
+ stmt.executeUpdate();
+
+ } // end try
+ catch (SQLException e)
+ { // translate to a general DatabaseException
+ throw generalException(e);
+
+ } // end catch
+ finally
+ { // shut everything down
+ MySQLUtils.unlockTables(conn);
+ SQLUtils.shutdown(rs);
+ SQLUtils.shutdown(stmt);
+ SQLUtils.shutdown(stmt2);
+ SQLUtils.shutdown(conn);
+
+ } // end finally
+
+ } // end unmarkInstalled
+
+} // end class ModuleDBOps_mysql
diff --git a/src/dynamo-framework/com/silverwrist/dynamo/module/ModuleLoader.java b/src/dynamo-framework/com/silverwrist/dynamo/module/ModuleLoader.java
index 3e4d6c6..1a36ead 100644
--- a/src/dynamo-framework/com/silverwrist/dynamo/module/ModuleLoader.java
+++ b/src/dynamo-framework/com/silverwrist/dynamo/module/ModuleLoader.java
@@ -22,6 +22,7 @@ import java.net.*;
import java.security.Principal;
import java.util.jar.*;
import org.apache.log4j.Logger;
+import com.silverwrist.dynamo.db.NamespaceCache;
import com.silverwrist.dynamo.except.*;
import com.silverwrist.dynamo.iface.*;
import com.silverwrist.dynamo.util.*;
@@ -112,6 +113,9 @@ class ModuleLoader extends URLClassLoader implements Module
*--------------------------------------------------------------------------------
*/
+ private ModuleDBOps m_ops; // module operations
+ private NamespaceCache m_nscache; // namespace cache
+ private ServiceProvider m_install_svcs; // reference to installer services
private URL m_jar_url; // URL to the module JAR file
private String m_filename; // filename of the original JAR file relative to module directory
private String m_resource_path; // resource path for the JAR file
@@ -123,11 +127,15 @@ class ModuleLoader extends URLClassLoader implements Module
*--------------------------------------------------------------------------------
*/
- ModuleLoader(File modfile, String filename) throws ModuleException, MalformedURLException
+ ModuleLoader(File modfile, String filename, ModuleDBOps ops, NamespaceCache nscache, ServiceProvider install_svcs)
+ throws ModuleException, MalformedURLException
{
super(new URL[] { modfile.toURL() },ModuleLoader.class.getClassLoader());
logger.info("Loading module " + modfile.getAbsolutePath());
m_filename = filename;
+ m_ops = ops;
+ m_nscache = nscache;
+ m_install_svcs = install_svcs;
String main_class_name = null;
try
{ // create a JAR URL and use it to get the JAR attributes
@@ -276,9 +284,12 @@ class ModuleLoader extends URLClassLoader implements Module
} // end getModuleID
- public void install(ServiceProvider services, Principal installer) throws ModuleException
+ public synchronized void install(Principal installer) throws DatabaseException, ModuleException
{
- if (!(m_modfuncs.canInstall(services,installer)))
+ if (m_ops.isModuleInstalled(m_filename))
+ return; // already installed
+
+ if (!(m_modfuncs.canInstall(m_install_svcs,installer)))
{ // you are not permitted to install or uninstall modules
ModuleException me = new ModuleException(ModuleLoader.class,"ModuleMessages","module.noAuth");
me.setParameter(0,m_modfuncs.getModuleID().toString());
@@ -295,15 +306,20 @@ class ModuleLoader extends URLClassLoader implements Module
} // end if
ModuleSite s = new Site();
- m_modfuncs.install(s,services,installer);
- m_modfuncs.initialize(s,services);
+ m_modfuncs.install(s,m_install_svcs,installer);
+ QualifiedNameKey name = m_modfuncs.getModuleID();
+ m_ops.markInstalled(m_filename,m_nscache.namespaceNameToId(name.getNamespace()),name.getName());
+ m_modfuncs.initialize(s,m_install_svcs);
m_initialized = true;
} // end install
- public void uninstall(ServiceProvider services, Principal uninstaller) throws ModuleException
+ public synchronized void uninstall(Principal uninstaller) throws DatabaseException, ModuleException
{
- if (!(m_modfuncs.canInstall(services,uninstaller)))
+ if (!(m_ops.isModuleInstalled(m_filename)))
+ return; // already uninstalled
+
+ if (!(m_modfuncs.canInstall(m_install_svcs,uninstaller)))
{ // you are not permitted to install or uninstall modules
ModuleException me = new ModuleException(ModuleLoader.class,"ModuleMessages","module.noAuth");
me.setParameter(0,m_modfuncs.getModuleID().toString());
@@ -318,7 +334,8 @@ class ModuleLoader extends URLClassLoader implements Module
} // end if
- m_modfuncs.uninstall(new Site(),services,uninstaller);
+ m_modfuncs.uninstall(new Site(),m_install_svcs,uninstaller);
+ m_ops.unmarkInstalled(m_filename);
} // end uninstall
@@ -347,6 +364,14 @@ class ModuleLoader extends URLClassLoader implements Module
} // end shutdown
+ void dispose()
+ {
+ m_ops = null;
+ m_nscache = null;
+ m_modfuncs = null;
+
+ } // end dispose
+
boolean isInitialized()
{
return m_initialized;
diff --git a/src/dynamo-framework/com/silverwrist/dynamo/module/ModuleManager.java b/src/dynamo-framework/com/silverwrist/dynamo/module/ModuleManager.java
index 865fa6a..44fd557 100644
--- a/src/dynamo-framework/com/silverwrist/dynamo/module/ModuleManager.java
+++ b/src/dynamo-framework/com/silverwrist/dynamo/module/ModuleManager.java
@@ -21,16 +21,25 @@ import java.io.*;
import java.net.MalformedURLException;
import java.util.*;
import java.util.jar.*;
+import org.apache.log4j.Logger;
import org.w3c.dom.*;
import com.silverwrist.util.xml.*;
import com.silverwrist.dynamo.Namespaces;
import com.silverwrist.dynamo.app.ApplicationContainer;
+import com.silverwrist.dynamo.db.NamespaceCache;
import com.silverwrist.dynamo.except.*;
import com.silverwrist.dynamo.iface.*;
import com.silverwrist.dynamo.util.*;
public class ModuleManager implements NamedObject, ComponentInitialize, ComponentShutdown, ModuleOperations
{
+ /*--------------------------------------------------------------------------------
+ * Static data members
+ *--------------------------------------------------------------------------------
+ */
+
+ private static Logger logger = Logger.getLogger(ModuleManager.class);
+
/*--------------------------------------------------------------------------------
* Attributes
*--------------------------------------------------------------------------------
@@ -38,9 +47,13 @@ public class ModuleManager implements NamedObject, ComponentInitialize, Componen
private String m_name;
private ApplicationContainer m_appcon;
+ private NamespaceCache m_nscache;
+ private ModuleDBOps m_ops;
private File m_mod_dir;
private HashMap m_jar_to_module = new HashMap();
private HashMap m_qname_to_module = new HashMap();
+ private InstallServiceManager m_instservice;
+ private ServiceProvider m_install_services;
private ComponentShutdown m_shut1;
private ComponentShutdown m_shut2;
private ComponentShutdown m_shut3;
@@ -140,7 +153,7 @@ public class ModuleManager implements NamedObject, ComponentInitialize, Componen
public void initialize(Element config_root, ServiceProvider services) throws ConfigException
{
XMLLoader loader = XMLLoader.get();
- String mod_dir = null;
+ String mod_dir = null, conn_name = null, nscache_name = null;
try
{ // verify the right node name
loader.verifyNodeName(config_root,"object");
@@ -151,6 +164,12 @@ public class ModuleManager implements NamedObject, ComponentInitialize, Componen
// get the raw template directory
mod_dir = loader.getSubElementText(config_root,"module-directory");
+ // get the database configuration connection
+ DOMElementHelper config_root_h = new DOMElementHelper(config_root);
+ Element elt = loader.getSubElement(config_root_h,"database");
+ conn_name = loader.getAttribute(elt,"connection");
+ nscache_name = loader.getAttribute(elt,"namespaces");
+
} // end try
catch (XMLLoadException e)
{ // error loading XML config data
@@ -158,6 +177,14 @@ public class ModuleManager implements NamedObject, ComponentInitialize, Componen
} // end catch
+ // Get the database connection pool and namespace cache.
+ DBConnectionPool pool = GetObjectUtils.getDatabaseConnection(services,conn_name);
+ m_nscache =
+ (NamespaceCache)(GetObjectUtils.getDynamoComponent(services,NamespaceCache.class,nscache_name));
+
+ // Get the database operations object.
+ m_ops = ModuleDBOps.get(pool);
+
// Get the application container.
ObjectProvider op = (ObjectProvider)(services.queryService(ObjectProvider.class));
m_appcon = (ApplicationContainer)(op.getObject(Namespaces.DYNAMO_APPLICATION_NAMESPACE,"__container__"));
@@ -172,6 +199,10 @@ public class ModuleManager implements NamedObject, ComponentInitialize, Componen
} // end if
+ // Get the install service manager and set up the install service provider.
+ m_instservice = new InstallServiceManager();
+ m_install_services = m_instservice.getServiceProvider(m_appcon.getInitServices());
+
// Hook this into the service providers.
SingletonServiceProvider ssp = new SingletonServiceProvider("ModuleManager",ModuleOperations.class,this);
HookServiceProviders hooker = (HookServiceProviders)(services.queryService(HookServiceProviders.class));
@@ -199,6 +230,7 @@ public class ModuleManager implements NamedObject, ComponentInitialize, Componen
ModuleLoader ml = (ModuleLoader)(tmp.removeFirst());
if (ml.isInitialized())
ml.shutdown();
+ ml.dispose();
} // end while
@@ -209,6 +241,12 @@ public class ModuleManager implements NamedObject, ComponentInitialize, Componen
m_shut2 = null;
m_shut1.shutdown();
m_shut1 = null;
+ m_install_services = null;
+ m_instservice.dispose();
+ m_instservice = null;
+ m_ops.dispose();
+ m_ops = null;
+ m_nscache = null;
m_appcon = null;
} // end shutdown
@@ -254,7 +292,7 @@ public class ModuleManager implements NamedObject, ComponentInitialize, Componen
try
{ // create a new ModuleLoader
- rc = new ModuleLoader(mod_file,name);
+ rc = new ModuleLoader(mod_file,name,m_ops,m_nscache,m_install_services);
} // end try
catch (MalformedURLException e)
@@ -304,6 +342,7 @@ public class ModuleManager implements NamedObject, ComponentInitialize, Componen
m_qname_to_module.remove(ntry.getValue());
if (ml.isInitialized())
ml.shutdown();
+ ml.dispose();
} // end while
@@ -340,4 +379,31 @@ public class ModuleManager implements NamedObject, ComponentInitialize, Componen
} // end listAllModuleNames
+ public Set listInstalledModuleNames() throws DatabaseException
+ {
+ return m_ops.getInstalledModules();
+
+ } // end listInstalledModuleNames
+
+ public void loadInstalledModules() throws DatabaseException, ModuleException
+ {
+ Set set = m_ops.getInstalledModules();
+ logger.info("loadInstalledModules(): " + set.size() + " module(s) to load");
+ Iterator it = set.iterator();
+ while (it.hasNext())
+ { // load each of the installed modules in turn
+ String mod_filename = (String)(it.next());
+ logger.info("loadInstalledModules(): loading " + mod_filename);
+ this.loadModule(mod_filename,true);
+
+ } // end while
+
+ } // end loadInstalledModules
+
+ public ComponentShutdown hookInstallServices(ServiceProvider sp)
+ {
+ return m_instservice.hook(sp);
+
+ } // end hookInstallServices
+
} // end class ModuleManager
diff --git a/src/dynamo-framework/com/silverwrist/dynamo/module/ModuleOperations.java b/src/dynamo-framework/com/silverwrist/dynamo/module/ModuleOperations.java
index 8ec54eb..1c7c13a 100644
--- a/src/dynamo-framework/com/silverwrist/dynamo/module/ModuleOperations.java
+++ b/src/dynamo-framework/com/silverwrist/dynamo/module/ModuleOperations.java
@@ -18,8 +18,12 @@
package com.silverwrist.dynamo.module;
import java.util.List;
+import java.util.Set;
+import com.silverwrist.dynamo.except.DatabaseException;
import com.silverwrist.dynamo.except.ModuleException;
+import com.silverwrist.dynamo.iface.ComponentShutdown;
import com.silverwrist.dynamo.iface.Module;
+import com.silverwrist.dynamo.iface.ServiceProvider;
public interface ModuleOperations
{
@@ -31,4 +35,10 @@ public interface ModuleOperations
public List listAllModuleNames();
+ public Set listInstalledModuleNames() throws DatabaseException;
+
+ public void loadInstalledModules() throws DatabaseException, ModuleException;
+
+ public ComponentShutdown hookInstallServices(ServiceProvider sp);
+
} // end interface ModuleOperations
diff --git a/src/dynamo-framework/com/silverwrist/dynamo/app/ServiceKey.java b/src/dynamo-framework/com/silverwrist/dynamo/util/ServiceKey.java
similarity index 90%
rename from src/dynamo-framework/com/silverwrist/dynamo/app/ServiceKey.java
rename to src/dynamo-framework/com/silverwrist/dynamo/util/ServiceKey.java
index 1eeeddb..8fbac8c 100644
--- a/src/dynamo-framework/com/silverwrist/dynamo/app/ServiceKey.java
+++ b/src/dynamo-framework/com/silverwrist/dynamo/util/ServiceKey.java
@@ -11,13 +11,13 @@
*
* The Initial Developer of the Original Code is Eric J. Bowersox ,
* for Silverwrist Design Studios. Portions created by Eric J. Bowersox are
- * Copyright (C) 2002 Eric J. Bowersox/Silverwrist Design Studios. All Rights Reserved.
+ * Copyright (C) 2002-03 Eric J. Bowersox/Silverwrist Design Studios. All Rights Reserved.
*
* Contributor(s):
*/
-package com.silverwrist.dynamo.app;
+package com.silverwrist.dynamo.util;
-class ServiceKey
+public class ServiceKey
{
/*--------------------------------------------------------------------------------
* Attributes
@@ -32,7 +32,7 @@ class ServiceKey
*--------------------------------------------------------------------------------
*/
- ServiceKey(Class klass, String serviceid)
+ public ServiceKey(Class klass, String serviceid)
{
m_class = klass;
m_serviceid = serviceid;
diff --git a/src/venice-base/com/silverwrist/venice/app/VeniceAppMessages.properties b/src/venice-base/com/silverwrist/venice/app/VeniceAppMessages.properties
index d780626..0da3c56 100644
--- a/src/venice-base/com/silverwrist/venice/app/VeniceAppMessages.properties
+++ b/src/venice-base/com/silverwrist/venice/app/VeniceAppMessages.properties
@@ -26,3 +26,5 @@ xtitle.mail=Mail Error
xtitle.script=Scripting Error
xtitle.style=Style Sheet Error
xtitle.valid=Validation Error
+module.dbfail=Unable to retrieve the installed module names from the database: {0}
+module.initfail=Module initialization failure: {0}
diff --git a/src/venice-base/com/silverwrist/venice/app/VeniceApplication.java b/src/venice-base/com/silverwrist/venice/app/VeniceApplication.java
index f3b86bf..526dfde 100644
--- a/src/venice-base/com/silverwrist/venice/app/VeniceApplication.java
+++ b/src/venice-base/com/silverwrist/venice/app/VeniceApplication.java
@@ -25,6 +25,7 @@ import com.silverwrist.dynamo.db.UserPropertyTranslator;
import com.silverwrist.dynamo.db.UserPropertyTranslatorInstall;
import com.silverwrist.dynamo.except.*;
import com.silverwrist.dynamo.iface.*;
+import com.silverwrist.dynamo.module.ModuleOperations;
import com.silverwrist.dynamo.util.*;
import com.silverwrist.dynamo.velocity.VelocityRendererConfig;
import com.silverwrist.venice.VeniceNamespaces;
@@ -112,6 +113,27 @@ public class VeniceApplication implements ComponentShutdown, Application, Styles
(VelocityRendererConfig)(services.queryService(VelocityRendererConfig.class));
m_shutdown_list.addFirst(vrcon.addStandardComponentClass("datefmt",DateFormatterTopHalf.class));
+ try
+ { // Call down to the module manager to load and initialize all installed modules.
+ ModuleOperations modops = (ModuleOperations)(services.queryService(ModuleOperations.class));
+ modops.loadInstalledModules();
+
+ } // end try
+ catch (DatabaseException de)
+ { // error in database
+ ConfigException ce = new ConfigException(VeniceApplication.class,"VeniceAppMessages","module.dbfail",de);
+ ce.setParameter(0,de.getMessage());
+ throw ce;
+
+ } // end catch
+ catch (ModuleException me)
+ { // error initializing the modules
+ ConfigException ce = new ConfigException(VeniceApplication.class,"VeniceAppMessages","module.initfail",me);
+ ce.setParameter(0,me.getMessage());
+ throw ce;
+
+ } // end catch
+
// Done with initialization
logger.info("Venice application '" + m_name + "' initialization done");