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/dynamo-venice.xml b/conf/dynamo-venice.xml index b8a365e..6d9e12b 100644 --- a/conf/dynamo-venice.xml +++ b/conf/dynamo-venice.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");