PageRenderTime 48ms CodeModel.GetById 18ms RepoModel.GetById 0ms app.codeStats 0ms

/servers/diameter/tools/jopr-plugin/src/main/java/org/rhq/plugins/diameter/jbossas5/util/JnpConfig.java

http://mobicents.googlecode.com/
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
  1. /*
  2. * Jopr Management Platform
  3. * Copyright (C) 2005-2009 Red Hat, Inc.
  4. * All rights reserved.
  5. *
  6. * This program is free software; you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License, version 2, as
  8. * published by the Free Software Foundation, and/or the GNU Lesser
  9. * General Public License, version 2.1, also as published by the Free
  10. * Software Foundation.
  11. *
  12. * This program is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. * GNU General Public License and the GNU Lesser General Public License
  16. * for more details.
  17. *
  18. * You should have received a copy of the GNU General Public License
  19. * and the GNU Lesser General Public License along with this program;
  20. * if not, write to the Free Software Foundation, Inc.,
  21. * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  22. */
  23. package org.rhq.plugins.diameter.jbossas5.util;
  24. import java.io.File;
  25. import java.io.FileInputStream;
  26. import java.io.IOException;
  27. import java.io.InputStream;
  28. import java.net.MalformedURLException;
  29. import java.net.URL;
  30. import java.util.HashMap;
  31. import java.util.Properties;
  32. import java.util.jar.JarEntry;
  33. import java.util.jar.JarFile;
  34. import javax.xml.parsers.ParserConfigurationException;
  35. import javax.xml.parsers.SAXParser;
  36. import javax.xml.parsers.SAXParserFactory;
  37. import org.apache.commons.logging.Log;
  38. import org.apache.commons.logging.LogFactory;
  39. import org.jetbrains.annotations.Nullable;
  40. import org.xml.sax.Attributes;
  41. import org.xml.sax.EntityResolver;
  42. import org.xml.sax.InputSource;
  43. import org.xml.sax.SAXException;
  44. import org.xml.sax.XMLReader;
  45. import org.xml.sax.helpers.DefaultHandler;
  46. import org.rhq.core.util.StringPropertyReplacer;
  47. import org.rhq.plugins.diameter.jbossas5.helper.JBossProperties;
  48. /**
  49. * This class will parse the passed File in the getConfig method. This file is normally the jboss-service.xml file in
  50. * the conf directory of the JBoss Server.
  51. * <p/>
  52. * 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
  53. * for the Port attribute to determine the jnp port
  54. * <p/>
  55. * The JBossServerHandler class handles the searching, by determining when the SAX parser has started reading the
  56. * element that has the text that is being searched, and when that element has ended.
  57. * <p/>
  58. * Config parsing intended only for JBoss server auto discovery.
  59. */
  60. public class JnpConfig {
  61. private static Log log = LogFactory.getLog(JnpConfig.class);
  62. static final String PROPERTY_EXPRESSION_PREFIX = "${";
  63. private static final HashMap<File, JnpConfig> CACHE = new HashMap<File, JnpConfig>();
  64. private String jnpAddress;
  65. private Integer jnpPort;
  66. private long lastModified = 0;
  67. private String serverName;
  68. private File storeFile;
  69. private Properties systemProperties;
  70. private JnpConfig(Properties systemProperties) {
  71. this.systemProperties = systemProperties;
  72. }
  73. public static synchronized JnpConfig getConfig(final File distributionDirectory, File configXML,
  74. Properties systemProperties) {
  75. JnpConfig config = CACHE.get(configXML);
  76. long lastModified = configXML.lastModified();
  77. if ((config == null) || (lastModified != config.lastModified)) {
  78. config = new JnpConfig(systemProperties);
  79. config.lastModified = lastModified;
  80. CACHE.put(configXML, config);
  81. try {
  82. config.read(distributionDirectory, configXML);
  83. } catch (IOException e) {
  84. e.printStackTrace();
  85. }
  86. }
  87. return config;
  88. }
  89. /**
  90. * Returns the JNP port, or null if the port could not be determined.
  91. *
  92. * @return the JNP port, or null if the port could not be determined
  93. */
  94. @Nullable
  95. public Integer getJnpPort() {
  96. return this.jnpPort;
  97. }
  98. /**
  99. * Returns the JNP address, or null if the address could not be determined.
  100. *
  101. * @return the JNP address, or null if the address could not be determined
  102. */
  103. @Nullable
  104. public String getJnpAddress() {
  105. return this.jnpAddress;
  106. }
  107. private void read(File distributionDirectory, File file) throws IOException {
  108. try {
  109. parseServiceXML(distributionDirectory, file);
  110. } catch (SAXException e) {
  111. throw new IllegalArgumentException(e.getMessage());
  112. } catch (ParserConfigurationException e) {
  113. throw new IllegalArgumentException(e.getMessage());
  114. }
  115. // Not in that first xml - let's try the binding service xml...
  116. if (this.jnpPort == null && this.storeFile != null) {
  117. parseBindingManagerXML();
  118. }
  119. }
  120. private void parseServiceXML(File distributionDirectory, File serviceXmlFile) throws IOException, SAXException,
  121. ParserConfigurationException {
  122. FileInputStream is = null;
  123. try {
  124. is = new FileInputStream(serviceXmlFile);
  125. SAXParserFactory factory = SAXParserFactory.newInstance();
  126. SAXParser parser = factory.newSAXParser();
  127. EntityResolver r = new LocalEntityResolver(distributionDirectory);
  128. JBossServiceHandler handler = new JBossServiceHandler(serviceXmlFile);
  129. XMLReader reader = parser.getXMLReader();
  130. reader.setEntityResolver(r);
  131. reader.setContentHandler(handler);
  132. reader.parse(new InputSource(is));
  133. this.jnpAddress = handler.getNamingBindAddress();
  134. this.jnpPort = handler.getNamingPort();
  135. this.storeFile = handler.getStoreFile();
  136. this.serverName = handler.getServerName();
  137. } finally {
  138. if (is != null) {
  139. is.close();
  140. }
  141. }
  142. }
  143. private void parseBindingManagerXML() throws IOException {
  144. InputStream bindIs = null;
  145. try {
  146. SAXParserFactory factory = SAXParserFactory.newInstance();
  147. SAXParser parser = factory.newSAXParser();
  148. if (!this.storeFile.isFile()) {
  149. log.warn("Store file does not exist: " + this.storeFile);
  150. return;
  151. }
  152. JBossBindingManagerHandler bindingHandler = new JBossBindingManagerHandler(this.storeFile);
  153. bindingHandler.setServerName(this.serverName);
  154. XMLReader reader = parser.getXMLReader();
  155. bindIs = new FileInputStream(this.storeFile);
  156. reader.setContentHandler(bindingHandler);
  157. reader.parse(new InputSource(bindIs));
  158. this.jnpAddress = bindingHandler.getJnpAddress();
  159. this.jnpPort = bindingHandler.getJnpPort();
  160. } catch (Exception e) {
  161. throw new IllegalArgumentException(e.getMessage());
  162. } finally {
  163. if (bindIs != null) {
  164. bindIs.close();
  165. }
  166. }
  167. }
  168. private class JBossBindingManagerHandler extends DefaultHandler {
  169. private File file;
  170. private boolean inServer = false;
  171. private boolean inServiceConfig = false;
  172. private boolean inNamingPort = false;
  173. private String jnpAddress;
  174. private Integer jnpPort;
  175. private String serverName;
  176. private JBossBindingManagerHandler(File file) {
  177. this.file = file;
  178. }
  179. @Override
  180. public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
  181. if (qName.equals("server")) {
  182. String name = attributes.getValue("name");
  183. if ((name != null) && name.equals(serverName)) {
  184. inServer = true;
  185. return;
  186. }
  187. }
  188. if (inServer && qName.equals("service-config")) {
  189. String name = attributes.getValue("name");
  190. if ((name != null) && name.equals("jboss:service=Naming")) {
  191. inServiceConfig = true;
  192. return;
  193. }
  194. }
  195. if (inServiceConfig && qName.equals("binding")) {
  196. jnpAddress = replaceProperties(attributes.getValue("host"));
  197. if (jnpAddress.substring(0, PROPERTY_EXPRESSION_PREFIX.length()).equals(PROPERTY_EXPRESSION_PREFIX)) {
  198. log.warn("Naming binding 'host' attribute has invalid value (" + jnpAddress
  199. + ") in JBossAS config file " + file
  200. + " - the value should be a host name, an IP address, or a resolvable property reference.");
  201. jnpAddress = null;
  202. }
  203. String jnpPortString = replaceProperties(attributes.getValue("port"));
  204. try {
  205. jnpPort = Integer.parseInt(jnpPortString);
  206. } catch (NumberFormatException e) {
  207. log.warn("Naming binding 'port' attribute has invalid value (" + jnpPortString
  208. + ") in JBossAS config file " + file
  209. + " - the value should be a positive integer or a resolvable property reference.");
  210. jnpPort = null;
  211. }
  212. }
  213. }
  214. @Override
  215. public void endElement(String uri, String localName, String qName) {
  216. if (inServiceConfig && qName.equals("binding")) {
  217. inServiceConfig = false;
  218. }
  219. if (inNamingPort && qName.equals("service-config")) {
  220. inNamingPort = false;
  221. }
  222. if (inServer && qName.equals("server")) {
  223. inServer = false;
  224. }
  225. }
  226. public String getJnpAddress() {
  227. return this.jnpAddress;
  228. }
  229. protected Integer getJnpPort() {
  230. return this.jnpPort;
  231. }
  232. protected void setServerName(String serverName) {
  233. this.serverName = serverName;
  234. }
  235. }
  236. private class JBossServiceHandler extends DefaultHandler {
  237. private static final String DEFAULT_JNP_ADDRESS = "0.0.0.0";
  238. private static final String DEFAULT_JNP_PORT = "1099";
  239. private File file;
  240. //Naming Service
  241. private boolean inNaming = false;
  242. private boolean inNamingPort = false;
  243. private boolean inNamingBindAddress = false;
  244. private StringBuilder namingPort = null;
  245. private StringBuilder namingBindAddress = null;
  246. //Binding Manager
  247. private boolean inBinding = false;
  248. private boolean inServerName = false;
  249. private boolean inStoreURL = false;
  250. private boolean isBindingManagerInUse = false;
  251. private StringBuilder storeURL = new StringBuilder();
  252. private StringBuilder serverName = new StringBuilder();
  253. private JBossServiceHandler(File filePath) {
  254. this.file = filePath;
  255. }
  256. @Override
  257. public void characters(char[] ch, int start, int length) throws SAXException {
  258. if (inNamingBindAddress) {
  259. namingBindAddress.append(ch, start, length);
  260. } else if (inNamingPort) {
  261. namingPort.append(ch, start, length);
  262. } else if (inServerName) {
  263. serverName.append(ch, start, length);
  264. } else if (inStoreURL) {
  265. storeURL.append(ch, start, length);
  266. }
  267. }
  268. @Override
  269. public void endElement(String uri, String localName, String qName) {
  270. if (inNamingPort && qName.equals("attribute")) {
  271. inNamingPort = false;
  272. namingPort = processValue(namingPort, DEFAULT_JNP_PORT);
  273. return;
  274. }
  275. if (inNamingBindAddress && qName.equals("attribute")) {
  276. inNamingBindAddress = false;
  277. namingBindAddress = processValue(namingBindAddress, DEFAULT_JNP_ADDRESS);
  278. return;
  279. }
  280. if (inServerName && qName.equals("attribute")) {
  281. inServerName = false;
  282. serverName = processValue(serverName, null);
  283. return;
  284. }
  285. if (inStoreURL && qName.equals("attribute")) {
  286. storeURL = processValue(storeURL, null);
  287. inStoreURL = false;
  288. return;
  289. }
  290. if (inNaming && qName.equals("mbean")) {
  291. inNaming = false;
  292. return;
  293. }
  294. if (inBinding && qName.equals("mbean")) {
  295. inBinding = false;
  296. }
  297. }
  298. @Override
  299. public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
  300. if (inNaming && qName.equals("attribute")) {
  301. String name = attributes.getValue("name");
  302. if (name != null) {
  303. if (name.equals("Port")) {
  304. inNamingPort = true;
  305. namingPort = new StringBuilder();
  306. return;
  307. } else if (name.equals("BindAddress")) {
  308. inNamingBindAddress = true;
  309. namingBindAddress = new StringBuilder();
  310. return;
  311. }
  312. }
  313. }
  314. if (inBinding && qName.equals("attribute")) {
  315. String name = attributes.getValue("name");
  316. if ((name != null) && name.equals("ServerName")) {
  317. inServerName = true;
  318. return;
  319. }
  320. if ((name != null) && name.equals("StoreURL")) {
  321. inStoreURL = true;
  322. return;
  323. }
  324. }
  325. if (qName.equals("mbean")) {
  326. String name = attributes.getValue("name");
  327. if ((name != null) && name.equals("jboss:service=Naming")) {
  328. inNaming = true;
  329. return;
  330. }
  331. if ((name != null) && name.equals("jboss.system:service=ServiceBindingManager")) {
  332. inBinding = true;
  333. isBindingManagerInUse = true;
  334. }
  335. }
  336. }
  337. protected Integer getNamingPort() {
  338. if (isBindingManagerInUse) {
  339. return null;
  340. }
  341. if (null == namingPort) {
  342. log.warn("Naming 'RmiPort' attribute not found in JBossAS config file " + file
  343. + ". This may be ok as it can be specified in more than one place.");
  344. return null;
  345. }
  346. try {
  347. return Integer.parseInt(namingPort.toString());
  348. } catch (NumberFormatException e) {
  349. log.warn("Naming 'Port' attribute has invalid value (" + namingPort + ") in JBossAS config file "
  350. + file + " - the value should be a positive integer or a resolvable property reference.");
  351. return null;
  352. }
  353. }
  354. protected String getNamingBindAddress() {
  355. if (isBindingManagerInUse) {
  356. return null;
  357. }
  358. if (null == namingBindAddress) {
  359. log.warn("Naming 'BindingAddress' attribute not found in JBossAS config file " + file
  360. + ". This may be ok as it can be specified in more than one place.");
  361. return null;
  362. }
  363. String bindAddressString = namingBindAddress.toString();
  364. if ((null == bindAddressString) || bindAddressString.startsWith(PROPERTY_EXPRESSION_PREFIX)) {
  365. log.warn("Naming 'BindingAddress' attribute has invalid value (" + namingBindAddress
  366. + ") in JBossAS config file " + file
  367. + ". The value should be a host name, an IP address, or a resolvable property reference.");
  368. return null;
  369. }
  370. return bindAddressString;
  371. }
  372. protected String getServerName() {
  373. return serverName.toString();
  374. }
  375. protected File getStoreFile() {
  376. File homeDir = new File(systemProperties.getProperty(JBossProperties.HOME_DIR));
  377. try {
  378. URL url = JBossConfigurationUtility.makeURL(storeURL.toString(), homeDir);
  379. if (!"file".equals(url.getProtocol())) {
  380. // TODO: Do we need to support non-file URL's too?
  381. throw new MalformedURLException();
  382. }
  383. return new File(url.getPath());
  384. } catch (MalformedURLException e) {
  385. log.warn("Binding 'StoreURL' attribute has invalid value (" + storeURL + ") in JBossAS config file "
  386. + file + " - the value should be a file URL or file path.");
  387. return null;
  388. }
  389. }
  390. private StringBuilder processValue(StringBuilder value, String defaultValue) {
  391. String stringValue = value.toString().trim();
  392. if (stringValue.equals("") && defaultValue != null) {
  393. stringValue = defaultValue;
  394. }
  395. stringValue = replaceProperties(stringValue);
  396. return new StringBuilder(stringValue);
  397. }
  398. }
  399. public static class LocalEntityResolver implements EntityResolver {
  400. static Properties resolverMap = new Properties();
  401. static {
  402. resolverMap.setProperty("-//JBoss//DTD JBOSS 3.2//EN", "jboss-service_3_2.dtd");
  403. resolverMap.setProperty("-//JBoss//DTD JBOSS 4.0//EN", "jboss-service_4_0.dtd");
  404. }
  405. private File distributionDirectory;
  406. public LocalEntityResolver(File distributionDirectory) {
  407. this.distributionDirectory = distributionDirectory;
  408. }
  409. public InputSource resolveEntity(String publicId, String systemId) throws SAXException, IOException {
  410. if (log.isDebugEnabled())
  411. log.debug("Resolving DTD [" + publicId + "]...");
  412. String dtdName = resolverMap.getProperty(publicId);
  413. if (dtdName != null) {
  414. File systemJar = new File(distributionDirectory + File.separator + "lib" + File.separator
  415. + "jboss-system.jar");
  416. if (systemJar.exists()) {
  417. JarFile j = new JarFile(systemJar);
  418. JarEntry entry = j.getJarEntry("dtd/" + dtdName);
  419. if (entry == null) {
  420. entry = j.getJarEntry("org/jboss/metadata/" + dtdName);
  421. }
  422. if (entry != null) {
  423. if (log.isDebugEnabled())
  424. log.debug("Found DTD locally: " + entry.getName());
  425. return new InputSource(j.getInputStream(entry));
  426. }
  427. }
  428. }
  429. return null;
  430. }
  431. }
  432. private String replaceProperties(String value) {
  433. return (value != null) ? StringPropertyReplacer.replaceProperties(value, this.systemProperties) : null;
  434. }
  435. public static void main(String[] args) throws Exception {
  436. if (args.length != 1) {
  437. System.err.println("Usage: <config file>");
  438. System.exit(1);
  439. }
  440. File serviceFile = new File(args[0]);
  441. File distDir = serviceFile.getParentFile().getParentFile().getParentFile().getParentFile();
  442. // Pass in an empty set of System properties.
  443. JnpConfig cfg = JnpConfig.getConfig(distDir, serviceFile, new Properties());
  444. System.out.println("JNP address: " + cfg.getJnpAddress());
  445. System.out.println("JNP port: " + cfg.getJnpPort());
  446. }
  447. }