/******************************************************************************** * CruiseControl, a Continuous Integration Toolkit * Copyright (c) 2005 ThoughtWorks, Inc. * 200 E. Randolph, 25th Floor * Chicago, IL 60601 USA * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * + Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * + Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following * disclaimer in the documentation and/or other materials provided * with the distribution. * * + Neither the name of ThoughtWorks, Inc., CruiseControl, nor the * names of its contributors may be used to endorse or promote * products derived from this software without specific prior * written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ********************************************************************************/ package net.sourceforge.cruisecontrol; import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.StringReader; import java.util.Arrays; import java.util.Collection; import java.util.HashMap; import java.util.LinkedList; import java.util.List; import java.util.Map; import javax.management.Attribute; import javax.management.AttributeNotFoundException; import javax.management.InstanceNotFoundException; import javax.management.InvalidAttributeValueException; import javax.management.MBeanException; import javax.management.MBeanServerConnection; import javax.management.MalformedObjectNameException; import javax.management.ObjectName; import javax.management.ReflectionException; import javax.management.remote.JMXConnector; import javax.management.remote.JMXConnectorFactory; import javax.management.remote.JMXServiceURL; import javax.naming.Context; import net.sourceforge.cruisecontrol.util.Util; import org.apache.commons.lang.StringUtils; import org.jdom.Document; import org.jdom.Element; import org.jdom.JDOMException; import org.jdom.input.SAXBuilder; import org.jdom.output.Format; import org.jdom.output.XMLOutputter; /** * Communicates with the CruiseControl JMX server to allow CRUD operations on * the CruiseControl configuration. */ public class Configuration { private MBeanServerConnection server; private ObjectName ccMgr; private String configuration; private PluginDetail[] pluginDetails; public Configuration(final String jmxServer, final int rmiPort) throws IOException, MalformedObjectNameException { final JMXServiceURL address = new JMXServiceURL("service:jmx:rmi://" + jmxServer + ":" + rmiPort + "/jndi/jrmp"); final Map<String, Object> environment = new HashMap<String, Object>(); environment.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.rmi.registry.RegistryContextFactory"); environment.put(Context.PROVIDER_URL, "rmi://" + jmxServer + ":" + rmiPort); final JMXConnector cntor = JMXConnectorFactory.connect(address, environment); server = cntor.getMBeanServerConnection(); ccMgr = ObjectName.getInstance("CruiseControl Manager:id=unique"); } public String getConfiguration() throws AttributeNotFoundException, InstanceNotFoundException, MBeanException, ReflectionException, IOException, JDOMException { if (configuration == null) { load(); } return configuration; } public Document getDocument() throws ReflectionException, IOException, InstanceNotFoundException, MBeanException, AttributeNotFoundException, JDOMException { return stringToDoc(getConfiguration()); } public Element getElement(String name) throws ReflectionException, InstanceNotFoundException, IOException, MBeanException, AttributeNotFoundException, JDOMException { return JDOMSearcher.getElement(getDocument(), name); } public PluginDetail[] getPluginDetails() throws AttributeNotFoundException, InstanceNotFoundException, MBeanException, ReflectionException, IOException { if (pluginDetails == null) { pluginDetails = (PluginDetail[]) server.getAttribute(ccMgr, "AvailablePlugins"); } return pluginDetails; } public PluginDetail[] getConfiguredBootstrappers(String project) throws CruiseControlException, AttributeNotFoundException, InstanceNotFoundException, MBeanException, ReflectionException, IOException, JDOMException { return getConfiguredPluginDetails(getProjectConfig(project).getBootstrappers()); } public PluginDetail[] getConfiguredBuilders(String project) throws AttributeNotFoundException, InstanceNotFoundException, MBeanException, ReflectionException, IOException, CruiseControlException, JDOMException { return getConfiguredPluginDetails(getProjectConfig(project).getSchedule().getBuilders()); } public PluginDetail[] getConfiguredListeners(String project) throws AttributeNotFoundException, InstanceNotFoundException, MBeanException, ReflectionException, IOException, CruiseControlException, JDOMException { return getConfiguredPluginDetails(getProjectConfig(project).getListeners()); } public PluginDetail[] getConfiguredLoggers(String project) throws AttributeNotFoundException, InstanceNotFoundException, MBeanException, ReflectionException, IOException, CruiseControlException, JDOMException { return getConfiguredPluginDetails(Arrays.asList(getProjectConfig(project).getLog().getLoggers())); } public PluginDetail[] getConfiguredPublishers(String project) throws AttributeNotFoundException, InstanceNotFoundException, MBeanException, ReflectionException, IOException, CruiseControlException, JDOMException { return getConfiguredPluginDetails(getProjectConfig(project).getPublishers()); } public PluginDetail[] getConfiguredSourceControls(String project) throws AttributeNotFoundException, InstanceNotFoundException, MBeanException, ReflectionException, IOException, CruiseControlException, JDOMException { return getConfiguredPluginDetails(getProjectConfig(project).getModificationSet().getSourceControls()); } public void load() throws MBeanException, AttributeNotFoundException, InstanceNotFoundException, ReflectionException, IOException, JDOMException { // Ensure xml is well-formed configuration = docToString(stringToDoc(loadConfiguration())); } public void save() throws InstanceNotFoundException, AttributeNotFoundException, InvalidAttributeValueException, MBeanException, ReflectionException, IOException { server.setAttribute(ccMgr, new Attribute("ConfigFileContents", configuration)); } public void setConfiguration(String configuration) { this.configuration = configuration; } public void setConfiguration(Document doc) { setConfiguration(docToString(doc)); } // we know pluginConfiguration.getDetails().entrySet() returns <Map.Entry<String, String>> @SuppressWarnings("unchecked") public void updatePluginConfiguration(final PluginConfiguration pluginConfiguration) throws AttributeNotFoundException, InstanceNotFoundException, MBeanException, ReflectionException, IOException, JDOMException, InvalidAttributeValueException { final Element plugin = new Element(pluginConfiguration.getName()); for (final Map.Entry<String, String> element : (Iterable<Map.Entry<String, String>>) pluginConfiguration.getDetails().entrySet()) { final String key = element.getKey(); final String value = element.getValue(); if (StringUtils.isNotBlank(value)) { plugin.setAttribute(key, value); } } final Document doc = getDocument(); final Element parent = JDOMSearcher.getElement(doc, pluginConfiguration.getParentElementName()); parent.removeChild(plugin.getName()); parent.addContent(plugin); setConfiguration(doc); } private static String docToString(Document doc) { return new XMLOutputter(Format.getPrettyFormat()).outputString(doc).trim(); } private static Document stringToDoc(String configuration) throws JDOMException, IOException { return new SAXBuilder().build(new StringReader(configuration)); } private PluginDetail[] getConfiguredPluginDetails(final List plugins) throws AttributeNotFoundException, InstanceNotFoundException, MBeanException, ReflectionException, IOException, CruiseControlException { final Collection<PluginDetail> details = new LinkedList<PluginDetail>(); final PluginRegistry registry = getPluginRegistry(); for (final Object plugin : plugins) { Class nextClass = plugin.getClass(); details.add(new GenericPluginDetail(registry.getPluginName(nextClass), nextClass)); } return details.toArray(new PluginDetail[details.size()]); } private PluginRegistry getPluginRegistry() throws AttributeNotFoundException, InstanceNotFoundException, MBeanException, ReflectionException, IOException { return (PluginRegistry) server.getAttribute(ccMgr, "PluginRegistry"); } private ProjectConfig getProjectConfig(String project) throws CruiseControlException, AttributeNotFoundException, InstanceNotFoundException, MBeanException, ReflectionException, IOException, JDOMException { Element element = Util.loadRootElement(new ByteArrayInputStream(getConfiguration().getBytes())); CruiseControlConfig config = new CruiseControlConfig(element); return (ProjectConfig) config.getProject(project); } private String loadConfiguration() throws MBeanException, AttributeNotFoundException, InstanceNotFoundException, ReflectionException, IOException { return (String) server.getAttribute(ccMgr, "ConfigFileContents"); } }