/servers/diameter/tools/jopr-plugin/src/main/java/org/rhq/plugins/diameter/jbossas5/util/JnpConfig.java
Java | 528 lines | 398 code | 81 blank | 49 comment | 97 complexity | 327b0af603d7bb389d3f000244e05562 MD5 | raw file
Possible License(s): LGPL-3.0, GPL-3.0, LGPL-2.1, GPL-2.0, CC-BY-SA-3.0, CC0-1.0, Apache-2.0, BSD-3-Clause
- /*
- * Jopr Management Platform
- * Copyright (C) 2005-2009 Red Hat, Inc.
- * All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License, version 2, as
- * published by the Free Software Foundation, and/or the GNU Lesser
- * General Public License, version 2.1, also as published by the Free
- * Software Foundation.
- *
- * This program 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 General Public License and the GNU Lesser General Public License
- * for more details.
- *
- * You should have received a copy of the GNU General Public License
- * and the GNU Lesser General Public License along with this program;
- * if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
- package org.rhq.plugins.diameter.jbossas5.util;
- import java.io.File;
- import java.io.FileInputStream;
- import java.io.IOException;
- import java.io.InputStream;
- import java.net.MalformedURLException;
- import java.net.URL;
- import java.util.HashMap;
- import java.util.Properties;
- import java.util.jar.JarEntry;
- import java.util.jar.JarFile;
- import javax.xml.parsers.ParserConfigurationException;
- import javax.xml.parsers.SAXParser;
- import javax.xml.parsers.SAXParserFactory;
- import org.apache.commons.logging.Log;
- import org.apache.commons.logging.LogFactory;
- import org.jetbrains.annotations.Nullable;
- import org.xml.sax.Attributes;
- import org.xml.sax.EntityResolver;
- import org.xml.sax.InputSource;
- import org.xml.sax.SAXException;
- import org.xml.sax.XMLReader;
- import org.xml.sax.helpers.DefaultHandler;
- import org.rhq.core.util.StringPropertyReplacer;
- import org.rhq.plugins.diameter.jbossas5.helper.JBossProperties;
- /**
- * This class will parse the passed File in the getConfig method. This file is normally the jboss-service.xml file in
- * the conf directory of the JBoss Server.
- * <p/>
- * Using a SaxParser it will look for the MBean tag for Naming, when it finds that it is in that tag, it will then look
- * for the Port attribute to determine the jnp port
- * <p/>
- * The JBossServerHandler class handles the searching, by determining when the SAX parser has started reading the
- * element that has the text that is being searched, and when that element has ended.
- * <p/>
- * Config parsing intended only for JBoss server auto discovery.
- */
- public class JnpConfig {
- private static Log log = LogFactory.getLog(JnpConfig.class);
- static final String PROPERTY_EXPRESSION_PREFIX = "${";
- private static final HashMap<File, JnpConfig> CACHE = new HashMap<File, JnpConfig>();
- private String jnpAddress;
- private Integer jnpPort;
- private long lastModified = 0;
- private String serverName;
- private File storeFile;
- private Properties systemProperties;
- private JnpConfig(Properties systemProperties) {
- this.systemProperties = systemProperties;
- }
- public static synchronized JnpConfig getConfig(final File distributionDirectory, File configXML,
- Properties systemProperties) {
- JnpConfig config = CACHE.get(configXML);
- long lastModified = configXML.lastModified();
- if ((config == null) || (lastModified != config.lastModified)) {
- config = new JnpConfig(systemProperties);
- config.lastModified = lastModified;
- CACHE.put(configXML, config);
- try {
- config.read(distributionDirectory, configXML);
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
- return config;
- }
- /**
- * Returns the JNP port, or null if the port could not be determined.
- *
- * @return the JNP port, or null if the port could not be determined
- */
- @Nullable
- public Integer getJnpPort() {
- return this.jnpPort;
- }
- /**
- * Returns the JNP address, or null if the address could not be determined.
- *
- * @return the JNP address, or null if the address could not be determined
- */
- @Nullable
- public String getJnpAddress() {
- return this.jnpAddress;
- }
- private void read(File distributionDirectory, File file) throws IOException {
- try {
- parseServiceXML(distributionDirectory, file);
- } catch (SAXException e) {
- throw new IllegalArgumentException(e.getMessage());
- } catch (ParserConfigurationException e) {
- throw new IllegalArgumentException(e.getMessage());
- }
- // Not in that first xml - let's try the binding service xml...
- if (this.jnpPort == null && this.storeFile != null) {
- parseBindingManagerXML();
- }
- }
- private void parseServiceXML(File distributionDirectory, File serviceXmlFile) throws IOException, SAXException,
- ParserConfigurationException {
- FileInputStream is = null;
- try {
- is = new FileInputStream(serviceXmlFile);
- SAXParserFactory factory = SAXParserFactory.newInstance();
- SAXParser parser = factory.newSAXParser();
- EntityResolver r = new LocalEntityResolver(distributionDirectory);
- JBossServiceHandler handler = new JBossServiceHandler(serviceXmlFile);
- XMLReader reader = parser.getXMLReader();
- reader.setEntityResolver(r);
- reader.setContentHandler(handler);
- reader.parse(new InputSource(is));
- this.jnpAddress = handler.getNamingBindAddress();
- this.jnpPort = handler.getNamingPort();
- this.storeFile = handler.getStoreFile();
- this.serverName = handler.getServerName();
- } finally {
- if (is != null) {
- is.close();
- }
- }
- }
- private void parseBindingManagerXML() throws IOException {
- InputStream bindIs = null;
- try {
- SAXParserFactory factory = SAXParserFactory.newInstance();
- SAXParser parser = factory.newSAXParser();
- if (!this.storeFile.isFile()) {
- log.warn("Store file does not exist: " + this.storeFile);
- return;
- }
- JBossBindingManagerHandler bindingHandler = new JBossBindingManagerHandler(this.storeFile);
- bindingHandler.setServerName(this.serverName);
- XMLReader reader = parser.getXMLReader();
- bindIs = new FileInputStream(this.storeFile);
- reader.setContentHandler(bindingHandler);
- reader.parse(new InputSource(bindIs));
- this.jnpAddress = bindingHandler.getJnpAddress();
- this.jnpPort = bindingHandler.getJnpPort();
- } catch (Exception e) {
- throw new IllegalArgumentException(e.getMessage());
- } finally {
- if (bindIs != null) {
- bindIs.close();
- }
- }
- }
- private class JBossBindingManagerHandler extends DefaultHandler {
- private File file;
- private boolean inServer = false;
- private boolean inServiceConfig = false;
- private boolean inNamingPort = false;
- private String jnpAddress;
- private Integer jnpPort;
- private String serverName;
- private JBossBindingManagerHandler(File file) {
- this.file = file;
- }
- @Override
- public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
- if (qName.equals("server")) {
- String name = attributes.getValue("name");
- if ((name != null) && name.equals(serverName)) {
- inServer = true;
- return;
- }
- }
- if (inServer && qName.equals("service-config")) {
- String name = attributes.getValue("name");
- if ((name != null) && name.equals("jboss:service=Naming")) {
- inServiceConfig = true;
- return;
- }
- }
- if (inServiceConfig && qName.equals("binding")) {
- jnpAddress = replaceProperties(attributes.getValue("host"));
- if (jnpAddress.substring(0, PROPERTY_EXPRESSION_PREFIX.length()).equals(PROPERTY_EXPRESSION_PREFIX)) {
- log.warn("Naming binding 'host' attribute has invalid value (" + jnpAddress
- + ") in JBossAS config file " + file
- + " - the value should be a host name, an IP address, or a resolvable property reference.");
- jnpAddress = null;
- }
- String jnpPortString = replaceProperties(attributes.getValue("port"));
- try {
- jnpPort = Integer.parseInt(jnpPortString);
- } catch (NumberFormatException e) {
- log.warn("Naming binding 'port' attribute has invalid value (" + jnpPortString
- + ") in JBossAS config file " + file
- + " - the value should be a positive integer or a resolvable property reference.");
- jnpPort = null;
- }
- }
- }
- @Override
- public void endElement(String uri, String localName, String qName) {
- if (inServiceConfig && qName.equals("binding")) {
- inServiceConfig = false;
- }
- if (inNamingPort && qName.equals("service-config")) {
- inNamingPort = false;
- }
- if (inServer && qName.equals("server")) {
- inServer = false;
- }
- }
- public String getJnpAddress() {
- return this.jnpAddress;
- }
- protected Integer getJnpPort() {
- return this.jnpPort;
- }
- protected void setServerName(String serverName) {
- this.serverName = serverName;
- }
- }
- private class JBossServiceHandler extends DefaultHandler {
- private static final String DEFAULT_JNP_ADDRESS = "0.0.0.0";
- private static final String DEFAULT_JNP_PORT = "1099";
- private File file;
- //Naming Service
- private boolean inNaming = false;
- private boolean inNamingPort = false;
- private boolean inNamingBindAddress = false;
- private StringBuilder namingPort = null;
- private StringBuilder namingBindAddress = null;
- //Binding Manager
- private boolean inBinding = false;
- private boolean inServerName = false;
- private boolean inStoreURL = false;
- private boolean isBindingManagerInUse = false;
- private StringBuilder storeURL = new StringBuilder();
- private StringBuilder serverName = new StringBuilder();
- private JBossServiceHandler(File filePath) {
- this.file = filePath;
- }
- @Override
- public void characters(char[] ch, int start, int length) throws SAXException {
- if (inNamingBindAddress) {
- namingBindAddress.append(ch, start, length);
- } else if (inNamingPort) {
- namingPort.append(ch, start, length);
- } else if (inServerName) {
- serverName.append(ch, start, length);
- } else if (inStoreURL) {
- storeURL.append(ch, start, length);
- }
- }
- @Override
- public void endElement(String uri, String localName, String qName) {
- if (inNamingPort && qName.equals("attribute")) {
- inNamingPort = false;
- namingPort = processValue(namingPort, DEFAULT_JNP_PORT);
- return;
- }
- if (inNamingBindAddress && qName.equals("attribute")) {
- inNamingBindAddress = false;
- namingBindAddress = processValue(namingBindAddress, DEFAULT_JNP_ADDRESS);
- return;
- }
- if (inServerName && qName.equals("attribute")) {
- inServerName = false;
- serverName = processValue(serverName, null);
- return;
- }
- if (inStoreURL && qName.equals("attribute")) {
- storeURL = processValue(storeURL, null);
- inStoreURL = false;
- return;
- }
- if (inNaming && qName.equals("mbean")) {
- inNaming = false;
- return;
- }
- if (inBinding && qName.equals("mbean")) {
- inBinding = false;
- }
- }
- @Override
- public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
- if (inNaming && qName.equals("attribute")) {
- String name = attributes.getValue("name");
- if (name != null) {
- if (name.equals("Port")) {
- inNamingPort = true;
- namingPort = new StringBuilder();
- return;
- } else if (name.equals("BindAddress")) {
- inNamingBindAddress = true;
- namingBindAddress = new StringBuilder();
- return;
- }
- }
- }
- if (inBinding && qName.equals("attribute")) {
- String name = attributes.getValue("name");
- if ((name != null) && name.equals("ServerName")) {
- inServerName = true;
- return;
- }
- if ((name != null) && name.equals("StoreURL")) {
- inStoreURL = true;
- return;
- }
- }
- if (qName.equals("mbean")) {
- String name = attributes.getValue("name");
- if ((name != null) && name.equals("jboss:service=Naming")) {
- inNaming = true;
- return;
- }
- if ((name != null) && name.equals("jboss.system:service=ServiceBindingManager")) {
- inBinding = true;
- isBindingManagerInUse = true;
- }
- }
- }
- protected Integer getNamingPort() {
- if (isBindingManagerInUse) {
- return null;
- }
- if (null == namingPort) {
- log.warn("Naming 'RmiPort' attribute not found in JBossAS config file " + file
- + ". This may be ok as it can be specified in more than one place.");
- return null;
- }
- try {
- return Integer.parseInt(namingPort.toString());
- } catch (NumberFormatException e) {
- log.warn("Naming 'Port' attribute has invalid value (" + namingPort + ") in JBossAS config file "
- + file + " - the value should be a positive integer or a resolvable property reference.");
- return null;
- }
- }
- protected String getNamingBindAddress() {
- if (isBindingManagerInUse) {
- return null;
- }
- if (null == namingBindAddress) {
- log.warn("Naming 'BindingAddress' attribute not found in JBossAS config file " + file
- + ". This may be ok as it can be specified in more than one place.");
- return null;
- }
- String bindAddressString = namingBindAddress.toString();
- if ((null == bindAddressString) || bindAddressString.startsWith(PROPERTY_EXPRESSION_PREFIX)) {
- log.warn("Naming 'BindingAddress' attribute has invalid value (" + namingBindAddress
- + ") in JBossAS config file " + file
- + ". The value should be a host name, an IP address, or a resolvable property reference.");
- return null;
- }
- return bindAddressString;
- }
- protected String getServerName() {
- return serverName.toString();
- }
- protected File getStoreFile() {
- File homeDir = new File(systemProperties.getProperty(JBossProperties.HOME_DIR));
- try {
- URL url = JBossConfigurationUtility.makeURL(storeURL.toString(), homeDir);
- if (!"file".equals(url.getProtocol())) {
- // TODO: Do we need to support non-file URL's too?
- throw new MalformedURLException();
- }
- return new File(url.getPath());
- } catch (MalformedURLException e) {
- log.warn("Binding 'StoreURL' attribute has invalid value (" + storeURL + ") in JBossAS config file "
- + file + " - the value should be a file URL or file path.");
- return null;
- }
- }
- private StringBuilder processValue(StringBuilder value, String defaultValue) {
- String stringValue = value.toString().trim();
- if (stringValue.equals("") && defaultValue != null) {
- stringValue = defaultValue;
- }
- stringValue = replaceProperties(stringValue);
- return new StringBuilder(stringValue);
- }
- }
- public static class LocalEntityResolver implements EntityResolver {
- static Properties resolverMap = new Properties();
- static {
- resolverMap.setProperty("-//JBoss//DTD JBOSS 3.2//EN", "jboss-service_3_2.dtd");
- resolverMap.setProperty("-//JBoss//DTD JBOSS 4.0//EN", "jboss-service_4_0.dtd");
- }
- private File distributionDirectory;
- public LocalEntityResolver(File distributionDirectory) {
- this.distributionDirectory = distributionDirectory;
- }
- public InputSource resolveEntity(String publicId, String systemId) throws SAXException, IOException {
- if (log.isDebugEnabled())
- log.debug("Resolving DTD [" + publicId + "]...");
- String dtdName = resolverMap.getProperty(publicId);
- if (dtdName != null) {
- File systemJar = new File(distributionDirectory + File.separator + "lib" + File.separator
- + "jboss-system.jar");
- if (systemJar.exists()) {
- JarFile j = new JarFile(systemJar);
- JarEntry entry = j.getJarEntry("dtd/" + dtdName);
- if (entry == null) {
- entry = j.getJarEntry("org/jboss/metadata/" + dtdName);
- }
- if (entry != null) {
- if (log.isDebugEnabled())
- log.debug("Found DTD locally: " + entry.getName());
- return new InputSource(j.getInputStream(entry));
- }
- }
- }
- return null;
- }
- }
- private String replaceProperties(String value) {
- return (value != null) ? StringPropertyReplacer.replaceProperties(value, this.systemProperties) : null;
- }
- public static void main(String[] args) throws Exception {
- if (args.length != 1) {
- System.err.println("Usage: <config file>");
- System.exit(1);
- }
- File serviceFile = new File(args[0]);
- File distDir = serviceFile.getParentFile().getParentFile().getParentFile().getParentFile();
- // Pass in an empty set of System properties.
- JnpConfig cfg = JnpConfig.getConfig(distDir, serviceFile, new Properties());
- System.out.println("JNP address: " + cfg.getJnpAddress());
- System.out.println("JNP port: " + cfg.getJnpPort());
- }
- }