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