PageRenderTime 85ms CodeModel.GetById 31ms RepoModel.GetById 0ms app.codeStats 0ms

/modules/plugins/tomcat/src/main/java/org/jboss/on/plugins/tomcat/TomcatConnectorComponent.java

https://github.com/ccrouch/rhq
Java | 253 lines | 151 code | 41 blank | 61 comment | 22 complexity | e49cb072a662ce2e98bf51f460b53098 MD5 | raw file
  1. /*
  2. * Jopr Management Platform
  3. * Copyright (C) 2005-2008 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.jboss.on.plugins.tomcat;
  24. import java.net.InetAddress;
  25. import java.net.UnknownHostException;
  26. import java.util.List;
  27. import java.util.Set;
  28. import org.apache.commons.logging.Log;
  29. import org.apache.commons.logging.LogFactory;
  30. import org.mc4j.ems.connection.EmsConnection;
  31. import org.mc4j.ems.connection.bean.EmsBean;
  32. import org.mc4j.ems.connection.bean.attribute.EmsAttribute;
  33. import org.rhq.core.domain.configuration.Configuration;
  34. import org.rhq.core.domain.configuration.ConfigurationUpdateStatus;
  35. import org.rhq.core.domain.configuration.definition.ConfigurationDefinition;
  36. import org.rhq.core.domain.configuration.definition.PropertyDefinition;
  37. import org.rhq.core.domain.measurement.AvailabilityType;
  38. import org.rhq.core.domain.measurement.MeasurementDataNumeric;
  39. import org.rhq.core.domain.measurement.MeasurementReport;
  40. import org.rhq.core.domain.measurement.MeasurementScheduleRequest;
  41. import org.rhq.core.pluginapi.configuration.ConfigurationUpdateReport;
  42. import org.rhq.core.pluginapi.inventory.InvalidPluginConfigurationException;
  43. import org.rhq.core.pluginapi.inventory.ResourceContext;
  44. import org.rhq.plugins.jmx.MBeanResourceComponent;
  45. import org.rhq.plugins.jmx.ObjectNameQueryUtility;
  46. /**
  47. * Plugin component for representing Tomcat connectors. Much of the functionality is left to the super class,
  48. * however the metrics required special handling.
  49. *
  50. * @author Jay Shaughnessy
  51. * @author Jason Dobies
  52. */
  53. public class TomcatConnectorComponent extends MBeanResourceComponent<TomcatServerComponent<?>> {
  54. /**
  55. * property name for the protocol of the connector
  56. */
  57. public static final String CONFIG_PROTOCOL = "protocol";
  58. /**
  59. * V5 only property
  60. */
  61. public static final String CONFIG_V5_KEEP_ALIVE_TIMEOUT = "keepAliveTimeout";
  62. /**
  63. * Plugin property name for the address the connector is bound to.
  64. */
  65. public static final String PLUGIN_CONFIG_ADDRESS = "address";
  66. /**
  67. * Plugin property name for the protocol handler. This prefix is used in the associated GlobalRequestProcessor object name.
  68. */
  69. public static final String PLUGIN_CONFIG_HANDLER = "handler";
  70. /**
  71. * Plugin property name for the port the connector is listening on.
  72. */
  73. public static final String PLUGIN_CONFIG_PORT = "port";
  74. public static final String UNKNOWN = "?";
  75. private final Log log = LogFactory.getLog(this.getClass());
  76. @Override
  77. public AvailabilityType getAvailability() {
  78. // First, ensure the underlying mbean for the connector is active
  79. AvailabilityType result = super.getAvailability();
  80. if (AvailabilityType.UP == result) {
  81. // When the connector is stopped its associated GlobalRequestProcessor will not exist. We test
  82. // for availability by checking the existence of objectName Catalina:type=GlobalRequestProcessor,name=%handler%[%address%]-%port%.
  83. String objectName = getGlobalRequestProcessorName();
  84. EmsConnection connection = getEmsConnection();
  85. ObjectNameQueryUtility queryUtility = new ObjectNameQueryUtility(objectName);
  86. List<EmsBean> beans = connection.queryBeans(queryUtility.getTranslatedQuery());
  87. result = (beans.isEmpty()) ? AvailabilityType.DOWN : AvailabilityType.UP;
  88. }
  89. return result;
  90. }
  91. @Override
  92. public void start(ResourceContext<TomcatServerComponent<?>> context) {
  93. if (UNKNOWN.equals(context.getPluginConfiguration().getSimple(PLUGIN_CONFIG_HANDLER).getStringValue())) {
  94. throw new InvalidPluginConfigurationException(
  95. "The connector is not listening for requests on the configured port. This is most likely due to the configured port being in use at Tomcat startup. In some cases (AJP connectors) Tomcat will assign an open port. This happens most often when there are multiple Tomcat servers running on the same platform. Check your Tomcat configuration for conflicts: "
  96. + context.getResourceKey());
  97. }
  98. super.start(context);
  99. }
  100. @Override
  101. public void getValues(MeasurementReport report, Set<MeasurementScheduleRequest> requests) {
  102. getEmsConnection(); // reload the EMS connection
  103. for (MeasurementScheduleRequest request : requests) {
  104. String name = request.getName();
  105. name = getAttributeName(name);
  106. String beanName = name.substring(0, name.lastIndexOf(':'));
  107. String attributeName = name.substring(name.lastIndexOf(':') + 1);
  108. try {
  109. // Bean is cached by EMS, so no problem with getting the bean from the connection on each call
  110. EmsBean eBean = loadBean(beanName);
  111. if (eBean == null) {
  112. log.warn("Bean " + beanName + " not found, skipping ...");
  113. continue;
  114. }
  115. EmsAttribute attribute = eBean.getAttribute(attributeName);
  116. Object valueObject = attribute.refresh();
  117. Number value = (Number) valueObject;
  118. report.addData(new MeasurementDataNumeric(request, value.doubleValue()));
  119. } catch (Exception e) {
  120. log.error("Failed to obtain measurement [" + name + "]", e);
  121. }
  122. }
  123. }
  124. /**
  125. * Get the real name of the passed property for a concrete connector. The actual object name will begin with:
  126. * Catalina:type=GlobalRequestProcessor,name=handler[-address]-port. We need to
  127. * substitute in the address and port of this particular connector before the value can be read. In the plugin
  128. * descriptor, these are written as %handler%, %address% and %port% respectively, so we can replace on those.
  129. */
  130. @Override
  131. protected String getAttributeName(String property) {
  132. String theProperty = replaceGlobalRequestProcessorNameProps(property);
  133. if (log.isDebugEnabled()) {
  134. log.debug("Finding metrics for: " + theProperty);
  135. }
  136. return theProperty;
  137. }
  138. private String getGlobalRequestProcessorName() {
  139. String name = "Catalina:type=GlobalRequestProcessor,name=%handler%%address%-%port%";
  140. return replaceGlobalRequestProcessorNameProps(name);
  141. }
  142. private String replaceGlobalRequestProcessorNameProps(String name) {
  143. String result = name;
  144. Configuration pluginConfiguration = getResourceContext().getPluginConfiguration();
  145. String port = pluginConfiguration.getSimple(PLUGIN_CONFIG_PORT).getStringValue();
  146. String handler = pluginConfiguration.getSimple(PLUGIN_CONFIG_HANDLER).getStringValue();
  147. String address = pluginConfiguration.getSimpleValue(PLUGIN_CONFIG_ADDRESS, "");
  148. if (!"".equals(address)) {
  149. StringBuilder sb = new StringBuilder("-");
  150. sb.append(address);
  151. // if it's a host name, add the IP portion that Tomcat expects
  152. if (!address.contains(".")) {
  153. String ip;
  154. try {
  155. ip = InetAddress.getByName(address).getHostAddress();
  156. sb.append("%2F");
  157. sb.append(ip);
  158. address = sb.toString();
  159. } catch (UnknownHostException e) {
  160. log.debug("Failed to resolve host [" + address + "]. Can not get objectName for property: " + name);
  161. }
  162. } else {
  163. address = sb.toString();
  164. }
  165. }
  166. result = result.replace("%port%", port);
  167. result = result.replace("%address%", address);
  168. result = result.replace("%handler%", handler);
  169. return result;
  170. }
  171. @Override
  172. public void updateResourceConfiguration(ConfigurationUpdateReport report) {
  173. // When starting the component get the connector type specific property keys
  174. ResourceContext<TomcatServerComponent<?>> context = getResourceContext();
  175. ConfigurationDefinition configDef = context.getResourceType().getResourceConfigurationDefinition();
  176. String protocol = report.getConfiguration().getSimpleValue(CONFIG_PROTOCOL, null);
  177. if ((null == protocol) || protocol.toUpperCase().contains("HTTP")) {
  178. // remove AJP only properties
  179. for (PropertyDefinition propDef : configDef.getPropertiesInGroup("AJP")) {
  180. report.getConfiguration().remove(propDef.getName());
  181. }
  182. }
  183. if ((null == protocol) || protocol.toUpperCase().contains("AJP")) {
  184. // remove HTTP only properties
  185. for (PropertyDefinition propDef : configDef.getPropertiesInGroup("HTTP")) {
  186. report.getConfiguration().remove(propDef.getName());
  187. }
  188. for (PropertyDefinition propDef : configDef.getPropertiesInGroup("HTTP SSL")) {
  189. report.getConfiguration().remove(propDef.getName());
  190. }
  191. }
  192. if (getResourceContext().getParentResourceComponent().getResourceContext().getVersion().startsWith("5")) {
  193. report.getConfiguration().remove(CONFIG_V5_KEEP_ALIVE_TIMEOUT);
  194. }
  195. super.updateResourceConfiguration(report);
  196. // if the mbean update failed, return now
  197. if (ConfigurationUpdateStatus.SUCCESS != report.getStatus()) {
  198. return;
  199. }
  200. // If all went well, persist the changes to the Tomcat server.xml
  201. try {
  202. storeConfig();
  203. } catch (Exception e) {
  204. report
  205. .setErrorMessage("Failed to persist configuration change. Changes will not survive Tomcat restart unless a successful Store Configuration operation is performed.");
  206. }
  207. }
  208. /** Persist local changes to the server.xml */
  209. void storeConfig() throws Exception {
  210. this.getResourceContext().getParentResourceComponent().storeConfig();
  211. }
  212. }