From 3752e73c2d006f41989dbafcc9a052cf525f7b28 Mon Sep 17 00:00:00 2001 From: "Eric J. Bowersox" Date: Wed, 21 Nov 2001 09:47:27 +0000 Subject: [PATCH] the first real phase of service integration - mostly it's the configuration file, the bare beginnings of the Service Control Manager on the server side, and the new "community left menu" on the client side (still controlled by the existing feature mechanism, for now). The engine still needs to incorporate the SCM in place of the old feature definitions. Also added some utility classes (StockMessage, XMLLoader) to aid with loading XML data from the config files (big help in the RenderConfig constructor and VeniceEngineImpl.initialize!) --- etc/render-config.xml | 3 + etc/services-config.xml | 62 ++ etc/venice-config.xml | 7 +- .../silverwrist/util/DOMElementHelper.java | 82 ++- src/com/silverwrist/util/StockMessages.java | 85 +++ src/com/silverwrist/venice/core/Startup.java | 145 +---- .../silverwrist/venice/core/VeniceEngine.java | 2 + .../core/impl/ServiceControlManager.java | 144 +++++ .../venice/core/impl/StaticCommService.java | 135 +++++ .../venice/core/impl/VeniceEngineImpl.java | 337 ++++------- .../venice/servlets/Variables.java | 25 +- .../venice/servlets/VeniceServlet.java | 2 +- .../venice/servlets/format/RenderConfig.java | 539 ++++++------------ .../CommunityLeftMenu.java} | 28 +- .../format/menus/CommunityLeftMenuEntry.java | 117 ++++ .../menus/CommunityLeftMenuFactory.java | 130 +++++ .../servlets/format/menus/LinkItem.java | 13 +- .../silverwrist/venice/svc/CommService.java | 35 ++ .../venice/svc/CommServiceSite.java | 22 + .../silverwrist/venice/util/XMLLoader.java | 235 ++++++++ 20 files changed, 1416 insertions(+), 732 deletions(-) create mode 100644 etc/services-config.xml create mode 100644 src/com/silverwrist/util/StockMessages.java create mode 100644 src/com/silverwrist/venice/core/impl/ServiceControlManager.java create mode 100644 src/com/silverwrist/venice/core/impl/StaticCommService.java rename src/com/silverwrist/venice/servlets/format/{MenuCommunity.java => menus/CommunityLeftMenu.java} (83%) create mode 100644 src/com/silverwrist/venice/servlets/format/menus/CommunityLeftMenuEntry.java create mode 100644 src/com/silverwrist/venice/servlets/format/menus/CommunityLeftMenuFactory.java create mode 100644 src/com/silverwrist/venice/svc/CommService.java create mode 100644 src/com/silverwrist/venice/svc/CommServiceSite.java create mode 100644 src/com/silverwrist/venice/util/XMLLoader.java diff --git a/etc/render-config.xml b/etc/render-config.xml index 5b70984..bc2ec98 100644 --- a/etc/render-config.xml +++ b/etc/render-config.xml @@ -97,6 +97,9 @@ Image should be 100x100 pixels. --> photo_not_avail.gif + + WEB-INF/services-config.xml + diff --git a/etc/services-config.xml b/etc/services-config.xml new file mode 100644 index 0000000..d64b7f8 --- /dev/null +++ b/etc/services-config.xml @@ -0,0 +1,62 @@ + + + + + + + + + + + + + Profile + + + + + + + Administration + + + + + + + System Administration + + + + + + + Conferences + + + + + + + Members + + + + + \ No newline at end of file diff --git a/etc/venice-config.xml b/etc/venice-config.xml index 6df7b8d..9d5d913 100644 --- a/etc/venice-config.xml +++ b/etc/venice-config.xml @@ -26,6 +26,9 @@ WEB-INF/sidebox-config.xml + + + WEB-INF/services-config.xml @@ -303,8 +306,8 @@ main dictionary. The default lexicon is a standard US English one, with a supplemental list of words provided by Erbo. --> - /home/erbo/venice/WEB-INF/en-us.dict - /home/erbo/venice/WEB-INF/erbo.dict + WEB-INF/en-us.dict + WEB-INF/erbo.dict diff --git a/src/com/silverwrist/util/DOMElementHelper.java b/src/com/silverwrist/util/DOMElementHelper.java index 0d59a4c..28ee6ae 100644 --- a/src/com/silverwrist/util/DOMElementHelper.java +++ b/src/com/silverwrist/util/DOMElementHelper.java @@ -27,7 +27,7 @@ import org.w3c.dom.*; * @version X * @see org.w3c.dom.Element */ -public class DOMElementHelper +public final class DOMElementHelper { /*-------------------------------------------------------------------------------- * Attributes @@ -65,7 +65,7 @@ public class DOMElementHelper * @return The text content under this Element node. If the specified Element * has no text nodes underneath it, returns null. */ - private static String getTextOfElement(Element e) + private static final String getTextOfElement(Element e) { NodeList kids = e.getChildNodes(); if (kids==null) @@ -94,6 +94,30 @@ public class DOMElementHelper } // end getTextOfElement + /** + * Returns the value of the text of the specified Element, expressed as an integer. + * + * @param e The Element to extract text from. + * @return An Integer object containing the value of the specified element. If + * the Element has no text, or if the text cannot be expressed as an integer, + * returns null. + */ + private static final Integer getIntegerFromElement(Element e) + { + try + { // extract the text and create an Integer around it + String s = getTextOfElement(e); + return ((s==null) ? null : new Integer(s.trim())); + + } // end try + catch (NumberFormatException nfe) + { // value cannot be parsed as an integer + return null; + + } // end catch + + } // end getIntegerFromElement + /*-------------------------------------------------------------------------------- * External operations *-------------------------------------------------------------------------------- @@ -104,7 +128,7 @@ public class DOMElementHelper * * @return See above. */ - public Element getElement() + public final Element getElement() { return elt; @@ -118,7 +142,7 @@ public class DOMElementHelper * If the Element has no child Elements with the given name, * the method returns null. */ - public Element getSubElement(String name) + public final Element getSubElement(String name) { NodeList kids = elt.getChildNodes(); if (kids==null) @@ -142,12 +166,25 @@ public class DOMElementHelper * @return The text content under the wrapped Element node. If the wrapped Element * has not text nodes underneath it, returns null. */ - public String getElementText() + public final String getElementText() { return getTextOfElement(elt); } // end getElementText + /** + * Returns the value of the text of the wrapped Element, expressed as an integer. + * + * @return An Integer object containing the value of the wrapped element. If + * the Element has no text, or if the text cannot be expressed as an integer, + * returns null. + */ + public final Integer getElementInt() + { + return getIntegerFromElement(elt); + + } // end getElementInt + /** * Returns the content of all text nodes underneath the first sub-element of the wrapped * Element, with the given name, concatenated together into a single string. @@ -157,16 +194,30 @@ public class DOMElementHelper * If the wrapped Element does not have a sub-element with the given name, or * that sub-element has no text nodes underneath it, returns null. */ - public String getSubElementText(String name) + public final String getSubElementText(String name) { Element se = getSubElement(name); - if (se==null) - return null; - else - return getTextOfElement(se); + return ((se==null) ? null : getTextOfElement(se)); } // end getSubElementText + /** + * Returns the value of the text underneath the first sub-element of the wrapped + * Element, with the given name, expressed as an integer. + * + * @param name The name of the sub-element to search for. + * @return An Integer object containing the value of the specified element. If + * the wrapped Element does not have a sub-element with the given name, or that + * sub-element has no text, or if the text cannot be expressed as an integer, returns + * null. + */ + public final Integer getSubElementInt(String name) + { + Element se = getSubElement(name); + return ((se==null) ? null : getIntegerFromElement(se)); + + } // end getSubElementInt + /** * Determines whether the wrapped Element has a sub-element with the given name. * @@ -174,10 +225,9 @@ public class DOMElementHelper * @return true if the wrapped Element has a sub-element with the * specified name, false if not. */ - public boolean hasChildElement(String name) + public final boolean hasChildElement(String name) { - Element tmp = getSubElement(name); - return (tmp==null) ? false : true; + return (getSubElement(name)!=null); } // end hasChildElement @@ -188,7 +238,7 @@ public class DOMElementHelper * @return true if the wrapped Element has an attribute with the * specified name, false if not. */ - public boolean hasAttribute(String name) + public final boolean hasAttribute(String name) { return !(StringUtil.isStringEmpty(elt.getAttribute(name))); @@ -203,14 +253,14 @@ public class DOMElementHelper * the wrapped Element has no such attribute, or if the attribute's value * cannot be expressed as an integer, returns null. */ - public Integer getAttributeInt(String name) + public final Integer getAttributeInt(String name) { String tmp = elt.getAttribute(name); if (StringUtil.isStringEmpty(tmp)) return null; try { // convert to an Integer - return new Integer(tmp); + return new Integer(tmp.trim()); } // end try catch (NumberFormatException nfe) diff --git a/src/com/silverwrist/util/StockMessages.java b/src/com/silverwrist/util/StockMessages.java new file mode 100644 index 0000000..5524924 --- /dev/null +++ b/src/com/silverwrist/util/StockMessages.java @@ -0,0 +1,85 @@ +/* + * 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) 2001 Eric J. Bowersox/Silverwrist Design Studios. All Rights Reserved. + * + * Contributor(s): + */ +package com.silverwrist.util; + +import java.util.*; +import org.apache.log4j.*; +import org.w3c.dom.*; + +public final class StockMessages +{ + /*-------------------------------------------------------------------------------- + * Static data members + *-------------------------------------------------------------------------------- + */ + + private static Category logger = Category.getInstance(StockMessages.class); + + /*-------------------------------------------------------------------------------- + * Attributes + *-------------------------------------------------------------------------------- + */ + + private Map msgmap; + + /*-------------------------------------------------------------------------------- + * Constructor + *-------------------------------------------------------------------------------- + */ + + public StockMessages(Element elt) + { + HashMap tmp_msgmap = new HashMap(); + NodeList msgs = elt.getChildNodes(); + for (int i=0; i0) + msgmap = Collections.unmodifiableMap(tmp_msgmap); + else + msgmap = Collections.EMPTY_MAP; + + if (logger.isDebugEnabled()) + logger.debug(msgmap.size() + " stock message(s) loaded from <" + elt.getTagName() + "/> section"); + + } // end constructor + + public final String get(String name) + { + return (String)(msgmap.get(name)); + + } // end get + + public final String getReplace(String name, Map vars) + { + return StringUtil.replaceAllVariables((String)(msgmap.get(name)),vars); + + } // end getReplace + +} // end class StockMessages diff --git a/src/com/silverwrist/venice/core/Startup.java b/src/com/silverwrist/venice/core/Startup.java index b21d094..44bf698 100644 --- a/src/com/silverwrist/venice/core/Startup.java +++ b/src/com/silverwrist/venice/core/Startup.java @@ -17,14 +17,11 @@ */ package com.silverwrist.venice.core; -import java.io.*; -import javax.xml.parsers.*; import org.apache.log4j.*; import org.w3c.dom.*; -import org.xml.sax.SAXException; -import org.xml.sax.SAXParseException; import com.silverwrist.util.DOMElementHelper; import com.silverwrist.venice.except.*; +import com.silverwrist.venice.util.XMLLoader; public class Startup { @@ -45,126 +42,28 @@ public class Startup } // end constructor /*-------------------------------------------------------------------------------- - * Internal functions + * External static operations *-------------------------------------------------------------------------------- */ - private static String getEngineClassName(Document config) throws ConfigException - { - // Make sure the configuration is valid... - Element root = config.getDocumentElement(); - if (!(root.getTagName().equals("venice-config"))) - { // not the correct root tag name - logger.fatal("config document is not a document (root tag: <" - + root.getTagName() + "/>)"); - throw new ConfigException("document is not a document",root); - - } // end if - - // Get the section. - DOMElementHelper root_h = new DOMElementHelper(root); - Element engine_sect = root_h.getSubElement("engine"); - if (engine_sect==null) - { // no section - bail out now! - logger.fatal("config document has no section"); - throw new ConfigException("no section found in config file",root); - - } // end if - - // Get the classname out of that section. - DOMElementHelper engine_sect_h = new DOMElementHelper(engine_sect); - String rc = engine_sect_h.getSubElementText("classname"); - if (rc==null) - { // no specified - bail out now! - logger.fatal("config document section has no "); - throw new ConfigException("no found in section",engine_sect); - - } // end if - - return rc; - - } // end getEngineClassName - - /*-------------------------------------------------------------------------------- - * External static methods (global functions) - *-------------------------------------------------------------------------------- - */ - - public static Document loadConfiguration(String configname) throws ConfigException - { - try - { // create a simple DOM parser by using the Java XML parsing API - DocumentBuilderFactory fac = DocumentBuilderFactory.newInstance(); - fac.setNamespaceAware(false); - fac.setValidating(false); - DocumentBuilder parser = fac.newDocumentBuilder(); - - // access the config file and parse it into our config data tree - File configfile = new File(configname); - Document rc = parser.parse(configfile); - if (logger.isDebugEnabled()) - logger.debug("configuration loaded successfully"); - return rc; - - } // end try - catch (FactoryConfigurationError e1) - { // if the document builder factory could not be created - logger.fatal("Parser factory configuration error: " + e1.getMessage(),e1); - throw new ConfigException("XML parser factory could not be created - " + e1.getMessage()); - - } // end catch - catch (ParserConfigurationException e2) - { // if the XML parser itself could not be created - logger.fatal("Parser configuration error: " + e2.getMessage(),e2); - throw new ConfigException("XML parser could not be created - " + e2.getMessage(),e2); - - } // end catch - catch (SAXException e3) - { // if the XML parser choked on our document - if (e3 instanceof SAXParseException) - { // we have a detailed message - make a proper exception - SAXParseException e3a = (SAXParseException)e3; - logger.fatal("Config file error [" + configname + ":" + e3a.getLineNumber() + "," - + e3a.getColumnNumber() + "]: " + e3a.getMessage(),e3a); - throw new ConfigException("Configuration file error: " + e3a.getMessage() + " at line " - + e3a.getLineNumber() + ", column " + e3a.getColumnNumber(),e3a); - - } // end if - else - { // generic exception - just send up a simple error message - logger.fatal("Config file error [" + configname + "]: " + e3.getMessage(),e3); - throw new ConfigException("Configuration file error - " + e3.getMessage(),e3); - - } // end else - - } // end catch - catch (IOException e4) - { // error reading the config file itself off the disk - logger.fatal("IO error reading config: " + e4.getMessage(),e4); - throw new ConfigException("unable to read config file \"" + configname + "\" - " + e4.getMessage(),e4); - - } // end catch - - } // end loadConfiguration - public static VeniceEngine createEngine(String configname, String app_root) throws ConfigException, DataException { + XMLLoader loader = XMLLoader.get(); + // load the configuration data - Document config = loadConfiguration(configname); + Document config = loader.loadConfigDocument(configname); // find the classname of the engine - String cname = getEngineClassName(config); - + Element root = loader.configGetRootElement(config,"venice-config"); + Element sect = loader.configGetSubSection(root,"engine"); + String cname = loader.configGetSubElementText(sect,"classname"); if (logger.isDebugEnabled()) logger.debug("Venice engine classname: " + cname); try - { // attempt to load the engine class - Class engine_class = Class.forName(cname); - - // now create a new Venice engine (cast to the external interface) - VeniceEngine engine = (VeniceEngine)(engine_class.newInstance()); + { // create a new Venice engine (cast to the external interface) + VeniceEngine engine = (VeniceEngine)(Class.forName(cname).newInstance()); if (logger.isDebugEnabled()) logger.debug("VeniceEngine created successfully"); @@ -176,39 +75,39 @@ public class Startup return engine; } // end try - catch (ClassNotFoundException e1) + catch (ClassNotFoundException cnfe) { // the class was not found - logger.fatal("Venice engine class \"" + cname + "\" not found",e1); + logger.fatal("Venice engine class \"" + cname + "\" not found",cnfe); throw new ConfigException("Invalid engine classname: " + cname); } // end catch - catch (IllegalAccessException e2) + catch (IllegalAccessException iae) { // could not access constructor or something - logger.fatal("Can't access \"" + cname + "\" constructor: " + e2.getMessage(),e2); + logger.fatal("Can't access \"" + cname + "\" constructor: " + iae.getMessage(),iae); throw new ConfigException("Unable to create classname: " + cname); } // end catch - catch (InstantiationException e3) + catch (InstantiationException ie) { // could not create the instance - logger.fatal("Can't create instance of \"" + cname + "\": " + e3.getMessage(),e3); + logger.fatal("Can't create instance of \"" + cname + "\": " + ie.getMessage(),ie); throw new ConfigException("Unable to create classname: " + cname); } // end catch - catch (ExceptionInInitializerError e4) + catch (ExceptionInInitializerError eiie) { // some exception while initializing class - logger.fatal("Exception while initializing \"" + cname + "\": " + e4.getMessage(),e4); + logger.fatal("Exception while initializing \"" + cname + "\": " + eiie.getMessage(),eiie); throw new ConfigException("Unable to create classname: " + cname); } // end catch - catch (SecurityException e5) + catch (SecurityException se) { // security violation somewhere - logger.fatal("Security violation on \"" + cname + "\": " + e5.getMessage(),e5); + logger.fatal("Security violation on \"" + cname + "\": " + se.getMessage(),se); throw new ConfigException("Unable to create classname: " + cname); } // end catch - catch (ClassCastException e6) + catch (ClassCastException cce) { // engine could not be cast to VeniceEngine interface type - logger.fatal("\"" + cname + "\" is not of type VeniceEngine",e6); + logger.fatal("\"" + cname + "\" is not of type VeniceEngine",cce); throw new ConfigException("Invalid engine classname: " + cname); } // end catch diff --git a/src/com/silverwrist/venice/core/VeniceEngine.java b/src/com/silverwrist/venice/core/VeniceEngine.java index df008ed..b5d8e82 100644 --- a/src/com/silverwrist/venice/core/VeniceEngine.java +++ b/src/com/silverwrist/venice/core/VeniceEngine.java @@ -31,6 +31,8 @@ public interface VeniceEngine extends SearchMode { public abstract void initialize(Document config, String app_root) throws ConfigException, DataException; + public abstract void shutdown() throws ConfigException; + public abstract int getNumFeatures(); public abstract BitSet getAllFeaturesMask(); diff --git a/src/com/silverwrist/venice/core/impl/ServiceControlManager.java b/src/com/silverwrist/venice/core/impl/ServiceControlManager.java new file mode 100644 index 0000000..84020a4 --- /dev/null +++ b/src/com/silverwrist/venice/core/impl/ServiceControlManager.java @@ -0,0 +1,144 @@ +/* + * 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) 2001 Eric J. Bowersox/Silverwrist Design Studios. All Rights Reserved. + * + * Contributor(s): + */ +package com.silverwrist.venice.core.impl; + +import java.util.*; +import org.apache.log4j.*; +import org.w3c.dom.*; +import com.silverwrist.util.*; +import com.silverwrist.venice.except.*; +import com.silverwrist.venice.security.*; +import com.silverwrist.venice.svc.*; +import com.silverwrist.venice.util.XMLLoader; + +class ServiceControlManager +{ + /*-------------------------------------------------------------------------------- + * Internal "Community Service Site" class + *-------------------------------------------------------------------------------- + */ + + class MyCommServiceSite implements CommServiceSite + { + MyCommServiceSite() + { // do nothing + } // end constructor + + } // end class MyCommServiceSite + + /*-------------------------------------------------------------------------------- + * Static data members + *-------------------------------------------------------------------------------- + */ + + private static Category logger = Category.getInstance(ServiceControlManager.class); + + /*-------------------------------------------------------------------------------- + * Attributes + *-------------------------------------------------------------------------------- + */ + + private Map comm_symbol_to_service; + private Map comm_index_to_service; + + /*-------------------------------------------------------------------------------- + * Constructors + *-------------------------------------------------------------------------------- + */ + + ServiceControlManager(Document cfg, SecurityMonitor sm_global, SecurityMonitor sm_comm) + throws ConfigException + { + XMLLoader loader = XMLLoader.get(); + Element root = loader.configGetRootElement(cfg,"services-config"); + DOMElementHelper root_h = new DOMElementHelper(root); + NodeList nl; + int i; + + // Get the "community" section + Element sect = root_h.getSubElement("community"); + if (sect!=null) + { // load the services for the section + HashMap tmp_symbol_to_service = new HashMap(); + HashMap tmp_index_to_service = new HashMap(); + nl = sect.getChildNodes(); + for (i=0; i0) + comm_symbol_to_service = Collections.unmodifiableMap(tmp_symbol_to_service); + else + comm_symbol_to_service = Collections.EMPTY_MAP; + if (tmp_index_to_service.size()>0) + comm_index_to_service = Collections.unmodifiableMap(tmp_index_to_service); + else + comm_index_to_service = Collections.EMPTY_MAP; + + } // end if + else + { // no community services - undo this + comm_symbol_to_service = Collections.EMPTY_MAP; + comm_index_to_service = Collections.EMPTY_MAP; + + } // end else + + } // end constructor + + /*-------------------------------------------------------------------------------- + * Internal operations + *-------------------------------------------------------------------------------- + */ + + private CommService initCommunityService(Element root, SecurityMonitor sm) throws ConfigException + { + CommService svc; + // FUTURE: do a create of a specific class + svc = new StaticCommService(); + svc.initialize(root,sm,new MyCommServiceSite()); + return svc; + + } // end initCommunityService + + /*-------------------------------------------------------------------------------- + * External operations + *-------------------------------------------------------------------------------- + */ + + public final void shutdown() + { + Iterator it = comm_symbol_to_service.values().iterator(); + while (it.hasNext()) + { // shut down each service in turn + CommService svc = (CommService)(it.next()); + svc.shutdown(); + + } // end while + + } // end shutdown + +} // end class ServiceControlManager diff --git a/src/com/silverwrist/venice/core/impl/StaticCommService.java b/src/com/silverwrist/venice/core/impl/StaticCommService.java new file mode 100644 index 0000000..6fe115e --- /dev/null +++ b/src/com/silverwrist/venice/core/impl/StaticCommService.java @@ -0,0 +1,135 @@ +/* + * 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) 2001 Eric J. Bowersox/Silverwrist Design Studios. All Rights Reserved. + * + * Contributor(s): + */ +package com.silverwrist.venice.core.impl; + +import org.w3c.dom.*; +import com.silverwrist.util.*; +import com.silverwrist.venice.except.*; +import com.silverwrist.venice.security.*; +import com.silverwrist.venice.svc.*; +import com.silverwrist.venice.util.XMLLoader; + +class StaticCommService implements CommService +{ + /*-------------------------------------------------------------------------------- + * Attributes + *-------------------------------------------------------------------------------- + */ + + private String symbol; + private int index; + private boolean is_default; + private boolean is_locked; + private SecurityMonitor secmon; + private String permission; + private Role role; + + /*-------------------------------------------------------------------------------- + * Constructor + *-------------------------------------------------------------------------------- + */ + + public StaticCommService() + { + } // end constructor + + /*-------------------------------------------------------------------------------- + * Implementations from interface CommunityService + *-------------------------------------------------------------------------------- + */ + + public void initialize(Element root, SecurityMonitor sm, CommServiceSite site) throws ConfigException + { + XMLLoader loader = XMLLoader.get(); + + // Load the symbol and index from the root element. + symbol = loader.configGetAttribute(root,"id"); + index = loader.configGetAttributeInt(root,"index"); + + // Get the setup from the subelement. + DOMElementHelper h = new DOMElementHelper(root); + Element sub = h.getSubElement("setup"); + if (sub!=null) + { // read the values of the "default" and "locked" flags + DOMElementHelper h2 = new DOMElementHelper(sub); + is_default = h2.hasAttribute("default"); + is_locked = h2.hasAttribute("locked"); + + } // end if + else + { // default those two flags + is_default = false; + is_locked = false; + + } // end else + + // Get the access control element from the subelement. + sub = h.getSubElement("access"); + if (sub!=null) + { // get the attributes... + DOMElementHelper h3 = new DOMElementHelper(sub); + if (h3.hasAttribute("permission")) + { // get the permission and verify that it exists + permission = sub.getAttribute("permission"); + if (!(sm.permissionDefined(permission,false))) + throw new ConfigException("permission \"" + permission + "\" is not defined",sub); + + } // end if + else // just null out the permission + permission = null; + + if (h3.hasAttribute("role")) + { // get the role and verify that it exists + role = sm.getRole(sub.getAttribute("role")); + if (role==null) + throw new ConfigException("role \"" + sub.getAttribute("role") + "\" is not defined",sub); + + } // end if + else // default the role + role = sm.getRole("NotInList"); + + } // end if + else + { // default the values + permission = null; + role = sm.getRole("NotInList"); + + } // end else + + // Save the security monitor reference. + secmon = sm; + + } // end initialize + + public void shutdown() + { // do nothing + } // end shutdown + + public String getSymbol() + { + return symbol; + + } // end getSymbol + + public int getIndex() + { + return index; + + } // end getIndex + +} // end class StaticCommService diff --git a/src/com/silverwrist/venice/core/impl/VeniceEngineImpl.java b/src/com/silverwrist/venice/core/impl/VeniceEngineImpl.java index fb61357..a448d4b 100644 --- a/src/com/silverwrist/venice/core/impl/VeniceEngineImpl.java +++ b/src/com/silverwrist/venice/core/impl/VeniceEngineImpl.java @@ -32,6 +32,7 @@ import com.silverwrist.venice.htmlcheck.*; import com.silverwrist.venice.htmlcheck.dict.*; import com.silverwrist.venice.htmlcheck.filters.*; import com.silverwrist.venice.security.*; +import com.silverwrist.venice.util.XMLLoader; public class VeniceEngineImpl implements VeniceEngine, EngineBackend { @@ -143,37 +144,13 @@ public class VeniceEngineImpl implements VeniceEngine, EngineBackend MasterSideBox(Element section) throws ConfigException { - try - { // get the ID value for this sidebox - String tmp = section.getAttribute("id"); - if (StringUtil.isStringEmpty(tmp)) - { // there's no - logger.fatal(" specified with no ID!"); - throw new ConfigException("no ID specified in ",section); - - } // end if - - id = Integer.parseInt(tmp); - - } // end try - catch (NumberFormatException e) - { // sidebox ID not numeric - logger.fatal(" ID not numeric!"); - throw new ConfigException("non-numeric ID specified in ",section); - - } // end catch + XMLLoader loader = XMLLoader.get(); + id = loader.configGetAttributeInt(section,"id"); + // get the title and classname DOMElementHelper section_h = new DOMElementHelper(section); - title = section_h.getSubElementText("title"); - anon_title = section_h.getSubElementText("anon-title"); - classname = section_h.getSubElementText("factory-class"); - - if (StringUtil.isStringEmpty(title) || StringUtil.isStringEmpty(classname)) - { // the configuration is not complete - logger.fatal(" config incomplete (missing or <factory-class/>)!"); - throw new ConfigException("configuration of <sidebox/> is not complete!",section); - - } // end if + title = loader.configGetSubElementText(section_h,"title"); + classname = loader.configGetSubElementText(section_h,"factory-class"); try { // try to resolve the classname here so we can be sure it's cool @@ -187,6 +164,8 @@ public class VeniceEngineImpl implements VeniceEngine, EngineBackend } // end catch + // get the anonymous title and default it if it's not found + anon_title = section_h.getSubElementText("anon-title"); if (StringUtil.isStringEmpty(anon_title)) anon_title = title; // just set as the same in the event of difficulty @@ -218,35 +197,6 @@ public class VeniceEngineImpl implements VeniceEngine, EngineBackend } // end class MasterSideBox - /*-------------------------------------------------------------------------------- - * Internal class for returning side box information. - *-------------------------------------------------------------------------------- - */ - - static class MasterSideBoxList extends AbstractList - { - private MasterSideBox[] array; - - MasterSideBoxList(MasterSideBox[] array) - { - this.array = array; - - } // end constructor - - public Object get(int index) - { - return array[index]; - - } // end get - - public int size() - { - return array.length; - - } // end size - - } // end class MasterSideBoxList - /*-------------------------------------------------------------------------------- * Internal class for creating new CommunityCoreData objects. *-------------------------------------------------------------------------------- @@ -390,12 +340,11 @@ public class VeniceEngineImpl implements VeniceEngine, EngineBackend *-------------------------------------------------------------------------------- */ - private Document config = null; // configuration data private EnvEngine env = null; // my environment private Random rng; // random number generator private Properties email_props = null; // email properties private javax.mail.Session mailsession = null; // email session object - private Hashtable stock_messages = null; // stock messages holder + private StockMessages stock_messages = null; // stock messages holder private ObjectCache comm_objcache = new ObjectCache(new CommunityCoreDataCreator()); private VeniceFeatureDef[] features; // master feature table private Hashtable feature_syms = new Hashtable(); // hashtable mapping symbols to features @@ -412,6 +361,7 @@ public class VeniceEngineImpl implements VeniceEngine, EngineBackend private SecurityMonitor global_security; // the global security monitor private SecurityMonitor community_security; // the community security monitor private SecurityMonitor conference_security; // conference security monitor (will move eventually) + private ServiceControlManager scmgr; // service control manager /*-------------------------------------------------------------------------------- * Constructor @@ -431,9 +381,34 @@ public class VeniceEngineImpl implements VeniceEngine, EngineBackend *-------------------------------------------------------------------------------- */ + private static Collection getDictionaryNames(Element sect, String app_root) + { + ArrayList rc = new ArrayList(); + NodeList nl = sect.getChildNodes(); + for (int i=0; i<nl.getLength(); i++) + { // scan the element looking for <file/> elements + Node n = nl.item(i); + if ((n.getNodeType()==Node.ELEMENT_NODE) && (n.getNodeName().equals("file"))) + { // extract the name of the file, possibly prefixing the application root directory + DOMElementHelper h = new DOMElementHelper((Element)n); + String fname = h.getElementText(); + if (fname==null) + continue; // no file name??? + if (!(fname.startsWith("/"))) + fname = app_root + fname; + rc.add(fname); + + } // end if + + } // end for + + return rc; + + } // end getDictionaryNames + private void checkInitialized() { - if (config==null) + if (env==null) throw new InternalStateError("Venice engine not initialized!"); } // end checkInitialized @@ -643,89 +618,41 @@ public class VeniceEngineImpl implements VeniceEngine, EngineBackend { int i; // loop counter - if (this.config!=null) + if (env!=null) { // already configured! logger.error("Venice engine already initialized"); throw new ConfigException("Venice engine already initialized"); } // end if - this.config = config; - DataPool datapool = null; - ArrayList dictionary_tmp; + Collection dictionary_tmp; try { // first, verify that this is a valid configuration - Element root = config.getDocumentElement(); - if (!(root.getTagName().equals("venice-config"))) - { // not the correct root tag name - logger.fatal("config document is not a <venice-config/> document (root tag: <" - + root.getTagName() + "/>)"); - throw new ConfigException("document is not a <venice-config/> document",root); - - } // end if - + XMLLoader loader = XMLLoader.get(); + Element root = loader.configGetRootElement(config,"venice-config"); DOMElementHelper root_h = new DOMElementHelper(root); // Get the <engine/> section. - Element engine_sect = root_h.getSubElement("engine"); - if (engine_sect==null) - { // unable to find the engine section - logger.fatal("config document has no <engine/> section"); - throw new ConfigException("no <engine/> section found in config file",root); - - } // end if - - DOMElementHelper engine_h = new DOMElementHelper(engine_sect); + Element sect = loader.configGetSubSection(root_h,"engine"); + DOMElementHelper sect_h = new DOMElementHelper(sect); // Get the name of the sidebox config file. - String sidebox_config = engine_h.getSubElementText("sidebox-config"); - if (sidebox_config==null) - { // unable to find the sidebox config file - logger.fatal("<engine/> section has no <sidebox-config/> element"); - throw new ConfigException("no <sidebox-config/> element found in <engine/> section",engine_sect); - - } // end if - + String sidebox_config = loader.configGetSubElementText(sect_h,"sidebox-config"); if (!(sidebox_config.startsWith("/"))) sidebox_config = app_root + sidebox_config; - Document sidebox_cfg_file = Startup.loadConfiguration(sidebox_config); - Element sb_root = sidebox_cfg_file.getDocumentElement(); - if (!(sb_root.getTagName().equals("sidebox-config"))) - { // the sidebox configuration file isn't the right type - logger.fatal("config document is not a <sidebox-config/> document (root tag: <" - + sb_root.getTagName() + "/>)"); - throw new ConfigException("document is not a <sidebox-config/> document",sb_root); - } // end if - - NodeList sb_nodes = sb_root.getChildNodes(); - ArrayList sidebox_tmp = new ArrayList(); - for (i=0; i<sb_nodes.getLength(); i++) - { // extract each sidebox section from the list and build a new master sidebox object - Node s = sb_nodes.item(i); - if ((s.getNodeType()==Node.ELEMENT_NODE) && (s.getNodeName().equals("sidebox"))) - sidebox_tmp.add(new MasterSideBox((Element)s)); - - } // end for - - // store the real master sidebox table as an array - sideboxes = (MasterSideBox[])(sidebox_tmp.toArray(new MasterSideBox[0])); - if (logger.isDebugEnabled()) - logger.debug(sideboxes.length + " sidebox definitions loaded from XML"); + // Get the name of the services config file. + String services_config = loader.configGetSubElementText(sect_h,"services-config"); + if (!(services_config.startsWith("/"))) + services_config = app_root + services_config; // Get the <database/> section. - Element db_sect = root_h.getSubElement("database"); - if (db_sect==null) - { // unable to find the database section - logger.fatal("config document has no <database/> section"); - throw new ConfigException("no <database/> section found in config file",root); - - } // end if + sect = loader.configGetSubSection(root_h,"database"); try { // allocate the data pool object - datapool = new DataPool(db_sect); + datapool = new DataPool(sect); } // end try catch (SQLException e) @@ -735,20 +662,16 @@ public class VeniceEngineImpl implements VeniceEngine, EngineBackend } // end catch - Element security_sect = root_h.getSubElement("security"); - if (security_sect==null) - { // no "security" section...bad! - logger.fatal("config document has no <security/> section"); - throw new ConfigException("no <security/> section found in config file",root); + // Get the <security/> section. + sect = loader.configGetSubSection(root_h,"security"); - } // end if - - NodeList sec_nodes = security_sect.getChildNodes(); - for (i=0; i<sec_nodes.getLength(); i++) + // Load the security monitors. + NodeList nl = sect.getChildNodes(); + for (i=0; i<nl.getLength(); i++) { // scan through and find security monitors to initialize - Node n = sec_nodes.item(i); + Node n = nl.item(i); if ((n.getNodeType()==Node.ELEMENT_NODE) && (n.getNodeName().equals("security-definition"))) - { // initial security definition + { // load one of the initial security definitions SecurityMonitor sm = new StaticSecurityMonitor((Element)n); if (sm.getID().equals("Global")) global_security = sm; @@ -761,120 +684,85 @@ public class VeniceEngineImpl implements VeniceEngine, EngineBackend } // end for - Element email_sect = root_h.getSubElement("email"); - if (email_sect==null) - { // unable to find the database section - logger.fatal("config document has no <email/> section"); - throw new ConfigException("no <email/> section found in config file",root); - - } // end if + // Get the <email/> section. + sect = loader.configGetSubSection(root_h,"email"); + sect_h = new DOMElementHelper(sect); // initialize the email properties and get a mail session object email_props = new Properties(); email_props.put("mail.transport.protocol","smtp"); - DOMElementHelper email_sect_h = new DOMElementHelper(email_sect); - email_props.put("mail.smtp.host",email_sect_h.getSubElementText("smtp-host")); - email_props.put("mail.from",email_sect_h.getSubElementText("mail-from-addr")); - email_props.put("com.silverwrist.venice.email.mailer",email_sect_h.getSubElementText("mailer")); + email_props.put("mail.smtp.host",sect_h.getSubElementText("smtp-host")); + email_props.put("mail.from",sect_h.getSubElementText("mail-from-addr")); + email_props.put("com.silverwrist.venice.email.mailer",sect_h.getSubElementText("mailer")); mailsession = javax.mail.Session.getInstance(email_props,null); - Element dict_sect = root_h.getSubElement("dictionary"); - if (dict_sect==null) - { // unable to find the database section - logger.fatal("config document has no <dictionary/> section"); - throw new ConfigException("no <dictionary/> section found in config file",root); + // Get the <dictionary/> section. + sect = loader.configGetSubSection(root_h,"dictionary"); - } // end if + // Retrieve the list of dictionary files. + dictionary_tmp = getDictionaryNames(sect,app_root); - // Retrieve the list of dictionary files to load into the spellchecker. - dictionary_tmp = new ArrayList(); - NodeList dict_nodes = dict_sect.getChildNodes(); - for (i=0; i<dict_nodes.getLength(); i++) - { // scan the <dictionary> element looking for <file> elements - Node dn = dict_nodes.item(i); - if ((dn.getNodeType()==Node.ELEMENT_NODE) && (dn.getNodeName().equals("file"))) - { // store the file name as a vector element - Element del = (Element)dn; - DOMElementHelper h = new DOMElementHelper(del); - dictionary_tmp.add(h.getElementText()); - - } // end if - - } // end for - - Element upload_sect = root_h.getSubElement("upload"); - if (upload_sect==null) - { // unable to find the "upload" section - logger.fatal("config document has no <upload/> section"); - throw new ConfigException("no <upload/> section found in config file",root); - - } // end if + // Get the <upload/> section. + sect = loader.configGetSubSection(root_h,"upload"); + sect_h = new DOMElementHelper(sect); // Look for a "no-compress" blacklist. - DOMElementHelper upload_sect_h = new DOMElementHelper(upload_sect); - Element no_compress_sect = upload_sect_h.getSubElement("no-compress"); - if (no_compress_sect!=null) + Element subsect = sect_h.getSubElement("no-compress"); + if (subsect!=null) { // Initialize the no-compress list. - NodeList nc_nodes = no_compress_sect.getChildNodes(); - for (i=0; i<nc_nodes.getLength(); i++) + nl = subsect.getChildNodes(); + for (i=0; i<nl.getLength(); i++) { // retrieve all entries from the list - Node ncn = nc_nodes.item(i); - if (ncn.getNodeType()==Node.ELEMENT_NODE) - { // get the element - DOMElementHelper ncel = new DOMElementHelper((Element)ncn); - if (ncel.getElement().getNodeName().equals("type")) - { // add a new element to the list - no_compress_types.add(ncel.getElementText().trim().toLowerCase()); - - } // end if - else - { // this is bad - bail out! - logger.fatal("spurious element in <no-compress/> section"); - throw new ConfigException("<no-compress/> section contains spurious element",no_compress_sect); - - } // end else + Node n = nl.item(i); + if (n.getNodeType()==Node.ELEMENT_NODE) + { // look at the element name now + loader.configVerifyNodeName(n,"type",subsect); + DOMElementHelper h = new DOMElementHelper((Element)n); + no_compress_types.add(h.getElementText().trim().toLowerCase()); } // end if - // else skip it + // else skip this node } // end for } // end if // else no list, just proceed - - Element msg_sect = root_h.getSubElement("messages"); - if (msg_sect==null) - { // unable to find the database section - logger.fatal("config document has no <messages/> section"); - throw new ConfigException("no <messages/> section found in config file",root); - } // end if + // Get the <messages/> section. + sect = loader.configGetSubSection(root_h,"messages"); // Initialize the stock messages list. - stock_messages = new Hashtable(); - NodeList msg_nodes = msg_sect.getChildNodes(); - for (i=0; i<msg_nodes.getLength(); i++) - { // examine all subnodes to add them to the message text - Node msgn = msg_nodes.item(i); - if (msgn.getNodeType()==Node.ELEMENT_NODE) - { // add it to the hash table by its tag name - Element msgel = (Element)msgn; - DOMElementHelper h = new DOMElementHelper(msgel); - String txt = h.getElementText(); - if (txt!=null) - stock_messages.put(msgel.getTagName(),txt.trim()); + stock_messages = new StockMessages(sect); - } // end if + // Now done with the master config... + // Load the sidebox configuration file. + Document subdoc = loader.loadConfigDocument(sidebox_config); + root = loader.configGetRootElement(subdoc,"sidebox-config"); + + // Load the individual sideboxes. + ArrayList sidebox_tmp = new ArrayList(); + nl = root.getChildNodes(); + for (i=0; i<nl.getLength(); i++) + { // extract each sidebox section from the list and build a new master sidebox object + Node n = nl.item(i); + if ((n.getNodeType()==Node.ELEMENT_NODE) && (n.getNodeName().equals("sidebox"))) + sidebox_tmp.add(new MasterSideBox((Element)n)); } // end for + // store the real master sidebox table as an array + sideboxes = (MasterSideBox[])(sidebox_tmp.toArray(new MasterSideBox[0])); if (logger.isDebugEnabled()) - logger.debug(stock_messages.size() + " stock messages loaded from config"); + logger.debug(sideboxes.length + " sidebox definitions loaded from XML"); + + // Now done with the sidebox config... + // Load the services config file. + subdoc = loader.loadConfigDocument(services_config); + scmgr = new ServiceControlManager(subdoc,global_security,community_security); } // end try catch (ConfigException ce) { // before we leave on a ConfigException, nuke the important data - this.config = null; if (datapool!=null) datapool.closeAllConnections(); throw ce; @@ -1014,6 +902,21 @@ public class VeniceEngineImpl implements VeniceEngine, EngineBackend } // end initialize + public void shutdown() throws ConfigException + { + if (env==null) + { // already configured! + logger.error("Venice engine not initialized"); + throw new ConfigException("Venice engine not initialized"); + + } // end if + + scmgr.shutdown(); + env.getDataPool().closeAllConnections(); + env = null; + + } // end shutdown + public int getNumFeatures() { checkInitialized(); @@ -1765,7 +1668,7 @@ public class VeniceEngineImpl implements VeniceEngine, EngineBackend public List getMasterSideBoxList() { - return new MasterSideBoxList(sideboxes); + return Arrays.asList(sideboxes); } // end getMasterSideBoxList diff --git a/src/com/silverwrist/venice/servlets/Variables.java b/src/com/silverwrist/venice/servlets/Variables.java index bd08b4a..c362e60 100644 --- a/src/com/silverwrist/venice/servlets/Variables.java +++ b/src/com/silverwrist/venice/servlets/Variables.java @@ -26,7 +26,7 @@ import org.apache.log4j.*; import com.silverwrist.venice.core.*; import com.silverwrist.venice.except.*; import com.silverwrist.venice.servlets.format.*; -import com.silverwrist.venice.servlets.format.menus.LeftMenu; +import com.silverwrist.venice.servlets.format.menus.*; public class Variables { @@ -206,23 +206,34 @@ public class Variables } // end setMenuTop - public static void setMenuCommunity(HttpSession session, CommunityContext comm) + public static void setMenuCommunity(ServletContext ctxt, HttpSession session, CommunityContext comm) { Object obj = session.getAttribute(MENU_ATTRIBUTE); boolean do_change; - if ((obj==null) || !(obj instanceof MenuCommunity)) + if ((obj==null) || !(obj instanceof CommunityLeftMenu)) do_change = true; else { // look at the actual community IDs underlying the MenuCommunity - MenuCommunity tmp = (MenuCommunity)obj; + CommunityLeftMenu tmp = (CommunityLeftMenu)obj; do_change = (tmp.getID()!=comm.getCommunityID()); } // end else if (do_change) - { // switch to the appropriate MenuCommunity - MenuCommunity mc = new MenuCommunity(comm); - session.setAttribute(MENU_ATTRIBUTE,mc); + { // switch to the appropriate CommunityLeftMenu + try + { // but note that getting the rendering configuration can throw a ServletException + RenderConfig cfg = RenderConfig.getRenderConfig(ctxt); + CommunityLeftMenu menu = cfg.createCommunityMenu(comm); + session.setAttribute(MENU_ATTRIBUTE,menu); + + } // end try + catch (ServletException e) + { // if we fail, just clear it out + logger.warn("caught ServletException in setMenuCommunity",e); + session.removeAttribute(MENU_ATTRIBUTE); + + } // end catch } // end if diff --git a/src/com/silverwrist/venice/servlets/VeniceServlet.java b/src/com/silverwrist/venice/servlets/VeniceServlet.java index 8f64046..29fea4e 100644 --- a/src/com/silverwrist/venice/servlets/VeniceServlet.java +++ b/src/com/silverwrist/venice/servlets/VeniceServlet.java @@ -321,7 +321,7 @@ public abstract class VeniceServlet extends HttpServlet protected final void changeMenuCommunity(HttpServletRequest request, CommunityContext comm) { - Variables.setMenuCommunity(request.getSession(true),comm); + Variables.setMenuCommunity(getServletContext(),request.getSession(true),comm); } // end changeMenuCommunity diff --git a/src/com/silverwrist/venice/servlets/format/RenderConfig.java b/src/com/silverwrist/venice/servlets/format/RenderConfig.java index 6490c87..873e97c 100644 --- a/src/com/silverwrist/venice/servlets/format/RenderConfig.java +++ b/src/com/silverwrist/venice/servlets/format/RenderConfig.java @@ -21,22 +21,17 @@ import java.io.*; import java.util.*; import javax.servlet.*; import javax.servlet.http.*; -import javax.xml.parsers.*; import org.apache.log4j.*; import org.w3c.dom.*; -import org.xml.sax.SAXException; -import org.xml.sax.SAXParseException; -import com.silverwrist.util.DOMElementHelper; -import com.silverwrist.util.IOUtil; -import com.silverwrist.util.StringUtil; +import com.silverwrist.util.*; +import com.silverwrist.venice.core.CommunityContext; import com.silverwrist.venice.core.UserContext; import com.silverwrist.venice.core.VeniceEngine; -import com.silverwrist.venice.except.AccessError; -import com.silverwrist.venice.except.ConfigException; -import com.silverwrist.venice.except.DataException; +import com.silverwrist.venice.except.*; import com.silverwrist.venice.servlets.Variables; -import com.silverwrist.venice.servlets.format.menus.LeftMenu; +import com.silverwrist.venice.servlets.format.menus.*; import com.silverwrist.venice.servlets.format.sideboxes.SideBoxFactory; +import com.silverwrist.venice.util.XMLLoader; public class RenderConfig implements ColorSelectors { @@ -57,7 +52,6 @@ public class RenderConfig implements ColorSelectors *-------------------------------------------------------------------------------- */ - private Document config; private String site_title; private boolean want_comments; private boolean allow_gzip; @@ -71,13 +65,14 @@ public class RenderConfig implements ColorSelectors private int site_logo_width = 140; private int site_logo_height = 80; private String site_logo_linkURL = null; - private HashMap stock_messages; - private HashMap menus; + private StockMessages stock_messages; + private Map menus; private String[] colors_array; private int footer_logo_scale; private Map sidebox_factories; private String photo_not_avail; private boolean photo_not_avail_fixup; + private CommunityLeftMenuFactory comm_menu_fact; /*-------------------------------------------------------------------------------- * Constructor @@ -86,104 +81,76 @@ public class RenderConfig implements ColorSelectors protected RenderConfig(String config_file, String root_file_path) throws ConfigException { - config = loadConfiguration(config_file); + XMLLoader loader = XMLLoader.get(); + Document doc = loader.loadConfigDocument(config_file); - // Make sure the configuration is valid... - Element root = config.getDocumentElement(); - if (!(root.getTagName().equals("render-config"))) - { // not the correct root tag name - logger.fatal("config document is not a <render-config/> document (root tag: <" - + root.getTagName() + "/>)"); - throw new ConfigException("document is not a <render-config/> document",root); - - } // end if - - // Get the site name. + // Make sure the document is valid. + Element root = loader.configGetRootElement(doc,"render-config"); DOMElementHelper root_h = new DOMElementHelper(root); - site_title = root_h.getSubElementText("site-name"); - if (site_title==null) - { // no <site-name/> section - bail out now! - logger.fatal("config document has no <site-title/> element"); - throw new ConfigException("no <site-title/> section found in config file",root); - - } // end if + // Get the site title. + site_title = loader.configGetSubElementText(root_h,"site-name"); if (logger.isDebugEnabled()) logger.debug("Site title: " + site_title); - Element render_sect = root_h.getSubElement("rendering"); - if (render_sect==null) - { // no <rendering/> section - bail out now! - logger.fatal("config document has no <rendering/> section"); - throw new ConfigException("no <rendering/> section found in config file",root); + // Get the <rendering/> section. + Element sect = loader.configGetSubSection(root_h,"rendering"); - } // end if - - DOMElementHelper render_sect_h = new DOMElementHelper(render_sect); - want_comments = render_sect_h.hasChildElement("html-comments"); - allow_gzip = render_sect_h.hasChildElement("gzip-output"); - no_smart_tags = !(render_sect_h.hasChildElement("ms-copyright-violations")); + // Load the quick Boolean values indicated by the presence or absence of a tag. + DOMElementHelper sect_h = new DOMElementHelper(sect); + want_comments = sect_h.hasChildElement("html-comments"); + allow_gzip = sect_h.hasChildElement("gzip-output"); + no_smart_tags = !(sect_h.hasChildElement("ms-copyright-violations")); if (logger.isDebugEnabled()) { // log the read values - logger.debug("Use HTML comments: " + String.valueOf(want_comments)); - logger.debug("Use GZIP encoding: " + String.valueOf(allow_gzip)); - logger.debug("Disable IE Smart Tags: " + String.valueOf(no_smart_tags)); - - } // end if - - font_face = render_sect_h.getSubElementText("font"); - if (font_face==null) - { // no <font/> tag - bail out now! - logger.fatal("<rendering/> section has no <font/> element"); - throw new ConfigException("no <font/> found in <rendering/> section",render_sect); + logger.debug("Use HTML comments: " + want_comments); + logger.debug("Use GZIP encoding: " + allow_gzip); + logger.debug("Disable IE Smart Tags: " + no_smart_tags); } // end if + // Load the default font face. + font_face = loader.configGetSubElementText(sect_h,"font"); if (logger.isDebugEnabled()) logger.debug("Font face: " + font_face); - String stylesheet_loc = render_sect_h.getSubElementText("stylesheet"); - if (stylesheet_loc!=null) + // Load the default stylesheet file reference. + String tmp = sect_h.getSubElementText("stylesheet"); + if (tmp!=null) { // we're using Cascading Stylesheets - load it and test for existence - if (!(stylesheet_loc.startsWith("/"))) - stylesheet_loc = root_file_path + stylesheet_loc; + if (!(tmp.startsWith("/"))) // prepend app root + tmp = root_file_path + tmp; if (logger.isDebugEnabled()) - logger.debug("Stylesheet location: " + stylesheet_loc); + logger.debug("Stylesheet location: " + tmp); // Test to make sure the stylesheet is actually present. - stylesheet = new File(stylesheet_loc); + stylesheet = new File(tmp); if (!(stylesheet.exists() && stylesheet.canRead())) { // it's not there - bail out! - logger.fatal("unable to read stylesheet file: " + stylesheet_loc); - throw new ConfigException("stylesheet " + stylesheet_loc + " cannot be read",render_sect); + logger.fatal("unable to read stylesheet file: " + tmp); + throw new ConfigException("stylesheet " + tmp + " cannot be read",sect); } // end if } // end if - else // no stylesheet + else // no stylesheet stylesheet = null; - Element colors_sect = render_sect_h.getSubElement("colors"); - if (colors_sect==null) - { // no <colors/> tag - bail out now! - logger.fatal("<rendering/> section has no <colors/> element"); - throw new ConfigException("no <colors/> found in <rendering/> section",render_sect); - - } // end if - + // Get the <colors/> section and load the colors out of it.. + Element sect1 = loader.configGetSubSection(sect_h,"colors"); colors_array = new String[colornames_map.size()]; int i; - NodeList colors_nlist = colors_sect.getChildNodes(); - for (i=0; i<colors_nlist.getLength(); i++) + NodeList nl = sect1.getChildNodes(); + for (i=0; i<nl.getLength(); i++) { // look at all subelements and map their names to color selectors - Node foo = colors_nlist.item(i); - if (foo.getNodeType()==Node.ELEMENT_NODE) - { // map the element name to a color selector - Integer csel = (Integer)(colornames_map.get(foo.getNodeName())); - if (csel!=null) - { // load the specified color into the colors array - DOMElementHelper foo_h = new DOMElementHelper((Element)foo); - colors_array[csel.intValue()] = foo_h.getElementText(); + Node n = nl.item(i); + if (n.getNodeType()==Node.ELEMENT_NODE) + { // map the name of the node to a color selector + Integer cs = (Integer)(colornames_map.get(n.getNodeName())); + if (cs!=null) + { // get the color value and load it into the array + DOMElementHelper h = new DOMElementHelper((Element)n); + colors_array[cs.intValue()] = h.getElementText(); } // end if @@ -191,186 +158,57 @@ public class RenderConfig implements ColorSelectors } // end for - try - { // load in the footer logo scale - String tmp = render_sect_h.getSubElementText("footer-logo-scale"); - if (tmp==null) - footer_logo_scale = 100; - else - footer_logo_scale = Integer.parseInt(tmp.trim()); + // Load in the footer logo scale. + Integer itmp = sect_h.getSubElementInt("footer-logo-scale"); + footer_logo_scale = ((itmp==null) ? 100 : itmp.intValue()); - } // end try - catch (NumberFormatException nfe) - { // just default on serious error - footer_logo_scale = 100; - - } // end catch - - Element paths_sect = root_h.getSubElement("paths"); - if (paths_sect==null) - { // no <paths/> section - bail out now! - logger.fatal("config document has no <paths/> section"); - throw new ConfigException("no <paths/> section found in config file",root); - - } // end if - - DOMElementHelper paths_sect_h = new DOMElementHelper(paths_sect); - image_url = paths_sect_h.getSubElementText("image"); - if (image_url==null) - { // no <image/> tag - bail out now! - logger.fatal("<paths/> section has no <image/> element"); - throw new ConfigException("no <image/> found in <paths/> section",paths_sect); - - } // end if + // Get the <paths/> section. + sect = loader.configGetSubSection(root_h,"paths"); + sect_h = new DOMElementHelper(sect); + // Load the image path. + image_url = loader.configGetSubElementText(sect_h,"image"); if (logger.isDebugEnabled()) logger.debug("Image path: " + image_url); - static_url = paths_sect_h.getSubElementText("static"); - if (static_url==null) - { // no <static/> tag - bail out now! - logger.fatal("<paths/> section has no <static/> element"); - throw new ConfigException("no <static/> found in <paths/> section",paths_sect); - - } // end if - + // Load the static path. + static_url = loader.configGetSubElementText(sect_h,"static"); if (logger.isDebugEnabled()) logger.debug("Static files path: " + static_url); - Element site_logo_elt = paths_sect_h.getSubElement("site-logo"); - if (site_logo_elt==null) - { // no <site-logo/> tag - bail out now! - logger.fatal("<paths/> section has no <site-logo/> element"); - throw new ConfigException("no <site-logo/> found in <paths/> section",paths_sect); + // Get the site logo element. + sect1 = loader.configGetSubSection(sect_h,"site-logo"); + DOMElementHelper sect1_h = new DOMElementHelper(sect1); + site_logo = loader.configGetText(sect1_h); - } // end if + // Get the width and height of the logo. + itmp = sect1_h.getAttributeInt("width"); + if (itmp!=null) + site_logo_width = itmp.intValue(); + itmp = sect1_h.getAttributeInt("height"); + if (itmp!=null) + site_logo_height = itmp.intValue(); - DOMElementHelper site_logo_h = new DOMElementHelper(site_logo_elt); - site_logo = site_logo_h.getElementText(); - if (site_logo==null) - { // no site logo specified - bail out now! - logger.fatal("<paths/> section has no site logo element"); - throw new ConfigException("no site logo found in <paths/> section",paths_sect); - - } // end if - - // get logo width and height - Integer fooint = site_logo_h.getAttributeInt("width"); - if (fooint!=null) - site_logo_width = fooint.intValue(); - fooint = site_logo_h.getAttributeInt("height"); - if (fooint!=null) - site_logo_height = fooint.intValue(); - - // get logo link URL - String tmp = site_logo_elt.getAttribute("href"); + // Get the link URL of the logo. + tmp = sect1.getAttribute("href"); if (!(StringUtil.isStringEmpty(tmp))) site_logo_linkURL = tmp; if (logger.isDebugEnabled()) logger.debug("Site logo: " + site_logo); - // Load the sidebox configuration information. - String sidebox_config = paths_sect_h.getSubElementText("sidebox-config"); - if (sidebox_config==null) - { // the sidebox config was not present - logger.fatal("<paths/> section has no <sidebox-config/> element"); - throw new ConfigException("no <sidebox-config/> found in <paths/> section",paths_sect); - - } // end if - + // Get the name of the sidebox configuration file. + String sidebox_config = loader.configGetSubElementText(sect_h,"sidebox-config"); if (!(sidebox_config.startsWith("/"))) sidebox_config = root_file_path + sidebox_config; - Document sb_doc = loadConfiguration(sidebox_config); - Element sb_root = sb_doc.getDocumentElement(); - if (!(sb_root.getTagName().equals("sidebox-config"))) - { // the sidebox configuration file isn't the right type - logger.fatal("config document is not a <sidebox-config/> document (root tag: <" - + sb_root.getTagName() + "/>)"); - throw new ConfigException("document is not a <sidebox-config/> document",sb_root); - } // end if - - NodeList sb_nodes = sb_root.getChildNodes(); - HashMap tmp_factories = new HashMap(); - for (i=0; i<sb_nodes.getLength(); i++) - { // extract each sidebox section from the list and build a new master sidebox object - Node s = sb_nodes.item(i); - if ((s.getNodeType()==Node.ELEMENT_NODE) && (s.getNodeName().equals("sidebox"))) - { // get the various attributes of the sidebox - Element sb = (Element)s; - try - { // get the ID of the sidebox first - tmp = sb.getAttribute("id"); - if (StringUtil.isStringEmpty(tmp)) - { // there was no ID specified for the sidebox - logger.fatal("<sidebox/> specified with no ID!"); - throw new ConfigException("no ID specified in <sidebox/>",sb); - - } // end if - - // convert to an integer which we'll be using later in the HashMap - Integer id = new Integer(tmp); - - // get the name of the factory class - DOMElementHelper sb_h = new DOMElementHelper(sb); - tmp = sb_h.getSubElementText("factory-class"); - if (StringUtil.isStringEmpty(tmp)) - { // the factory class was not specified! - logger.fatal("<sidebox/> config incomplete (missing <factory-class/>)!"); - throw new ConfigException("configuration of <sidebox/> is not complete!",sb); - - } // end if - - Class factory_class = Class.forName(tmp); - SideBoxFactory factory = (SideBoxFactory)(factory_class.newInstance()); - factory.setConfiguration(sb); - tmp_factories.put(id,factory); - - } // end if - catch (NumberFormatException e1) - { // ID value was not an integer - logger.fatal("<sidebox/> ID not numeric!"); - throw new ConfigException("non-numeric ID specified in <sidebox/>",sb); - - } // end catch - catch (ClassNotFoundException e2) - { // sidebox could not be configured - logger.fatal("<sidebox/> config <factory-class/> not valid!",e2); - throw new ConfigException("<factory-class/> in <sidebox/> is not a valid class!",sb); - - } // end catch - catch (IllegalAccessException e3) - { // could not access class and/or constructor - logger.fatal("<sidebox/> <factory-class/> is not accessible!",e3); - throw new ConfigException("<factory-class/> in <sidebox/> is not accessible!",sb); - - } // end catch - catch (InstantiationException e4) - { // unable to create the class - logger.fatal("<sidebox/> <factory-class/> could not be instantiated!",e4); - throw new ConfigException("<factory-class/> in <sidebox/> could not be created!",sb); - - } // end catch - catch (ClassCastException e5) - { // the class is not a SideBoxFactory implementor - cannot create - logger.fatal("<sidebox/> <factory-class/> is not a SideBoxFactory!",e5); - throw new ConfigException("<factory-class/> in <sidebox/> is not the correct type!",sb); - - } // end catch - - } // end if - - } // end for - - sidebox_factories = Collections.unmodifiableMap(tmp_factories); - - Element pna = paths_sect_h.getSubElement("photo-not-avail"); - if (pna!=null) - { // copy element text and fixup information - DOMElementHelper pna_h = new DOMElementHelper(pna); - photo_not_avail = pna_h.getElementText(); - photo_not_avail_fixup = pna_h.hasAttribute("fixup"); + // Get the name of the "photo not available" image. + sect1 = sect_h.getSubElement("photo-not-avail"); + if (sect1!=null) + { // load the element text and fixup information + sect1_h = new DOMElementHelper(sect1); + photo_not_avail = sect1_h.getElementText(); + photo_not_avail_fixup = sect1_h.hasAttribute("fixup"); } // end if else @@ -380,84 +218,97 @@ public class RenderConfig implements ColorSelectors } // end else - Element msg_sect = root_h.getSubElement("messages"); - if (msg_sect==null) - { // no <messages/> section - bail out now! - logger.fatal("config document has no <messages/> section"); - throw new ConfigException("no <messages/> section found in config file",root); + // Get the name of the services configuration file. + String services_config = loader.configGetSubElementText(sect_h,"services-config"); + if (!(services_config.startsWith("/"))) + services_config = root_file_path + services_config; - } // end if + // Load the <messages/> section. + sect = loader.configGetSubSection(root_h,"messages"); // Initialize the stock messages list. - stock_messages = new HashMap(); - NodeList msg_nodes = msg_sect.getChildNodes(); - for (i=0; i<msg_nodes.getLength(); i++) - { // examine all subnodes to add them to the message text - Node msgn = msg_nodes.item(i); - if (msgn.getNodeType()==Node.ELEMENT_NODE) - { // add it to the hash table by its tag name - Element msgel = (Element)msgn; - DOMElementHelper h = new DOMElementHelper(msgel); - String txt = h.getElementText(); - if (txt!=null) - stock_messages.put(msgel.getTagName(),txt.trim()); + stock_messages = new StockMessages(sect); - } // end if - - } // end for - - if (logger.isDebugEnabled()) - logger.debug(stock_messages.size() + " stock messages loaded from config"); - - Element menu_sect = root_h.getSubElement("menu-definitions"); - if (menu_sect==null) - { // no <menu-definitions/> section - bail out now! - logger.fatal("config document has no <menu-definitions/> section"); - throw new ConfigException("no <menu-definitions/> section found in config file",root); - - } // end if + // Load the <menu-definitions/> section. + sect = loader.configGetSubSection(root_h,"menu-definitions"); // Initialize the menus list. - menus = new HashMap(); - NodeList menu_nodes = menu_sect.getChildNodes(); - for (i=0; i<menu_nodes.getLength(); i++) + HashMap tmp_menus = new HashMap(); + nl = sect.getChildNodes(); + for (i=0; i<nl.getLength(); i++) { // look for <menudef> subnodes and use them to initialize menus - Node mn = menu_nodes.item(i); - if (mn.getNodeType()==Node.ELEMENT_NODE) - { // found an element - now check it's name - if (mn.getNodeName().equals("menudef")) - { // root of a menu definition - get its ID, build it, and save it - Element mel = (Element)mn; - String menuid = mel.getAttribute("id"); - if (menuid==null) - { // no menu ID attribute - logger.fatal("<menudef/> seen with no \"id\" attribute"); - throw new ConfigException("<menudef/> seen with no \"id\" attribute",mel); + Node n = nl.item(i); + if (n.getNodeType()==Node.ELEMENT_NODE) + { // verify that it's a menu definition, then get its ID and build a menu + loader.configVerifyNodeName(n,"menudef",sect); + String menuid = loader.configGetAttribute((Element)n,"id"); - } // end if - - // create the menu and add it to the mapping - LeftMenu menu = new LeftMenu(mel,menuid); - menus.put(menuid,menu); - if (logger.isDebugEnabled()) - logger.debug("menu \"" + menuid + "\" defined"); - - } // end if (found the root of a menu definition) - else - { // unknown element - bail out! - logger.fatal("config document has unknown node <" + mn.getNodeName() + - "/> inside <menu-definitions/>"); - throw new ConfigException("unknown node name <" + mn.getNodeName() + "/> in <menu-definitions/>", - menu_sect); - - } // end else + // create the menu and add it to the mapping + LeftMenu menu = new LeftMenu((Element)n,menuid); + tmp_menus.put(menuid,menu); + if (logger.isDebugEnabled()) + logger.debug("menu \"" + menuid + "\" defined"); } // end if + // else just ignore it + + } // end for + + // save off the menus as an unmodifiable map + if (tmp_menus.isEmpty()) + menus = Collections.EMPTY_MAP; + else + menus = Collections.unmodifiableMap(tmp_menus); + if (logger.isDebugEnabled()) + logger.debug(menus.size() + " menu definitions loaded from config"); + + // done with the render-config.xml file + // Load up the sidebox-config.xml file. + doc = loader.loadConfigDocument(sidebox_config); + root = loader.configGetRootElement(doc,"sidebox-config"); + + // Examine the child nodes for sidebox configuration data. + nl = root.getChildNodes(); + HashMap tmp_factories = new HashMap(); + for (i=0; i<nl.getLength(); i++) + { // extract each sidebox section from the list and build a new master sidebox object + Node n = nl.item(i); + if ((n.getNodeType()==Node.ELEMENT_NODE) && (n.getNodeName().equals("sidebox"))) + { // get the ID for this sidebox + try + { // get the ID and convert it to integer + tmp = loader.configGetAttribute((Element)n,"id"); + itmp = new Integer(tmp); + + } // end try + catch (NumberFormatException nfe) + { // sidebox ID was not an integer! + logger.fatal("<sidebox/> ID not numeric!"); + throw new ConfigException("non-numeric ID specified in <sidebox/>",(Element)n); + + } // end catch + + SideBoxFactory factory = createSideBoxFactory((Element)n); + tmp_factories.put(itmp,factory); + + } // end if + // else ignore this node } // end for - if (logger.isDebugEnabled()) - logger.debug(menus.size() + " menu definitions loaded from config"); + if (tmp_factories.isEmpty()) + sidebox_factories = Collections.EMPTY_MAP; + else + sidebox_factories = Collections.unmodifiableMap(tmp_factories); + + // done with the sidebox-config.xml file + // Load up the services-config.xml file. + doc = loader.loadConfigDocument(services_config); + root = loader.configGetRootElement(doc,"services-config"); + root_h = new DOMElementHelper(root); + + // Get the community section and pass it to the CommunityLeftMenuFactory. + comm_menu_fact = new CommunityLeftMenuFactory(root_h.getSubElement("community")); } // end constructor @@ -466,62 +317,44 @@ public class RenderConfig implements ColorSelectors *-------------------------------------------------------------------------------- */ - private static Document loadConfiguration(String configname) throws ConfigException + private static SideBoxFactory createSideBoxFactory(Element cfg) throws ConfigException { - try - { // create a simple DOM parser by using the Java XML parsing API - DocumentBuilderFactory fac = DocumentBuilderFactory.newInstance(); - fac.setNamespaceAware(false); - fac.setValidating(false); - DocumentBuilder parser = fac.newDocumentBuilder(); + XMLLoader loader = XMLLoader.get(); + String cname = loader.configGetSubElementText(cfg,"factory-class"); - // access the config file and parse it into our config data tree - File configfile = new File(configname); - Document rc = parser.parse(configfile); - if (logger.isDebugEnabled()) - logger.debug("configuration loaded successfully"); - return rc; + try + { // load the factory class and create an instance of the factory + SideBoxFactory factory = (SideBoxFactory)(Class.forName(cname).newInstance()); + factory.setConfiguration(cfg); + return factory; } // end try - catch (FactoryConfigurationError e1) - { // if the document builder factory could not be created - logger.fatal("Parser factory configuration error: " + e1.getMessage(),e1); - throw new ConfigException("XML parser factory could not be created - " + e1.getMessage()); + catch (ClassNotFoundException cnfe) + { // sidebox could not be configured + logger.fatal("<sidebox/> config <factory-class/> not valid!",cnfe); + throw new ConfigException("<factory-class/> in <sidebox/> is not a valid class!",cfg); } // end catch - catch (ParserConfigurationException e2) - { // if the XML parser itself could not be created - logger.fatal("Parser configuration error: " + e2.getMessage(),e2); - throw new ConfigException("XML parser could not be created - " + e2.getMessage(),e2); + catch (IllegalAccessException iae) + { // could not access class and/or constructor + logger.fatal("<sidebox/> <factory-class/> is not accessible!",iae); + throw new ConfigException("<factory-class/> in <sidebox/> is not accessible!",cfg); } // end catch - catch (SAXException e3) - { // if the XML parser choked on our document - if (e3 instanceof SAXParseException) - { // we have a detailed message - make a proper exception - SAXParseException e3a = (SAXParseException)e3; - logger.fatal("Config file error [" + configname + ":" + e3a.getLineNumber() + "," - + e3a.getColumnNumber() + "]: " + e3a.getMessage(),e3a); - throw new ConfigException("Configuration file error: " + e3a.getMessage() + " at line " - + e3a.getLineNumber() + ", column " + e3a.getColumnNumber(),e3a); - - } // end if - else - { // generic exception - just send up a simple error message - logger.fatal("Config file error [" + configname + "]: " + e3.getMessage(),e3); - throw new ConfigException("Configuration file error - " + e3.getMessage(),e3); - - } // end else + catch (InstantiationException ie) + { // unable to create the class + logger.fatal("<sidebox/> <factory-class/> could not be instantiated!",ie); + throw new ConfigException("<factory-class/> in <sidebox/> could not be created!",cfg); } // end catch - catch (IOException e4) - { // error reading the config file itself off the disk - logger.fatal("IO error reading config: " + e4.getMessage(),e4); - throw new ConfigException("unable to read config file \"" + configname + "\" - " + e4.getMessage(),e4); + catch (ClassCastException cce) + { // the class is not a SideBoxFactory implementor - cannot create + logger.fatal("<sidebox/> <factory-class/> is not a SideBoxFactory!",cce); + throw new ConfigException("<factory-class/> in <sidebox/> is not the correct type!",cfg); } // end catch - } // end loadConfiguration + } // end createSideBoxFactory /*-------------------------------------------------------------------------------- * External operations usable only by RenderData @@ -740,6 +573,12 @@ public class RenderConfig implements ColorSelectors } // end getPhotoNotAvailFixup + public CommunityLeftMenu createCommunityMenu(CommunityContext comm) + { + return comm_menu_fact.createMenu(comm); + + } // end createCommunityMenu + /*-------------------------------------------------------------------------------- * Static operations for use by VeniceServlet *-------------------------------------------------------------------------------- diff --git a/src/com/silverwrist/venice/servlets/format/MenuCommunity.java b/src/com/silverwrist/venice/servlets/format/menus/CommunityLeftMenu.java similarity index 83% rename from src/com/silverwrist/venice/servlets/format/MenuCommunity.java rename to src/com/silverwrist/venice/servlets/format/menus/CommunityLeftMenu.java index 9698c77..d05a934 100644 --- a/src/com/silverwrist/venice/servlets/format/MenuCommunity.java +++ b/src/com/silverwrist/venice/servlets/format/menus/CommunityLeftMenu.java @@ -15,16 +15,17 @@ * * Contributor(s): */ -package com.silverwrist.venice.servlets.format; +package com.silverwrist.venice.servlets.format.menus; import java.io.Writer; import java.io.IOException; import java.util.*; -import com.silverwrist.util.StringUtil; +import com.silverwrist.util.*; import com.silverwrist.venice.core.*; import com.silverwrist.venice.except.*; +import com.silverwrist.venice.servlets.format.*; -public class MenuCommunity implements ComponentRender, ColorSelectors +public class CommunityLeftMenu implements ComponentRender, ColorSelectors { /*-------------------------------------------------------------------------------- * Attributes @@ -43,7 +44,7 @@ public class MenuCommunity implements ComponentRender, ColorSelectors *-------------------------------------------------------------------------------- */ - public MenuCommunity(CommunityContext ctxt) + CommunityLeftMenu(CommunityContext ctxt, List items) { try { // retrieve the contact info for this puppy @@ -64,7 +65,7 @@ public class MenuCommunity implements ComponentRender, ColorSelectors } // end catch title = ctxt.getName(); - items_list = ctxt.getCommunityFeaturesList(); + items_list = items; cid = ctxt.getCommunityID(); show_unjoin = ctxt.canUnjoin(); @@ -92,24 +93,21 @@ public class MenuCommunity implements ComponentRender, ColorSelectors } // end if // display the title - out.write("<B>" + StringUtil.encodeHTML(title) + "</B>"); + out.write("<B>" + StringUtil.encodeHTML(title) + "</B><BR>"); // display the menu items Iterator it = items_list.iterator(); - String cparm = "sig=" + cid; while (it.hasNext()) { // display each menu item in turn - CommunityFeature ftr = (CommunityFeature)(it.next()); - out.write("<BR>\n<A CLASS=\"lbar\" HREF=\"" - + rdat.getEncodedServletPath(ftr.getApplet() + "?" + cparm) + "\">" + hilite - + StringUtil.encodeHTML(ftr.getName()) + "</FONT></A>\n"); + ComponentRender cr = (ComponentRender)(it.next()); + cr.renderHere(out,rdat); } // end while if (show_unjoin) - out.write("<P>\n<A CLASS=\"lbar\" HREF=\"" - + rdat.getEncodedServletPath("sigops?cmd=U&" + cparm) + "\">" - + hilite + "Unjoin</FONT></A>\n"); + out.write("<BR>\n<A CLASS=\"lbar\" HREF=\"" + + rdat.getEncodedServletPath("sigops?cmd=U&sig=" + cid) + "\">" + hilite + + "Unjoin</FONT></A>\n"); out.write("\n"); // all done... @@ -126,4 +124,4 @@ public class MenuCommunity implements ComponentRender, ColorSelectors } // end getID -} // end class MenuCommunity +} // end class CommunityLeftMenu diff --git a/src/com/silverwrist/venice/servlets/format/menus/CommunityLeftMenuEntry.java b/src/com/silverwrist/venice/servlets/format/menus/CommunityLeftMenuEntry.java new file mode 100644 index 0000000..1c14c35 --- /dev/null +++ b/src/com/silverwrist/venice/servlets/format/menus/CommunityLeftMenuEntry.java @@ -0,0 +1,117 @@ +/* + * 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 <http://www.mozilla.org/MPL/>. + * + * 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 <erbo@silcom.com>, + * for Silverwrist Design Studios. Portions created by Eric J. Bowersox are + * Copyright (C) 2001 Eric J. Bowersox/Silverwrist Design Studios. All Rights Reserved. + * + * Contributor(s): + */ +package com.silverwrist.venice.servlets.format.menus; + +import java.util.Map; +import org.w3c.dom.*; +import com.silverwrist.venice.except.*; +import com.silverwrist.venice.util.XMLLoader; + +class CommunityLeftMenuEntry implements Comparable +{ + /*-------------------------------------------------------------------------------- + * Attributes + *-------------------------------------------------------------------------------- + */ + + private String symbol; + private int index; + private int sequence; + private LinkItem item; + + /*-------------------------------------------------------------------------------- + * Constructor + *-------------------------------------------------------------------------------- + */ + + CommunityLeftMenuEntry(Element svc) throws ConfigException + { + XMLLoader loader = XMLLoader.get(); + symbol = loader.configGetAttribute(svc,"id"); + index = loader.configGetAttributeInt(svc,"index"); + + Element link_elt = loader.configGetSubSection(svc,"link"); + sequence = loader.configGetAttributeInt(link_elt,"sequence"); + item = new LinkItem(link_elt); + + } // end constructor + + /*-------------------------------------------------------------------------------- + * Overrides from class Object + *-------------------------------------------------------------------------------- + */ + + public boolean equals(Object o) + { + if ((o==null) || !(o instanceof CommunityLeftMenuEntry)) + return false; + CommunityLeftMenuEntry other = (CommunityLeftMenuEntry)o; + return (sequence==other.sequence); + + } // end equals + + public int hashCode() + { + return sequence; + + } // end hashCode + + /*-------------------------------------------------------------------------------- + * Implementations from interface Comparable + *-------------------------------------------------------------------------------- + */ + + public int compareTo(Object o) + { + if (o==null) + throw new NullPointerException("compareTo null object!"); + CommunityLeftMenuEntry other = (CommunityLeftMenuEntry)o; // may throw ClassCastException + return sequence - other.sequence; + + } // end compareTo + + /*-------------------------------------------------------------------------------- + * External operations + *-------------------------------------------------------------------------------- + */ + + final String getSymbol() + { + return symbol; + + } // end getSymbol + + final int getIndex() + { + return index; + + } // end getIndex + + final int getSequence() + { + return sequence; + + } // end getSequence + + final LinkItem resolveItem(Map vars) + { + return new LinkItem(item,vars); + + } // end resolveItem + +} // end class CommunityLeftMenuEntry diff --git a/src/com/silverwrist/venice/servlets/format/menus/CommunityLeftMenuFactory.java b/src/com/silverwrist/venice/servlets/format/menus/CommunityLeftMenuFactory.java new file mode 100644 index 0000000..d16009a --- /dev/null +++ b/src/com/silverwrist/venice/servlets/format/menus/CommunityLeftMenuFactory.java @@ -0,0 +1,130 @@ +/* + * 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 <http://www.mozilla.org/MPL/>. + * + * 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 <erbo@silcom.com>, + * for Silverwrist Design Studios. Portions created by Eric J. Bowersox are + * Copyright (C) 2001 Eric J. Bowersox/Silverwrist Design Studios. All Rights Reserved. + * + * Contributor(s): + */ +package com.silverwrist.venice.servlets.format.menus; + +import java.util.*; +import org.w3c.dom.*; +import com.silverwrist.venice.core.*; +import com.silverwrist.venice.except.*; + +public class CommunityLeftMenuFactory +{ + /*-------------------------------------------------------------------------------- + * Attributes + *-------------------------------------------------------------------------------- + */ + + private List entries; + + /*-------------------------------------------------------------------------------- + * Constructor + *-------------------------------------------------------------------------------- + */ + + public CommunityLeftMenuFactory(Element comm_sect) throws ConfigException + { + if (comm_sect!=null) + { // look for community services + NodeList nl = comm_sect.getChildNodes(); + ArrayList tmp_entries = new ArrayList(nl.getLength()); + for (int i=0; i<nl.getLength(); i++) + { // get each node and see if it's a service node + Node n = nl.item(i); + if ((n.getNodeType()==Node.ELEMENT_NODE) && (n.getNodeName().equals("service"))) + { // create a template LeftMenuEntry and add it + CommunityLeftMenuEntry ent = new CommunityLeftMenuEntry((Element)n); + tmp_entries.add(ent); + + } // end if + + } // end for + + if (tmp_entries.isEmpty()) + entries = Collections.EMPTY_LIST; + else + { // sort the list by sequence before we save it + if (tmp_entries.size()>1) + Collections.sort(tmp_entries); + tmp_entries.trimToSize(); + entries = Collections.unmodifiableList(tmp_entries); + + } // end else + + } // end if + else // no communty services - initialize to null + entries = Collections.EMPTY_LIST; + + } // end constructor + + /*-------------------------------------------------------------------------------- + * External operations + *-------------------------------------------------------------------------------- + */ + + public CommunityLeftMenu createMenu(CommunityContext comm) + { + // N.B. This implementation will change once the engine uses the SCM to return the defined + // community services. + + List items; + if (entries.size()>0) + { // Get the community features list and stash the indexes in a set. + HashSet defined = new HashSet(); + List ftr_list = comm.getCommunityFeaturesList(); + Iterator it = ftr_list.iterator(); + while (it.hasNext()) + { // add each index to the set + CommunityFeature ftr = (CommunityFeature)(it.next()); + defined.add(new Integer(ftr.getFeatureCode())); + + } // end while + + // Create the map used to replace the variables in the menu items. + HashMap vars = new HashMap(); + vars.put("cid",String.valueOf(comm.getCommunityID())); + + // Run through the list of entries (sorted by sequence) and add them. + ArrayList tmp_items = new ArrayList(defined.size()); + it = entries.iterator(); + while (it.hasNext()) + { // get this entry and see if there's a match in the set + CommunityLeftMenuEntry ntry = (CommunityLeftMenuEntry)(it.next()); + if (defined.contains(new Integer(ntry.getIndex()))) + tmp_items.add(ntry.resolveItem(vars)); + + } // end while + + if (tmp_items.isEmpty()) // dummy out the list + items = Collections.EMPTY_LIST; + else + { // make the list unmodifiable + tmp_items.trimToSize(); + items = Collections.unmodifiableList(tmp_items); + + } // end else + + } // end if + else // no defined services - short-circuit the whole business + items = Collections.EMPTY_LIST; + + // the constructor will handle the rest of the initialization + return new CommunityLeftMenu(comm,items); + + } // end createMenu + +} // end class CommunityLeftMenuFactory diff --git a/src/com/silverwrist/venice/servlets/format/menus/LinkItem.java b/src/com/silverwrist/venice/servlets/format/menus/LinkItem.java index fdc7fde..fa0e7e0 100644 --- a/src/com/silverwrist/venice/servlets/format/menus/LinkItem.java +++ b/src/com/silverwrist/venice/servlets/format/menus/LinkItem.java @@ -19,6 +19,7 @@ package com.silverwrist.venice.servlets.format.menus; import java.io.Writer; import java.io.IOException; +import java.util.Map; import org.apache.log4j.*; import org.w3c.dom.*; import com.silverwrist.util.*; @@ -53,7 +54,7 @@ class LinkItem implements ComponentRender, ColorSelectors private ComponentRender contents; /*-------------------------------------------------------------------------------- - * Constructor + * Constructors *-------------------------------------------------------------------------------- */ @@ -103,6 +104,16 @@ class LinkItem implements ComponentRender, ColorSelectors } // end constructor + LinkItem(LinkItem other, Map vars) + { + this.href = StringUtil.replaceAllVariables(other.href,vars); + this.type = other.type; + this.enabled = other.enabled; + this.target = other.target; + this.contents = other.contents; + + } // end constructor + /*-------------------------------------------------------------------------------- * Implementations from interface ComponentRender *-------------------------------------------------------------------------------- diff --git a/src/com/silverwrist/venice/svc/CommService.java b/src/com/silverwrist/venice/svc/CommService.java new file mode 100644 index 0000000..ba7f085 --- /dev/null +++ b/src/com/silverwrist/venice/svc/CommService.java @@ -0,0 +1,35 @@ +/* + * 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 <http://www.mozilla.org/MPL/>. + * + * 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 <erbo@silcom.com>, + * for Silverwrist Design Studios. Portions created by Eric J. Bowersox are + * Copyright (C) 2001 Eric J. Bowersox/Silverwrist Design Studios. All Rights Reserved. + * + * Contributor(s): + */ +package com.silverwrist.venice.svc; + +import org.w3c.dom.Element; +import com.silverwrist.venice.except.ConfigException; +import com.silverwrist.venice.security.SecurityMonitor; + +public interface CommService +{ + public abstract void initialize(Element root, SecurityMonitor sm, CommServiceSite site) + throws ConfigException; + + public abstract void shutdown(); + + public abstract String getSymbol(); + + public abstract int getIndex(); + +} // end interface CommService diff --git a/src/com/silverwrist/venice/svc/CommServiceSite.java b/src/com/silverwrist/venice/svc/CommServiceSite.java new file mode 100644 index 0000000..a940058 --- /dev/null +++ b/src/com/silverwrist/venice/svc/CommServiceSite.java @@ -0,0 +1,22 @@ +/* + * 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 <http://www.mozilla.org/MPL/>. + * + * 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 <erbo@silcom.com>, + * for Silverwrist Design Studios. Portions created by Eric J. Bowersox are + * Copyright (C) 2001 Eric J. Bowersox/Silverwrist Design Studios. All Rights Reserved. + * + * Contributor(s): + */ +package com.silverwrist.venice.svc; + +public interface CommServiceSite +{ +} // end interface CommServiceSite diff --git a/src/com/silverwrist/venice/util/XMLLoader.java b/src/com/silverwrist/venice/util/XMLLoader.java new file mode 100644 index 0000000..b6483f6 --- /dev/null +++ b/src/com/silverwrist/venice/util/XMLLoader.java @@ -0,0 +1,235 @@ +/* + * 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 <http://www.mozilla.org/MPL/>. + * + * 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 <erbo@silcom.com>, + * for Silverwrist Design Studios. Portions created by Eric J. Bowersox are + * Copyright (C) 2001 Eric J. Bowersox/Silverwrist Design Studios. All Rights Reserved. + * + * Contributor(s): + */ +package com.silverwrist.venice.util; + +import java.io.*; +import javax.xml.parsers.*; +import org.apache.log4j.*; +import org.w3c.dom.*; +import org.xml.sax.SAXException; +import org.xml.sax.SAXParseException; +import com.silverwrist.util.DOMElementHelper; +import com.silverwrist.util.StringUtil; +import com.silverwrist.venice.except.*; + +public class XMLLoader +{ + /*-------------------------------------------------------------------------------- + * Static data members + *-------------------------------------------------------------------------------- + */ + + private static Category logger = Category.getInstance(XMLLoader.class); + + private static XMLLoader self = null; + + /*-------------------------------------------------------------------------------- + * Constructor + *-------------------------------------------------------------------------------- + */ + + private XMLLoader() + { // do nothing + } // end constructor + + /*-------------------------------------------------------------------------------- + * External operations + *-------------------------------------------------------------------------------- + */ + + public final Document loadConfigDocument(String filename) throws ConfigException + { + if (logger.isDebugEnabled()) + logger.debug("loadConfigDocument(\"" + filename + "\")..."); + + try + { // create a simple DOM parser by using the Java XML parsing API + DocumentBuilderFactory fac = DocumentBuilderFactory.newInstance(); + fac.setNamespaceAware(false); + fac.setValidating(false); + DocumentBuilder parser = fac.newDocumentBuilder(); + + // access the config file and parse it into our config data tree + Document rc = parser.parse(new File(filename)); + if (logger.isDebugEnabled()) + logger.debug("config file \"" + filename + "\" loaded successfully"); + return rc; + + } // end try + catch (FactoryConfigurationError fce) + { // if the document builder factory could not be created + logger.fatal("Parser factory configuration error: " + fce.getMessage(),fce); + throw new ConfigException("XML parser factory could not be created - " + fce.getMessage()); + + } // end catch + catch (ParserConfigurationException pce) + { // if the XML parser itself could not be created + logger.fatal("Parser configuration error: " + pce.getMessage(),pce); + throw new ConfigException("XML parser could not be created - " + pce.getMessage(),pce); + + } // end catch + catch (SAXException se) + { // if the XML parser choked on our document + if (se instanceof SAXParseException) + { // we have a detailed message - make a proper exception + SAXParseException spe = (SAXParseException)se; + logger.fatal("Config file error [" + filename + ":" + spe.getLineNumber() + "," + + spe.getColumnNumber() + "]: " + spe.getMessage(),spe); + throw new ConfigException("Configuration file error: " + spe.getMessage() + " at line " + + spe.getLineNumber() + ", column " + spe.getColumnNumber(),spe); + + } // end if + else + { // generic exception - just send up a simple error message + logger.fatal("Config file error [" + filename + "]: " + se.getMessage(),se); + throw new ConfigException("Configuration file error - " + se.getMessage(),se); + + } // end else + + } // end catch + catch (IOException ioe) + { // error reading the config file itself off the disk + logger.fatal("IO error reading config: " + ioe.getMessage(),ioe); + throw new ConfigException("unable to read config file \"" + filename + "\" - " + ioe.getMessage(),ioe); + + } // end catch + + } // end loadConfigDocument + + public final Element configGetRootElement(Document doc, String expected_name) throws ConfigException + { + Element rc = doc.getDocumentElement(); + if (rc.getTagName().equals(expected_name)) + return rc; // we're OK + logger.fatal("config document is not a <" + expected_name + "/> document (actual root tag: <" + + rc.getTagName() + "/>)"); + throw new ConfigException("document is not a <" + expected_name + "/> document",rc); + + } // end configGetRootElement + + public final String configGetText(DOMElementHelper h) throws ConfigException + { + String rc = h.getElementText(); + if (rc!=null) + return rc; // we're OK + logger.fatal("<" + h.getElement().getTagName() + "/> has no value"); + throw new ConfigException("no data value found in <" + h.getElement().getTagName() + "/>",h.getElement()); + + } // end configGetSubElementText + + public final String configGetText(Element elt) throws ConfigException + { + return configGetText(new DOMElementHelper(elt)); + + } // end configGetText + + public final String configGetSubElementText(DOMElementHelper h, String elt_name) throws ConfigException + { + String rc = h.getSubElementText(elt_name); + if (rc!=null) + return rc; // we're OK + logger.fatal("<" + h.getElement().getTagName() + "/> has no <" + elt_name + "/> element"); + throw new ConfigException("no <" + elt_name + "/> element found in <" + h.getElement().getTagName() + "/>", + h.getElement()); + + } // end configGetSubElementText + + public final String configGetSubElementText(Element elt, String subelt_name) throws ConfigException + { + return configGetSubElementText(new DOMElementHelper(elt),subelt_name); + + } // end configGetSubElementText + + public final Element configGetSubSection(DOMElementHelper h, String sect_name) throws ConfigException + { + Element rc = h.getSubElement(sect_name); + if (rc!=null) + return rc; // we're OK + logger.fatal("<" + h.getElement().getTagName() + "/> has no <" + sect_name + "/> section"); + throw new ConfigException("no <" + sect_name + "/> section found in <" + h.getElement().getTagName() + + "/>",h.getElement()); + + } // end configGetSubElementText + + public final Element configGetSubSection(Element sect, String subsect_name) throws ConfigException + { + return configGetSubSection(new DOMElementHelper(sect),subsect_name); + + } // end configGetSubSection + + public final void configVerifyNodeName(Node n, String name, Element enclosing_sect) throws ConfigException + { + if (n.getNodeName().equals(name)) + return; + logger.fatal("unknown node <" + n.getNodeName() + "/> seen inside <" + enclosing_sect.getTagName() + "/>"); + throw new ConfigException("unknown node name <" + n.getNodeName() + "/> in <" + + enclosing_sect.getTagName() + "/>",enclosing_sect); + + } // end configVerifyNodeName + + public final String configGetAttribute(Element elt, String attr_name) throws ConfigException + { + String rc = elt.getAttribute(attr_name); + if (!(StringUtil.isStringEmpty(rc))) + return rc; + logger.fatal("no " + attr_name + "= attribute found in <" + elt.getTagName() + "/> element"); + throw new ConfigException("no " + attr_name + "= attribute found in <" + elt.getTagName() + + "/> element",elt); + + } // end configGetAttribute + + public final int configGetAttributeInt(Element elt, String attr_name) throws ConfigException + { + String tmp = elt.getAttribute(attr_name); + if (StringUtil.isStringEmpty(tmp)) + { // the attribute is not present + logger.fatal("no " + attr_name + "= attribute found in <" + elt.getTagName() + "/> element"); + throw new ConfigException("no " + attr_name + "= attribute found in <" + elt.getTagName() + + "/> element",elt); + + } // end if + + try + { // parse out the integer value + return Integer.parseInt(tmp.trim()); + + } // end try + catch (NumberFormatException nfe) + { // but it's not a valid integer - throw something else! + logger.fatal(attr_name + "= attribute in <" + elt.getTagName() + "/> element is not a valid integer"); + throw new ConfigException(attr_name + "= attribute in <" + elt.getTagName() + + "/> element is not a valid integer",elt); + + } // end catch + + } // end configGetAttributeInt + + /*-------------------------------------------------------------------------------- + * External static operations + *-------------------------------------------------------------------------------- + */ + + public static final synchronized XMLLoader get() + { + if (self==null) + self = new XMLLoader(); + return self; + + } // end get + +} // end class XMLLoader