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

/projects/tomcat-7.0.2/java/org/apache/catalina/ant/jmx/JMXAccessorTask.java

https://gitlab.com/essere.lab.public/qualitas.class-corpus
Java | 731 lines | 420 code | 81 blank | 230 comment | 115 complexity | ac2f88f6a158b28d6775c4468ed99002 MD5 | raw file
  1. /*
  2. * Licensed to the Apache Software Foundation (ASF) under one or more
  3. * contributor license agreements. See the NOTICE file distributed with
  4. * this work for additional information regarding copyright ownership.
  5. * The ASF licenses this file to You under the Apache License, Version 2.0
  6. * (the "License"); you may not use this file except in compliance with
  7. * the License. You may obtain a copy of the License at
  8. *
  9. * http://www.apache.org/licenses/LICENSE-2.0
  10. *
  11. * Unless required by applicable law or agreed to in writing, software
  12. * distributed under the License is distributed on an "AS IS" BASIS,
  13. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14. * See the License for the specific language governing permissions and
  15. * limitations under the License.
  16. */
  17. package org.apache.catalina.ant.jmx;
  18. import java.io.IOException;
  19. import java.lang.reflect.Array;
  20. import java.net.InetAddress;
  21. import java.net.MalformedURLException;
  22. import java.net.UnknownHostException;
  23. import java.util.HashMap;
  24. import java.util.Iterator;
  25. import java.util.List;
  26. import java.util.Map;
  27. import java.util.Properties;
  28. import java.util.Set;
  29. import java.util.StringTokenizer;
  30. import javax.management.MBeanServerConnection;
  31. import javax.management.MalformedObjectNameException;
  32. import javax.management.ObjectName;
  33. import javax.management.openmbean.CompositeData;
  34. import javax.management.openmbean.CompositeDataSupport;
  35. import javax.management.openmbean.CompositeType;
  36. import javax.management.openmbean.OpenType;
  37. import javax.management.openmbean.SimpleType;
  38. import javax.management.openmbean.TabularDataSupport;
  39. import javax.management.remote.JMXConnector;
  40. import javax.management.remote.JMXConnectorFactory;
  41. import javax.management.remote.JMXServiceURL;
  42. import org.apache.catalina.ant.BaseRedirectorHelperTask;
  43. import org.apache.tools.ant.BuildException;
  44. import org.apache.tools.ant.Project;
  45. /**
  46. * Access <em>JMX</em> JSR 160 MBeans Server.
  47. * <ul>
  48. * <li>open more then one JSR 160 rmi connection</li>
  49. * <li>Get/Set Mbeans attributes</li>
  50. * <li>Call Mbean Operation with arguments</li>
  51. * <li>Argument values can be converted from string to
  52. * int,long,float,double,boolean,ObjectName or InetAddress</li>
  53. * <li>Query Mbeans</li>
  54. * <li>Show Get, Call, Query result at Ant console log</li>
  55. * <li>Bind Get, Call, Query result at Ant properties</li>
  56. * </ul>
  57. *
  58. * Examples: open server with reference and autorisation
  59. *
  60. * <pre>
  61. *
  62. * &lt;jmxOpen
  63. * host=&quot;127.0.0.1&quot;
  64. * port=&quot;9014&quot;
  65. * username=&quot;monitorRole&quot;
  66. * password=&quot;mysecret&quot;
  67. * ref=&quot;jmx.myserver&quot;
  68. * /&gt;
  69. *
  70. * </pre>
  71. *
  72. * All calls after opening with same refid reuse the connection.
  73. * <p>
  74. * First call to a remote MBeanserver save the JMXConnection a referenz
  75. * <em>jmx.server</em>
  76. * </p>
  77. * All JMXAccessorXXXTask support the attribute <em>if</em> and
  78. * <em>unless</em>. With <em>if</em> the task is only execute when property
  79. * exist and with <em>unless</em> when property not exists. <br/><b>NOTE
  80. * </b>: These tasks require Ant 1.6 or later interface.
  81. *
  82. * @author Peter Rossbach
  83. * @version $Id: JMXAccessorTask.java 939305 2010-04-29 13:43:39Z kkolinko $
  84. * @since 5.5.10
  85. */
  86. public class JMXAccessorTask extends BaseRedirectorHelperTask {
  87. public static final String JMX_SERVICE_PREFIX = "service:jmx:rmi:///jndi/rmi://";
  88. public static final String JMX_SERVICE_SUFFIX = "/jmxrmi";
  89. // ----------------------------------------------------- Instance Variables
  90. private String name = null;
  91. private String resultproperty;
  92. private String url = null;
  93. private String host = "localhost";
  94. private String port = "8050";
  95. private String password = null;
  96. private String username = null;
  97. private String ref = "jmx.server";
  98. private boolean echo = false;
  99. private boolean separatearrayresults = true;
  100. private String delimiter;
  101. private String unlessCondition;
  102. private String ifCondition;
  103. private Properties properties = new Properties();
  104. // ----------------------------------------------------- Instance Info
  105. /**
  106. * Descriptive information describing this implementation.
  107. */
  108. private static final String info = "org.apache.catalina.ant.JMXAccessorTask/1.1";
  109. /**
  110. * Return descriptive information about this implementation and the
  111. * corresponding version number, in the format
  112. * <code>&lt;description&gt;/&lt;version&gt;</code>.
  113. */
  114. public String getInfo() {
  115. return (info);
  116. }
  117. // ------------------------------------------------------------- Properties
  118. /**
  119. * The name used at remote MbeanServer
  120. */
  121. public String getName() {
  122. return (this.name);
  123. }
  124. public void setName(String objectName) {
  125. this.name = objectName;
  126. }
  127. /**
  128. * @return Returns the resultproperty.
  129. */
  130. public String getResultproperty() {
  131. return resultproperty;
  132. }
  133. /**
  134. * @param propertyName The resultproperty to set.
  135. */
  136. public void setResultproperty(String propertyName) {
  137. this.resultproperty = propertyName;
  138. }
  139. /**
  140. * @return Returns the delimiter.
  141. */
  142. public String getDelimiter() {
  143. return delimiter;
  144. }
  145. /**
  146. * @param separator The delimiter to set.
  147. */
  148. public void setDelimiter(String separator) {
  149. this.delimiter = separator;
  150. }
  151. /**
  152. * @return Returns the echo.
  153. */
  154. public boolean isEcho() {
  155. return echo;
  156. }
  157. /**
  158. * @param echo
  159. * The echo to set.
  160. */
  161. public void setEcho(boolean echo) {
  162. this.echo = echo;
  163. }
  164. /**
  165. * @return Returns the separatearrayresults.
  166. */
  167. public boolean isSeparatearrayresults() {
  168. return separatearrayresults;
  169. }
  170. /**
  171. * @param separateArrayResults
  172. * The separatearrayresults to set.
  173. */
  174. public void setSeparatearrayresults(boolean separateArrayResults) {
  175. this.separatearrayresults = separateArrayResults;
  176. }
  177. /**
  178. * The login password for the <code>Manager</code> application.
  179. */
  180. public String getPassword() {
  181. return (this.password);
  182. }
  183. public void setPassword(String password) {
  184. this.password = password;
  185. }
  186. /**
  187. * The login username for the <code>JMX</code> MBeanServer.
  188. */
  189. public String getUsername() {
  190. return (this.username);
  191. }
  192. public void setUsername(String username) {
  193. this.username = username;
  194. }
  195. /**
  196. * The URL of the <code>JMX JSR 160</code> MBeanServer to be used.
  197. */
  198. public String getUrl() {
  199. return (this.url);
  200. }
  201. public void setUrl(String url) {
  202. this.url = url;
  203. }
  204. /**
  205. * The Host of the <code>JMX JSR 160</code> MBeanServer to be used.
  206. */
  207. public String getHost() {
  208. return (this.host);
  209. }
  210. public void setHost(String host) {
  211. this.host = host;
  212. }
  213. /**
  214. * The Port of the <code>JMX JSR 160</code> MBeanServer to be used.
  215. */
  216. public String getPort() {
  217. return (this.port);
  218. }
  219. public void setPort(String port) {
  220. this.port = port;
  221. }
  222. /**
  223. * @return Returns the useRef.
  224. */
  225. public boolean isUseRef() {
  226. return ref != null && !"".equals(ref);
  227. }
  228. /**
  229. * @return Returns the ref.
  230. */
  231. public String getRef() {
  232. return ref;
  233. }
  234. /**
  235. * @param refId The ref to set.
  236. */
  237. public void setRef(String refId) {
  238. this.ref = refId;
  239. }
  240. /**
  241. * @return Returns the ifCondition.
  242. */
  243. public String getIf() {
  244. return ifCondition;
  245. }
  246. /**
  247. * Only execute if a property of the given name exists in the current
  248. * project.
  249. *
  250. * @param c property name
  251. */
  252. public void setIf(String c) {
  253. ifCondition = c;
  254. }
  255. /**
  256. * @return Returns the unlessCondition.
  257. */
  258. public String getUnless() {
  259. return unlessCondition;
  260. }
  261. /**
  262. * Only execute if a property of the given name does not exist in the
  263. * current project.
  264. *
  265. * @param c property name
  266. */
  267. public void setUnless(String c) {
  268. unlessCondition = c;
  269. }
  270. // --------------------------------------------------------- Public Methods
  271. /**
  272. * Execute the specified command. This logic only performs the common
  273. * attribute validation required by all subclasses; it does not perform any
  274. * functional logic directly.
  275. *
  276. * @exception BuildException
  277. * if a validation error occurs
  278. */
  279. @Override
  280. public void execute() throws BuildException {
  281. if (testIfCondition() && testUnlessCondition()) {
  282. try {
  283. String error = null;
  284. MBeanServerConnection jmxServerConnection = getJMXConnection();
  285. error = jmxExecute(jmxServerConnection);
  286. if (error != null && isFailOnError()) {
  287. // exception should be thrown only if failOnError == true
  288. // or error line will be logged twice
  289. throw new BuildException(error);
  290. }
  291. } catch (Throwable t) {
  292. if (isFailOnError()) {
  293. throw new BuildException(t);
  294. } else {
  295. handleErrorOutput(t.getMessage());
  296. }
  297. } finally {
  298. closeRedirector();
  299. }
  300. }
  301. }
  302. /**
  303. * create a new JMX Connection with auth when username and password is set.
  304. */
  305. public static MBeanServerConnection createJMXConnection(String url,
  306. String host, String port, String username, String password)
  307. throws MalformedURLException, IOException {
  308. String urlForJMX;
  309. if (url != null)
  310. urlForJMX = url;
  311. else
  312. urlForJMX = JMX_SERVICE_PREFIX + host + ":" + port
  313. + JMX_SERVICE_SUFFIX;
  314. Map<String, String[]> environment = null;
  315. if (username != null && password != null) {
  316. String[] credentials = new String[2];
  317. credentials[0] = username;
  318. credentials[1] = password;
  319. environment = new HashMap<String, String[]>();
  320. environment.put(JMXConnector.CREDENTIALS, credentials);
  321. }
  322. return JMXConnectorFactory.connect(new JMXServiceURL(urlForJMX),
  323. environment).getMBeanServerConnection();
  324. }
  325. /**
  326. * test the if condition
  327. *
  328. * @return true if there is no if condition, or the named property exists
  329. */
  330. protected boolean testIfCondition() {
  331. if (ifCondition == null || "".equals(ifCondition)) {
  332. return true;
  333. }
  334. return getProperty(ifCondition) != null;
  335. }
  336. /**
  337. * test the unless condition
  338. *
  339. * @return true if there is no unless condition, or there is a named
  340. * property but it doesn't exist
  341. */
  342. protected boolean testUnlessCondition() {
  343. if (unlessCondition == null || "".equals(unlessCondition)) {
  344. return true;
  345. }
  346. return getProperty(unlessCondition) == null;
  347. }
  348. /**
  349. * Get Current Connection from <em>ref</em> parameter or create a new one!
  350. *
  351. * @return The server connection
  352. * @throws MalformedURLException
  353. * @throws IOException
  354. */
  355. public static MBeanServerConnection accessJMXConnection(Project project,
  356. String url, String host, String port, String username,
  357. String password, String refId) throws MalformedURLException,
  358. IOException {
  359. MBeanServerConnection jmxServerConnection = null;
  360. boolean isRef = project != null && refId != null && refId.length() > 0;
  361. if (isRef) {
  362. Object pref = project.getReference(refId);
  363. try {
  364. jmxServerConnection = (MBeanServerConnection) pref;
  365. } catch (ClassCastException cce) {
  366. project.log("wrong object reference " + refId + " - "
  367. + pref.getClass());
  368. return null;
  369. }
  370. }
  371. if (jmxServerConnection == null) {
  372. jmxServerConnection = createJMXConnection(url, host, port,
  373. username, password);
  374. }
  375. if (isRef && jmxServerConnection != null) {
  376. project.addReference(refId, jmxServerConnection);
  377. }
  378. return jmxServerConnection;
  379. }
  380. // ------------------------------------------------------ protected Methods
  381. /**
  382. * get JMXConnection
  383. *
  384. * @return The connection
  385. * @throws MalformedURLException
  386. * @throws IOException
  387. */
  388. protected MBeanServerConnection getJMXConnection()
  389. throws MalformedURLException, IOException {
  390. MBeanServerConnection jmxServerConnection = null;
  391. if (isUseRef()) {
  392. Object pref = null ;
  393. if(getProject() != null) {
  394. pref = getProject().getReference(getRef());
  395. if (pref != null) {
  396. try {
  397. jmxServerConnection = (MBeanServerConnection) pref;
  398. } catch (ClassCastException cce) {
  399. getProject().log(
  400. "Wrong object reference " + getRef() + " - "
  401. + pref.getClass());
  402. return null;
  403. }
  404. }
  405. }
  406. if (jmxServerConnection == null) {
  407. jmxServerConnection = accessJMXConnection(getProject(),
  408. getUrl(), getHost(), getPort(), getUsername(),
  409. getPassword(), getRef());
  410. }
  411. } else {
  412. jmxServerConnection = accessJMXConnection(getProject(), getUrl(),
  413. getHost(), getPort(), getUsername(), getPassword(), null);
  414. }
  415. return jmxServerConnection;
  416. }
  417. /**
  418. * Execute the specified command, based on the configured properties. The
  419. * input stream will be closed upon completion of this task, whether it was
  420. * executed successfully or not.
  421. *
  422. * @exception Exception
  423. * if an error occurs
  424. */
  425. public String jmxExecute(MBeanServerConnection jmxServerConnection)
  426. throws Exception {
  427. if ((jmxServerConnection == null)) {
  428. throw new BuildException("Must open a connection!");
  429. } else if (isEcho()) {
  430. handleOutput("JMX Connection ref=" + ref + " is open!");
  431. }
  432. return null;
  433. }
  434. /**
  435. * Convert string to datatype FIXME How we can transfer values from ant
  436. * project reference store (ref)?
  437. *
  438. * @param value The value
  439. * @param valueType The type
  440. * @return The converted object
  441. */
  442. protected Object convertStringToType(String value, String valueType) {
  443. if ("java.lang.String".equals(valueType))
  444. return value;
  445. Object convertValue = value;
  446. if ("java.lang.Integer".equals(valueType) || "int".equals(valueType)) {
  447. try {
  448. convertValue = new Integer(value);
  449. } catch (NumberFormatException ex) {
  450. if (isEcho())
  451. handleErrorOutput("Unable to convert to integer:" + value);
  452. }
  453. } else if ("java.lang.Long".equals(valueType)
  454. || "long".equals(valueType)) {
  455. try {
  456. convertValue = new Long(value);
  457. } catch (NumberFormatException ex) {
  458. if (isEcho())
  459. handleErrorOutput("Unable to convert to long:" + value);
  460. }
  461. } else if ("java.lang.Boolean".equals(valueType)
  462. || "boolean".equals(valueType)) {
  463. convertValue = new Boolean(value);
  464. } else if ("java.lang.Float".equals(valueType)
  465. || "float".equals(valueType)) {
  466. try {
  467. convertValue = new Float(value);
  468. } catch (NumberFormatException ex) {
  469. if (isEcho())
  470. handleErrorOutput("Unable to convert to float:" + value);
  471. }
  472. } else if ("java.lang.Double".equals(valueType)
  473. || "double".equals(valueType)) {
  474. try {
  475. convertValue = new Double(value);
  476. } catch (NumberFormatException ex) {
  477. if (isEcho())
  478. handleErrorOutput("Unable to convert to double:" + value);
  479. }
  480. } else if ("javax.management.ObjectName".equals(valueType)
  481. || "name".equals(valueType)) {
  482. try {
  483. convertValue = new ObjectName(value);
  484. } catch (MalformedObjectNameException e) {
  485. if (isEcho())
  486. handleErrorOutput("Unable to convert to ObjectName:"
  487. + value);
  488. }
  489. } else if ("java.net.InetAddress".equals(valueType)) {
  490. try {
  491. convertValue = InetAddress.getByName(value);
  492. } catch (UnknownHostException exc) {
  493. if (isEcho())
  494. handleErrorOutput("Unable to resolve host name:" + value);
  495. }
  496. }
  497. return convertValue;
  498. }
  499. /**
  500. * @param name context of result
  501. * @param result
  502. */
  503. protected void echoResult(String name, Object result) {
  504. if (isEcho()) {
  505. if (result.getClass().isArray()) {
  506. for (int i = 0; i < Array.getLength(result); i++) {
  507. handleOutput(name + "." + i + "=" + Array.get(result, i));
  508. }
  509. } else
  510. handleOutput(name + "=" + result);
  511. }
  512. }
  513. /**
  514. * create result as property with name from attribute resultproperty
  515. *
  516. * @param result The result
  517. * @see #createProperty(String, Object)
  518. */
  519. protected void createProperty(Object result) {
  520. if (resultproperty != null) {
  521. createProperty(resultproperty, result);
  522. }
  523. }
  524. /**
  525. * create result as property with name from property prefix When result is
  526. * an array and isSeparateArrayResults is true, resultproperty used as
  527. * prefix (<code>resultproperty.0-array.length</code> and store the
  528. * result array length at <code>resultproperty.length</code>. Other
  529. * option is that you delimit your result with a delimiter
  530. * (java.util.StringTokenizer is used).
  531. *
  532. * @param propertyPrefix
  533. * @param result
  534. */
  535. protected void createProperty(String propertyPrefix, Object result) {
  536. if (propertyPrefix == null)
  537. propertyPrefix = "";
  538. if (result instanceof CompositeDataSupport) {
  539. CompositeDataSupport data = (CompositeDataSupport) result;
  540. CompositeType compositeType = data.getCompositeType();
  541. Set<String> keys = compositeType.keySet();
  542. for (Iterator<String> iter = keys.iterator(); iter.hasNext();) {
  543. String key = iter.next();
  544. Object value = data.get(key);
  545. OpenType<?> type = compositeType.getType(key);
  546. if (type instanceof SimpleType<?>) {
  547. setProperty(propertyPrefix + "." + key, value);
  548. } else {
  549. createProperty(propertyPrefix + "." + key, value);
  550. }
  551. }
  552. } else if (result instanceof TabularDataSupport) {
  553. TabularDataSupport data = (TabularDataSupport) result;
  554. for (Iterator<Object> iter = data.keySet().iterator(); iter.hasNext();) {
  555. Object key = iter.next();
  556. for (Iterator<?> iter1 = ((List<?>) key).iterator(); iter1.hasNext();) {
  557. Object key1 = iter1.next();
  558. CompositeData valuedata = data.get(new Object[] { key1 });
  559. Object value = valuedata.get("value");
  560. OpenType<?> type = valuedata.getCompositeType().getType(
  561. "value");
  562. if (type instanceof SimpleType<?>) {
  563. setProperty(propertyPrefix + "." + key1, value);
  564. } else {
  565. createProperty(propertyPrefix + "." + key1, value);
  566. }
  567. }
  568. }
  569. } else if (result.getClass().isArray()) {
  570. if (isSeparatearrayresults()) {
  571. int size = 0;
  572. for (int i = 0; i < Array.getLength(result); i++) {
  573. if (setProperty(propertyPrefix + "." + size, Array.get(
  574. result, i))) {
  575. size++;
  576. }
  577. }
  578. if (size > 0) {
  579. setProperty(propertyPrefix + ".Length", Integer
  580. .toString(size));
  581. }
  582. }
  583. } else {
  584. String delim = getDelimiter();
  585. if (delim != null) {
  586. StringTokenizer tokenizer = new StringTokenizer(result
  587. .toString(), delim);
  588. int size = 0;
  589. for (; tokenizer.hasMoreTokens();) {
  590. String token = tokenizer.nextToken();
  591. if (setProperty(propertyPrefix + "." + size, token)) {
  592. size++;
  593. }
  594. }
  595. if (size > 0)
  596. setProperty(propertyPrefix + ".Length", Integer
  597. .toString(size));
  598. } else {
  599. setProperty(propertyPrefix, result.toString());
  600. }
  601. }
  602. }
  603. /**
  604. * get all properties, when project is there got all project Properties
  605. * @return properties
  606. */
  607. public Map getProperties() {
  608. Project currentProject = getProject();
  609. if (currentProject != null) {
  610. return currentProject.getProperties();
  611. } else {
  612. return properties;
  613. }
  614. }
  615. /**
  616. * get all Properties
  617. * @param property
  618. * @return The property
  619. */
  620. public String getProperty(String property) {
  621. Project currentProject = getProject();
  622. if (currentProject != null) {
  623. return currentProject.getProperty(property);
  624. } else {
  625. return properties.getProperty(property);
  626. }
  627. }
  628. /**
  629. * @param property The property
  630. * @param value The value
  631. * @return True if successful
  632. */
  633. public boolean setProperty(String property, Object value) {
  634. if (property != null) {
  635. if (value == null)
  636. value = "";
  637. if (isEcho()) {
  638. handleOutput(property + "=" + value.toString());
  639. }
  640. Project currentProject = getProject();
  641. if (currentProject != null) {
  642. currentProject.setNewProperty(property, value.toString());
  643. } else {
  644. properties.setProperty(property, value.toString());
  645. }
  646. return true;
  647. }
  648. return false;
  649. }
  650. }