/*
* JBoss, Home of Professional Open Source
* Copyright 2008, Red Hat Middleware LLC, and individual contributors
* as indicated by the @author tags.
* See the copyright.txt in the distribution for a
* full listing of individual contributors.
* This copyrighted material is made available to anyone wishing to use,
* modify, copy, or redistribute it subject to the terms and conditions
* of the GNU Lesser General Public License, v. 2.1.
* This program is distributed in the hope that it will be useful, but WITHOUT A
* 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,
* v.2.1 along with this distribution; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301, USA.
*
* (C) 2008,
* @author JBoss Inc.
*/
package org.jboss.test.jbossts.taskdefs;
import java.io.File;
import java.io.IOException;
import java.io.FileWriter;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import org.w3c.dom.*;
import org.xml.sax.SAXException;
/**
* Helper class to read a JBoss AS bindings file
*/
public class ServerBindingConfig
{
private static final String BINDING_MANAGER_NAME = "jboss.system:service=ServiceBindingManager";
private static final String BINDING_MANAGER_CLASS = "org.jboss.services.binding.ServiceBindingManager";
private static final String STORE_FACTORY_CLASS = "org.jboss.services.binding.XMLServicesStoreFactory";
public static final String DEFAULT_BINDING = "ports-01";
/**
* Configure an AS to start up with a non-default set of bindings.
*
* An mbean entry will be inserted into xmlFile with a name specified by bindingName.
* The file bindingXml will contain an entry with the name bindingName.
*
* @param xmlFile The file that is to recieve the binding service specification
* @param bindingName The name of the binding definition to use
* @param bindingXml file name of the file that contains a group of binding definitions
* @throws IOException
* @throws ParserConfigurationException
* @throws org.xml.sax.SAXException
* @throws TransformerException
*/
public static void setBinding(String xmlFile, String bindingName, String bindingXml) throws IOException, ParserConfigurationException,
org.xml.sax.SAXException, TransformerException
{
String xmlFileName = Utils.toFile(xmlFile).getAbsolutePath();
System.out.println("update bindings:");
System.out.println("\tConf File: " + xmlFileName);
System.out.println("\tBinding File: " + bindingXml);
System.out.println("\tBinding Name: " + bindingName);
DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
documentBuilderFactory.setNamespaceAware(true);
documentBuilderFactory.setValidating(false);
DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder();
Document doc1 = documentBuilder.parse(xmlFileName);
Document doc2 = documentBuilder.newDocument();
doc2.appendChild(doc2.createElement("server"));
NodeList children = doc1.getDocumentElement().getChildNodes();
Node server2 = doc2.getDocumentElement();
// add an mbean entry for the server binding
server2.appendChild(createBinding(doc2, bindingName, bindingXml));
for (int i=0; i< children.getLength(); i++)
{
Node child = children.item(i);
if ("mbean".equals(child.getNodeName()))
{
String name = ((Element) child).getAttribute("name");
// ignore the original binding since we are creating a new one
if (BINDING_MANAGER_NAME.equals(name))
continue;
}
// take a detached copy of the node and add it to the new document
Node copy = doc2.importNode(child, true).cloneNode(true);
server2.appendChild(copy);
}
printDocument(doc2, xmlFileName);
}
private static Element createBinding(Document document, String binding, String bindingXml)
{
Element mbean = document.createElement("mbean");
mbean.setAttribute("code", BINDING_MANAGER_CLASS);
mbean.setAttribute("name", BINDING_MANAGER_NAME);
mbean.appendChild(createMbeanAttribute(document, "ServerName", binding));
mbean.appendChild(createMbeanAttribute(document, "StoreURL", bindingXml));
mbean.appendChild(createMbeanAttribute(document, "StoreFactoryClassName", STORE_FACTORY_CLASS));
return mbean;
}
private static Element createMbeanAttribute(Document document, String name, String cdata)
{
Element element = document.createElement("attribute");
element.setAttribute("name", name);
element.setTextContent(cdata);
return element;
}
public static void printDocument(Document document, String fname){
try{
TransformerFactory tf = TransformerFactory.newInstance();
Transformer transformer = tf.newTransformer();
DOMSource source = new DOMSource(document);
StreamResult result;
if (fname == null)
result = new StreamResult(System.out);
else
result = new StreamResult(new FileWriter(fname));
transformer.transform(source, result);
}
catch(Exception e)
{
e.printStackTrace();
}
}
private static Document getDocument(String xmlFile)
{
Document doc = null;
DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
documentBuilderFactory.setNamespaceAware(true);
documentBuilderFactory.setValidating(false);
try
{
DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder();
doc = documentBuilder.parse(xmlFile);
}
catch (ParserConfigurationException e)
{
System.out.println("Unable to locate an XML doc builder: " + e.getMessage());
}
catch (Exception e)
{
System.out.println("Error parsing " + xmlFile + ' ' + e.getMessage());
}
return doc;
}
public static Node findServiceConfig(String bindingsFile, String server, String service)
{
Document doc = getDocument(bindingsFile);
if (doc == null)
return null;
Node node = findNode(doc.getDocumentElement(), "server", "name", server);
return (node != null ? findNode(node, "service-config", "name", service) : null);
}
public static String findBindingPort(Node node)
{
node = findNode(node, "binding", "port", null);
return (node != null ? ((Element) node).getAttribute("port") : null);
}
private static int parseInt(String intValue, int defValue, String errMsg)
{
try
{
return (intValue != null ? Integer.parseInt(intValue) : defValue);
}
catch (NumberFormatException e)
{
if (errMsg != null)
System.out.println(errMsg);
return defValue;
}
}
public static int lookupHttpPort(String bindingsFile, String server, int defValue)
{
Node node = findServiceConfig(bindingsFile, server, "jboss:service=invoker,type=http");
String port = findBindingPort(node);
return parseInt(port, defValue, "Invalid port found in service-config for binding " + server);
}
public static int lookupRmiPort(String bindingsFile, String server, int defValue)
{
Node node = findServiceConfig(bindingsFile, server, "jboss:service=Naming");
String port = findBindingPort(node);
return parseInt(port, defValue, "Invalid port found in service-config for binding " + server);
}
/**
* Find a node with a given name and having a specified attribute
* @param node the node to start the search from
* @param nodeName the name of the xml node to look for the attribute
* @param attrName the name of the attribute to match against
* @param attrValue the value of the attribute to match against. If null
* the first matching node with an attribute called attrName is returned
* @return the matching node
*/
private static Node findNode(Node node, String nodeName, String attrName, String attrValue)
{
if (node != null)
{
NodeList children = node.getChildNodes();
for (int i = 0; i < children.getLength(); i++)
{
Node child = children.item(i);
if (nodeName.equals(child.getNodeName()))
{
// found a node of the correct type - now see if it has the given attribute
String value = ((Element) child).getAttribute(attrName);
if (attrName == null || attrValue == null || value.equals(attrValue))
return child;
}
}
System.out.println("Node of type " + nodeName + " with " + attrName + '=' + attrValue + " not found");
}
return null;
}
public static void main(String[] args) throws IOException, ParserConfigurationException,
org.xml.sax.SAXException, TransformerException
{
if (args.length >= 3) {
setBinding(args[0], args[1], args[2]);
} else if (args.length == 2) {
System.out.println("Rmi port: " + lookupRmiPort(args[0], args[1], -1));
System.out.println("Http port: " + lookupHttpPort(args[0], args[1], -1));
} else {
System.out.println("syntax: ServerBindingConfig <conf file path> <server binding name> <path of bindings file>");
}
}
}