Java tutorial
//============================================================================== //=== //=== JeevesEngine //=== //============================================================================= //=== Copyright (C) 2001-2005 Food and Agriculture Organization of the //=== United Nations (FAO-UN), United Nations World Food Programme (WFP) //=== and United Nations Environment Programme (UNEP) //=== //=== This library is free software; you can redistribute it and/or //=== modify it under the terms of the GNU Lesser General Public //=== License as published by the Free Software Foundation; either //=== version 2.1 of the License, or (at your option) any later version. //=== //=== This library is distributed in the hope that it will be useful, //=== but WITHOUT ANY WARRANTY; without even the implied warranty of //=== MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU //=== Lesser General Public License for more details. //=== //=== You should have received a copy of the GNU Lesser General Public //=== License along with this library; if not, write to the Free Software //=== Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA //=== //=== Contact: Jeroen Ticheler - FAO - Viale delle Terme di Caracalla 2, //=== Rome - Italy. email: GeoNetwork@fao.org //============================================================================== package jeeves.server; import java.io.BufferedReader; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.sql.PreparedStatement; import java.sql.SQLException; import java.util.ArrayList; import java.util.HashMap; import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.Vector; import javax.servlet.ServletContext; import javax.servlet.ServletException; import javax.xml.transform.TransformerConfigurationException; import jeeves.config.springutil.JeevesApplicationContext; import jeeves.constants.ConfigFile; import jeeves.constants.Jeeves; import jeeves.exceptions.BadInputEx; import jeeves.interfaces.Activator; import jeeves.interfaces.ApplicationHandler; import jeeves.interfaces.Logger; import jeeves.monitor.MonitorManager; import jeeves.resources.dbms.Dbms; import jeeves.server.context.ServiceContext; import jeeves.server.dispatchers.ServiceManager; import jeeves.server.dispatchers.guiservices.XmlCacheManager; import jeeves.server.overrides.ConfigurationOverrides; import jeeves.server.resources.ProviderManager; import jeeves.server.resources.ResourceManager; import jeeves.server.sources.ServiceRequest; import jeeves.server.sources.http.JeevesServlet; import jeeves.utils.Log; import jeeves.utils.SerialFactory; import jeeves.utils.TransformerFactoryFactory; import jeeves.utils.Util; import jeeves.utils.Xml; import org.apache.commons.io.IOUtils; import org.apache.log4j.PropertyConfigurator; import org.jdom.Document; import org.jdom.Element; import org.jdom.output.XMLOutputter; import org.springframework.web.context.support.WebApplicationContextUtils; //============================================================================= /** This is the main class. It handles http connections and inits the system */ public class JeevesEngine { private static final String TRANSFORMER_PATH = "/WEB-INF/classes/META-INF/services/javax.xml.transform.TransformerFactory"; private String defaultSrv; private String startupErrorSrv; private String profilesFile; private String defaultLang; private String defaultContType; private String uploadDir; private int maxUploadSize; private String appPath; private boolean defaultLocal; private boolean debugFlag; private String dbResourceProviderName = "main-db"; private boolean dbLoaded; /** true if the 'general' part has been loaded */ private boolean generalLoaded; private ServiceManager serviceMan = new ServiceManager(); private ProviderManager providerMan = new ProviderManager(); private ScheduleManager scheduleMan = new ScheduleManager(); private SerialFactory serialFact = new SerialFactory(); private Logger appHandLogger = Log.createLogger(Log.APPHAND); private List<Element> appHandList = new ArrayList<Element>(); private Vector<ApplicationHandler> vAppHandlers = new Vector<ApplicationHandler>(); private Vector<Activator> vActivators = new Vector<Activator>(); private XmlCacheManager xmlCacheManager = new XmlCacheManager(); private MonitorManager monitorManager; private List<Element> dbservices = new ArrayList<Element>(); //--------------------------------------------------------------------------- //--- //--- Init //--- //--------------------------------------------------------------------------- /** Inits the engine, loading all needed data */ public void init(String appPath, String configPath, String baseUrl, JeevesServlet servlet) throws ServletException { try { PropertyConfigurator.configure(configPath + "log4j.cfg"); ServletContext servletContext = null; if (servlet != null) servletContext = servlet.getServletContext(); ConfigurationOverrides.DEFAULT.updateLoggingAsAccordingToOverrides(servletContext, appPath); monitorManager = new MonitorManager(servletContext, baseUrl); this.appPath = appPath; long start = System.currentTimeMillis(); long maxMem = Runtime.getRuntime().maxMemory() / 1024; long totMem = Runtime.getRuntime().totalMemory() / 1024; long freeMem = Runtime.getRuntime().freeMemory() / 1024; long usedMem = totMem - freeMem; long startFreeMem = maxMem - usedMem; // System.setProperty("javax.xml.transform.TransformerFactory", // "net.sf.saxon.TransformerFactoryImpl"); // Do this using library meta-inf to avoid affecting other servlets // in the same container info("=== Starting system ========================================"); //--------------------------------------------------------------------- //--- init system info("Engine : " + this.getClass().getName()); info("Java version : " + System.getProperty("java.vm.version")); info("Java vendor : " + System.getProperty("java.vm.vendor")); setupXSLTTransformerFactory(servlet); info("Path : " + appPath); info("BaseURL : " + baseUrl); // obtain application context so we can configure the serviceManager with it but we will configure it a bit later JeevesApplicationContext jeevesAppContext = (JeevesApplicationContext) WebApplicationContextUtils .getWebApplicationContext(servletContext); serviceMan.setAppPath(appPath); serviceMan.setProviderMan(providerMan); serviceMan.setMonitorMan(monitorManager); serviceMan.setXmlCacheManager(xmlCacheManager); serviceMan.setApplicationContext(jeevesAppContext); serviceMan.setSerialFactory(serialFact); serviceMan.setBaseUrl(baseUrl); serviceMan.setServlet(servlet); scheduleMan.setAppPath(appPath); scheduleMan.setProviderMan(providerMan); scheduleMan.setMonitorManager(monitorManager); scheduleMan.setApplicationContext(jeevesAppContext); scheduleMan.setSerialFactory(serialFact); scheduleMan.setBaseUrl(baseUrl); dbLoaded = false; loadConfigFile(servletContext, configPath, Jeeves.CONFIG_FILE, serviceMan); info("Initializing profiles..."); ProfileManager profileManager = serviceMan.loadProfiles(servletContext, profilesFile); // Add ResourceManager as a bean to the spring application context so that GeonetworkAuthentication can access it jeevesAppContext.getBeanFactory().registerSingleton("resourceManager", new ResourceManager(this.monitorManager, this.providerMan)); jeevesAppContext.getBeanFactory().registerSingleton("profileManager", profileManager); jeevesAppContext.getBeanFactory().registerSingleton("serialFactory", serialFact); //--- handlers must be started here because they may need the context //--- with the ProfileManager already loaded for (int i = 0; i < appHandList.size(); i++) initAppHandler((Element) appHandList.get(i), servlet, jeevesAppContext); info("Starting schedule manager..."); scheduleMan.start(); //--------------------------------------------------------------------- long end = System.currentTimeMillis(); long duration = (end - start) / 1000; freeMem = Runtime.getRuntime().freeMemory() / 1024; totMem = Runtime.getRuntime().totalMemory() / 1024; usedMem = totMem - freeMem; long endFreeMem = maxMem - usedMem; long dataMem = startFreeMem - endFreeMem; info("Memory used is : " + dataMem + " Kb"); info("Total memory is : " + maxMem + " Kb"); info("Startup time is : " + duration + " (secs)"); info("=== System working ========================================="); } catch (Exception e) { fatal("Raised exception during init"); fatal(" Exception : " + e); fatal(" Message : " + e.getMessage()); fatal(" Stack : " + Util.getStackTrace(e)); throw new ServletException("Exception raised", e); } } /** * Looks up the implementation of XSLT factory defined in META-INF/services/javax.xml.transform.TransformerFactory and instantiates * that implementation. This way, a conflicting setting in System Properties is overridden for this application only. * * @throws IOException * @throws TransformerConfigurationException */ private void setupXSLTTransformerFactory(JeevesServlet servlet) throws IOException, TransformerConfigurationException { InputStream in = null; BufferedReader br = null; // In debug mode, Jeeves may load a different file // Load javax.xml.transform.TransformerFactory from application path instead if (servlet != null) { in = servlet.getServletContext().getResourceAsStream(TRANSFORMER_PATH); } if (in == null) { File f = new File(appPath + TRANSFORMER_PATH); in = new FileInputStream(f); } try { if (in != null) { br = new BufferedReader(new InputStreamReader(in, "UTF-8")); String line; while ((line = br.readLine()) != null) { if (line.length() == 0) { warning("Malformed definition of XSLT transformer (in: META-INF/services/javax.xml.transform.TransformerFactory)."); } TransformerFactoryFactory.init(line); break; } } } catch (IOException x) { String msg = "Definition of XSLT transformer not found (tried: " + new File(appPath + TRANSFORMER_PATH).getCanonicalPath() + ")"; if (servlet != null) { msg += " and servlet.getServletContext().getResourceAsStream(" + TRANSFORMER_PATH + ")"; } warning(msg); error(x.getMessage()); x.printStackTrace(); } finally { IOUtils.closeQuietly(in); if (br != null) { IOUtils.closeQuietly(br); } } } //--------------------------------------------------------------------------- @SuppressWarnings("unchecked") private void loadConfigFile(ServletContext servletContext, String path, String file, ServiceManager serviceMan) throws Exception { file = path + file; info("Loading : " + file); Element configRoot = Xml.loadFile(file); ConfigurationOverrides.DEFAULT.updateWithOverrides(file, servletContext, appPath, configRoot); Element elGeneral = configRoot.getChild(ConfigFile.Child.GENERAL); Element elDefault = configRoot.getChild(ConfigFile.Child.DEFAULT); if (!generalLoaded) { if (elGeneral == null) throw new NullPointerException("Missing 'general' element in config file :" + file); if (elDefault == null) throw new NullPointerException("Missing 'default' element in config file :" + file); generalLoaded = true; initGeneral(elGeneral, serviceMan); initDefault(elDefault, serviceMan); } else { if (elGeneral != null) throw new IllegalArgumentException("Illegal 'general' element in secondary include"); if (elDefault != null) throw new IllegalArgumentException("Illegal 'default' element in secondary include"); } //--- init resources List<Element> resList = configRoot.getChildren(ConfigFile.Child.RESOURCES); for (int i = 0; i < resList.size(); i++) initResources(resList.get(i), file); //--- init app-handlers appHandList.addAll(configRoot.getChildren(ConfigFile.Child.APP_HANDLER)); //--- init services List<Element> srvList = configRoot.getChildren(ConfigFile.Child.SERVICES); for (int i = 0; i < srvList.size(); i++) initServices(srvList.get(i)); if (!dbLoaded) { setDBServicesElement(dbResourceProviderName); for (int i = 0; i < dbservices.size(); i++) { initServices(dbservices.get(i)); } dbLoaded = true; } //--- init schedules List<Element> schedList = configRoot.getChildren(ConfigFile.Child.SCHEDULES); for (int i = 0; i < schedList.size(); i++) initSchedules(schedList.get(i)); //--- init monitoring List<Element> monitorList = configRoot.getChildren(ConfigFile.Child.MONITORS); for (int i = 0; i < monitorList.size(); i++) monitorManager.initMonitors(monitorList.get(i)); //--- recurse on includes List<Element> includes = configRoot.getChildren(ConfigFile.Child.INCLUDE); for (int i = 0; i < includes.size(); i++) { Element include = includes.get(i); loadConfigFile(servletContext, path, include.getText(), serviceMan); } } //--------------------------------------------------------------------------- //--- //--- 'general' element //--- //--------------------------------------------------------------------------- /** Setup parameters from config tag (config.xml) */ private void initGeneral(Element general, ServiceManager serviceMan) throws BadInputEx { info("Initializing general configuration..."); profilesFile = Util.getParam(general, ConfigFile.General.Child.PROFILES); uploadDir = Util.getParam(general, ConfigFile.General.Child.UPLOAD_DIR); try { maxUploadSize = Integer.parseInt(Util.getParam(general, ConfigFile.General.Child.MAX_UPLOAD_SIZE)); } catch (Exception e) { maxUploadSize = 50; error("Maximum upload size not properly configured in config.xml. Using default size of 50MB"); error(" Exception : " + e); error(" Message : " + e.getMessage()); error(" Stack : " + Util.getStackTrace(e)); } if (!new File(uploadDir).isAbsolute()) uploadDir = appPath + uploadDir; if (!uploadDir.endsWith("/")) uploadDir += "/"; File uploadDirFile = new File(uploadDir); if (!uploadDirFile.mkdirs() && !uploadDirFile.exists()) { throw new RuntimeException("Unable to make upload directory: " + uploadDirFile); } else { Log.info(Log.JEEVES, "Upload directory is: " + uploadDir); } debugFlag = "true".equals(general.getChildText(ConfigFile.General.Child.DEBUG)); serviceMan.setUploadDir(uploadDir); serviceMan.setMaxUploadSize(maxUploadSize); } //--------------------------------------------------------------------------- //--- //--- 'general' element //--- //--------------------------------------------------------------------------- /** Setup parameters from config tag (config.xml) */ @SuppressWarnings("unchecked") private void initDefault(Element defaults, ServiceManager serviceMan) throws Exception { info("Initializing defaults..."); defaultSrv = Util.getParam(defaults, ConfigFile.Default.Child.SERVICE); // -- Don't break behaviour before gn 2.7 - if the startupErrorService // -- doesn't exist then ignore this parameter startupErrorSrv = Util.getParam(defaults, ConfigFile.Default.Child.STARTUPERRORSERVICE, ""); defaultLang = Util.getParam(defaults, ConfigFile.Default.Child.LANGUAGE); defaultContType = Util.getParam(defaults, ConfigFile.Default.Child.CONTENT_TYPE); defaultLocal = "true".equals(defaults.getChildText(ConfigFile.Default.Child.LOCALIZED)); info(" Default local is :" + defaultLocal); serviceMan.setDefaultLang(defaultLang); serviceMan.setDefaultLocal(defaultLocal); serviceMan.setDefaultContType(defaultContType); List<Element> errorPages = defaults.getChildren(ConfigFile.Default.Child.ERROR); for (int i = 0; i < errorPages.size(); i++) serviceMan.addErrorPage(errorPages.get(i)); Element gui = defaults.getChild(ConfigFile.Default.Child.GUI); if (gui != null) { List<Element> guiElems = gui.getChildren(); for (int i = 0; i < guiElems.size(); i++) serviceMan.addDefaultGui(guiElems.get(i)); } } //--------------------------------------------------------------------------- //--- //--- 'resources' element //--- //--------------------------------------------------------------------------- /** Setup resources from the resource element (config.xml) */ @SuppressWarnings("unchecked") private void initResources(Element resources, String file) { boolean resourceFound = false; info("Initializing resources..."); List<Element> resList = resources.getChildren(ConfigFile.Resources.Child.RESOURCE); for (int i = 0; i < resList.size(); i++) { Element res = resList.get(i); String name = res.getChildText(ConfigFile.Resource.Child.NAME); String provider = res.getChildText(ConfigFile.Resource.Child.PROVIDER); Element config = res.getChild(ConfigFile.Resource.Child.CONFIG); Element activator = res.getChild(ConfigFile.Resource.Child.ACTIVATOR); String enabled = res.getAttributeValue(ConfigFile.Resource.Attr.ENABLED); if ((enabled == null) || enabled.equals("true")) { info(" Adding resource : " + name); resourceFound = true; try { if (activator != null) { String clas = activator.getAttributeValue(ConfigFile.Activator.Attr.CLASS); info(" Loading activator : " + clas); Activator activ = (Activator) Class.forName(clas).newInstance(); info(" Starting activator : " + clas); activ.startup(appPath, activator); vActivators.add(activ); } providerMan.register(provider, name, config); // Try and open a resource from the provider providerMan.getProvider(name).open(); if (name.equals(dbResourceProviderName)) { Dbms dbms = null; try { dbms = (Dbms) providerMan.getProvider(name).open(); } finally { if (dbms != null) providerMan.getProvider(name).close(dbms); } } } catch (Exception e) { Map<String, String> errors = new HashMap<String, String>(); String eS = "Raised exception while initializing resource " + name + " in " + file + ". Skipped."; error(eS); errors.put("Error", eS); error(" Resource : " + name); errors.put("Resource", name); error(" Provider : " + provider); errors.put("Provider", provider); error(" Exception : " + e); errors.put("Exception", e.toString()); error(" Message : " + e.getMessage()); errors.put("Message", e.getMessage()); error(" Stack : " + Util.getStackTrace(e)); errors.put("Stack", Util.getStackTrace(e)); error(errors.toString()); serviceMan.setStartupErrors(errors); } } } if (!resourceFound) { Map<String, String> errors = new HashMap<String, String>(); errors.put("Error", "No database resources found to initialize - check " + file); error(errors.toString()); serviceMan.setStartupErrors(errors); } } //--------------------------------------------------------------------------- //--- //--- 'appHandler' element //--- //--------------------------------------------------------------------------- @SuppressWarnings("unchecked") private void initAppHandler(Element handler, JeevesServlet servlet, JeevesApplicationContext jeevesApplicationContext) throws Exception { if (handler == null) info("Handler not found"); else { String className = handler.getAttributeValue(ConfigFile.AppHandler.Attr.CLASS); if (className == null) throw new IllegalArgumentException("Missing '" + ConfigFile.AppHandler.Attr.CLASS + "' attribute in '" + ConfigFile.Child.APP_HANDLER + "' element"); info("Found handler : " + className); Class c = Class.forName(className); ApplicationHandler h = (ApplicationHandler) c.newInstance(); ServiceContext srvContext = serviceMan.createServiceContext("AppHandler", jeevesApplicationContext); srvContext.setLanguage(defaultLang); srvContext.setLogger(appHandLogger); srvContext.setServlet(servlet); srvContext.setAsThreadLocal(); try { info("--- Starting handler --------------------------------------"); Object context = h.start(handler, srvContext); srvContext.getResourceManager().close(); vAppHandlers.add(h); serviceMan.registerContext(h.getContextName(), context); scheduleMan.registerContext(h.getContextName(), context); monitorManager.initMonitorsForApp(srvContext); info("--- Handler started ---------------------------------------"); } catch (Exception e) { Map<String, String> errors = new HashMap<String, String>(); String eS = "Raised exception while starting appl handler. Skipped."; error(eS); errors.put("Error", eS); error(" Handler : " + className); errors.put("Handler", className); error(" Exception : " + e); errors.put("Exception", e.toString()); error(" Message : " + e.getMessage()); errors.put("Message", e.getMessage()); error(" Stack : " + Util.getStackTrace(e)); errors.put("Stack", Util.getStackTrace(e)); error(errors.toString()); // only set the error if we don't already have one if (!serviceMan.isStartupError()) serviceMan.setStartupErrors(errors); srvContext.getResourceManager().abort(); } } } //--------------------------------------------------------------------------- //--- //--- 'services' element //--- //--------------------------------------------------------------------------- /** Setup services found in the services tag (config.xml) */ @SuppressWarnings("unchecked") public void initServices(Element services) throws Exception { info("Initializing services..."); //--- get services root package String pack = services.getAttributeValue(ConfigFile.Services.Attr.PACKAGE); // --- scan services elements for (Element service : (List<Element>) services.getChildren(ConfigFile.Services.Child.SERVICE)) { String name = service.getAttributeValue(ConfigFile.Service.Attr.NAME); info(" Adding service : " + name); try { serviceMan.addService(pack, service); } catch (Exception e) { warning("Raised exception while registering service. Skipped."); warning(" Service : " + name); warning(" Package : " + pack); warning(" Exception : " + e); warning(" Message : " + e.getMessage()); warning(" Stack : " + Util.getStackTrace(e)); } } } //--------------------------------------------------------------------------- //--- //--- 'schedules' element //--- //--------------------------------------------------------------------------- /** Setup schedules found in the 'schedules' element (config.xml) */ @SuppressWarnings("unchecked") private void initSchedules(Element schedules) throws Exception { info("Initializing schedules..."); //--- get schedules root package String pack = schedules.getAttributeValue(ConfigFile.Schedules.Attr.PACKAGE); // --- scan schedules elements for (Element schedule : (List<Element>) schedules.getChildren(ConfigFile.Schedules.Child.SCHEDULE)) { String name = schedule.getAttributeValue(ConfigFile.Schedule.Attr.NAME); info(" Adding schedule : " + name); try { scheduleMan.addSchedule(pack, schedule); } catch (Exception e) { error("Raised exception while registering schedule. Skipped."); error(" Schedule : " + name); error(" Package : " + pack); error(" Exception : " + e); error(" Message : " + e.getMessage()); error(" Stack : " + Util.getStackTrace(e)); } } } //--------------------------------------------------------------------------- //--- //--- 'schedules' element //--- //--------------------------------------------------------------------------- /** Setup schedules found in the 'schedules' element (config.xml) */ //--------------------------------------------------------------------------- //--- //--- Destroy //--- //--------------------------------------------------------------------------- public void destroy() { try { info("=== Stopping system ========================================"); info("Shutting down monitor manager..."); monitorManager.shutdown(); info("Stopping schedule manager..."); scheduleMan.exit(); info("Stopping handlers..."); stopHandlers(); info("Stopping resources..."); stopResources(); info("=== System stopped ========================================"); } catch (Exception e) { error("Raised exception during destroy"); error(" Exception : " + e); error(" Message : " + e.getMessage()); error(" Stack : " + Util.getStackTrace(e)); } } //--------------------------------------------------------------------------- /** Stop handlers */ private void stopHandlers() throws Exception { for (ApplicationHandler h : vAppHandlers) { h.stop(); } } //--------------------------------------------------------------------------- /** Stop resources */ private void stopResources() { providerMan.end(); for (Activator a : vActivators) { info(" Stopping activator : " + a.getClass().getName()); a.shutdown(); } } //--------------------------------------------------------------------------- //--- //--- API methods //--- //--------------------------------------------------------------------------- public String getUploadDir() { return uploadDir; } //--------------------------------------------------------------------------- public int getMaxUploadSize() { return maxUploadSize; } //--------------------------------------------------------------------------- public void dispatch(ServiceRequest srvReq, UserSession session) { if (srvReq.getService() == null || srvReq.getService().length() == 0) srvReq.setService(defaultSrv); if (srvReq.getLanguage() == null || srvReq.getLanguage().length() == 0) srvReq.setLanguage(defaultLang); srvReq.setDebug(srvReq.hasDebug() && debugFlag); //--- if we have a startup error (ie. exception during startup) then //--- override with the startupErrorSrv service (if defined) if (serviceMan.isStartupError() && !startupErrorSrv.equals("") && !srvReq.getService().contains(startupErrorSrv)) srvReq.setService(startupErrorSrv); //--- normal dispatch pipeline serviceMan.dispatch(srvReq, session); } //--------------------------------------------------------------------------- //--- //--- Other private methods //--- //--------------------------------------------------------------------------- private void info(String message) { Log.info(Log.ENGINE, message); } private void warning(String message) { Log.warning(Log.ENGINE, message); } private void error(String message) { Log.error(Log.ENGINE, message); } private void fatal(String message) { Log.fatal(Log.ENGINE, message); } public ServiceManager getServiceManager() { return serviceMan; } public ProfileManager getProfileManager() { return serviceMan.getProfileManager(); } /** * Create Jeeves services from a configuration stored in the Services table * of the DBMS resource. * * @param name resource provider name to open dbms from (usually main-db) */ private void setDBServicesElement(String name) { Dbms dbms = null; try { dbms = (Dbms) providerMan.getProvider(name).open(); Element eltServices = new Element("services"); eltServices.setAttribute("package", "org.fao.geonet"); java.util.List serviceList = dbms.select("SELECT * FROM Services").getChildren(); if (!dbLoaded) { for (int j = 0; j < serviceList.size(); j++) { Element eltService = (Element) serviceList.get(j); Element srv = new Element("service"); Element cls = new Element("class"); java.util.List paramList = dbms .select("SELECT name, value FROM ServiceParameters WHERE service =?", Integer.valueOf(eltService.getChildText("id"))) .getChildren(); for (int k = 0; k < paramList.size(); k++) { Element eltParam = (Element) paramList.get(k); String paramId = eltParam.getChildText("id"); if (eltParam.getChildText("value") != null && !eltParam.getChildText("value").equals("")) { cls.addContent(new Element("param").setAttribute("name", "filter").setAttribute("value", "+" + eltParam.getChildText("name") + ":" + eltParam.getChildText("value"))); } } srv.setAttribute("name", eltService.getChildText("name")) .addContent(cls.setAttribute("name", eltService.getChildText("class"))); eltServices.addContent(srv); } } dbservices.add(eltServices); } catch (Exception e) { warning("Jeeves DBMS service configuration lookup failed (database may not be available yet). Message is: " + e.getMessage()); } finally { try { if (dbms != null) providerMan.getProvider(name).close(dbms); } catch (Exception e) { warning("Unable to close jeeves dbms - may not matter?"); e.printStackTrace(); } } } }