PageRenderTime 886ms CodeModel.GetById 35ms RepoModel.GetById 13ms app.codeStats 0ms

/arquillian/container-managed-clustering/src/main/java/org/jboss/as/arquillian/container/managed/clustering/ManagedDeployableContainer.java

https://github.com/elegar/jboss-as
Java | 266 lines | 199 code | 28 blank | 39 comment | 28 complexity | 2fcec86cf1676143b95a1d61009b661f MD5 | raw file
  1. /*
  2. * JBoss, Home of Professional Open Source
  3. * Copyright 2009, Red Hat Middleware LLC, and individual contributors
  4. * by the @authors tag. See the copyright.txt in the distribution for a
  5. * full listing of individual contributors.
  6. *
  7. * Licensed under the Apache License, Version 2.0 (the "License");
  8. * you may not use this file except in compliance with the License.
  9. * You may obtain a copy of the License at
  10. * http://www.apache.org/licenses/LICENSE-2.0
  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.jboss.as.arquillian.container.managed.clustering;
  18. import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.NAME;
  19. import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.OUTCOME;
  20. import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.READ_ATTRIBUTE_OPERATION;
  21. import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.RESULT;
  22. import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.SUCCESS;
  23. import java.io.File;
  24. import java.io.IOException;
  25. import java.io.InputStream;
  26. import java.io.InputStreamReader;
  27. import java.net.InetAddress;
  28. import java.net.URI;
  29. import java.net.UnknownHostException;
  30. import java.security.AccessController;
  31. import java.security.PrivilegedAction;
  32. import java.util.ArrayList;
  33. import java.util.List;
  34. import java.util.concurrent.TimeoutException;
  35. import java.util.logging.Logger;
  36. import javax.management.MBeanServerConnection;
  37. import org.jboss.arquillian.container.spi.client.container.LifecycleException;
  38. import org.jboss.arquillian.container.spi.context.annotation.ContainerScoped;
  39. import org.jboss.arquillian.core.api.InstanceProducer;
  40. import org.jboss.arquillian.core.api.annotation.Inject;
  41. import org.jboss.as.arquillian.container.CommonDeployableContainer;
  42. import org.jboss.as.arquillian.container.MBeanServerConnectionProvider;
  43. import org.jboss.as.controller.ControlledProcessState;
  44. import org.jboss.as.controller.PathAddress;
  45. import org.jboss.as.controller.operations.common.Util;
  46. import org.jboss.dmr.ModelNode;
  47. /**
  48. * JBossAsManagedContainer
  49. *
  50. * @author Thomas.Diesler@jboss.com
  51. * @since 17-Nov-2010
  52. */
  53. public final class ManagedDeployableContainer extends CommonDeployableContainer<ManagedContainerConfiguration> {
  54. private final Logger log = Logger.getLogger(ManagedDeployableContainer.class.getName());
  55. private MBeanServerConnectionProvider provider;
  56. private Thread shutdownThread;
  57. private Process process;
  58. @Inject
  59. @ContainerScoped
  60. private InstanceProducer<MBeanServerConnection> mbeanServerInst;
  61. private int destroyProcess() {
  62. if (process == null)
  63. return 0;
  64. process.destroy();
  65. try {
  66. return process.waitFor();
  67. } catch (InterruptedException e) {
  68. throw new RuntimeException(e);
  69. }
  70. }
  71. @Override
  72. public Class<ManagedContainerConfiguration> getConfigurationClass() {
  73. return ManagedContainerConfiguration.class;
  74. }
  75. @Override
  76. public void setup(ManagedContainerConfiguration config) {
  77. super.setup(config);
  78. }
  79. @Override
  80. protected void startInternal() throws LifecycleException {
  81. try {
  82. ManagedContainerConfiguration config = getContainerConfiguration();
  83. final String jbossHomeDir = config.getJbossHome();
  84. final String additionalJavaOpts = System.getProperty("jboss.options");
  85. final String modulePath;
  86. if(config.getModulePath() != null && !config.getModulePath().isEmpty()) {
  87. modulePath = config.getModulePath();
  88. } else {
  89. modulePath = jbossHomeDir + "/modules";
  90. }
  91. File modulesJar = new File(jbossHomeDir + "/jboss-modules.jar");
  92. if (modulesJar.exists() == false)
  93. throw new IllegalStateException("Cannot find: " + modulesJar);
  94. List<String> cmd = new ArrayList<String>();
  95. cmd.add("java");
  96. if (additionalJavaOpts != null) {
  97. for (String opt : additionalJavaOpts.split("\\s+")) {
  98. cmd.add(opt);
  99. }
  100. }
  101. // Can't figure out why -server-config won't work, so for now just
  102. // copy clustering-standalone.xml contents to standalone.xml
  103. // File srcFile = new File(jbossHomeDir + "/standalone/configuration/clustering-standalone.xml");
  104. // File destFile = new File(jbossHomeDir + "/standalone/configuration/standalone.xml");
  105. // FileChannel srcChannel = new java.io.FileInputStream(srcFile).getChannel();
  106. // FileChannel destChannel = new java.io.FileOutputStream(destFile).getChannel();
  107. // srcChannel.transferTo(0, srcFile.length(), destChannel);
  108. // srcChannel.close();
  109. // destChannel.close();
  110. cmd.add("-Djboss.home.dir=" + jbossHomeDir);
  111. cmd.add("-Dorg.jboss.boot.log.file=" + jbossHomeDir + "/standalone/log/boot.log");
  112. cmd.add("-Dlogging.configuration=file:" + jbossHomeDir + "/standalone/configuration/logging.properties");
  113. cmd.add("-Djboss.modules.dir=" + modulePath);
  114. cmd.add("-jar");
  115. cmd.add(modulesJar.getAbsolutePath());
  116. cmd.add("-mp");
  117. cmd.add(modulePath);
  118. cmd.add("-logmodule");
  119. cmd.add("org.jboss.logmanager");
  120. cmd.add("-jaxpmodule");
  121. cmd.add("javax.xml.jaxp-provider");
  122. // cmd.add("-server-config");
  123. // cmd.add(jbossHomeDir + "/standalone/configuration/clustering-standalone.xml");
  124. cmd.add("org.jboss.as.standalone");
  125. cmd.add("-server-config");
  126. cmd.add(config.getServerConfig());
  127. cmd.add("-Djava.net.preferIPv4Stack=true");
  128. log.info("Starting container with: " + cmd.toString());
  129. ProcessBuilder processBuilder = new ProcessBuilder(cmd);
  130. processBuilder.redirectErrorStream(true);
  131. process = processBuilder.start();
  132. new Thread(new ConsoleConsumer()).start();
  133. final Process proc = process;
  134. shutdownThread = new Thread(new Runnable() {
  135. @Override
  136. public void run() {
  137. if (proc != null) {
  138. proc.destroy();
  139. try {
  140. proc.waitFor();
  141. } catch (InterruptedException e) {
  142. throw new RuntimeException(e);
  143. }
  144. }
  145. }
  146. });
  147. Runtime.getRuntime().addShutdownHook(shutdownThread);
  148. long startupTimeout = getContainerConfiguration().getStartupTimeoutInSeconds();
  149. long timeout = startupTimeout * 1000;
  150. boolean serverAvailable = false;
  151. while (timeout > 0 && serverAvailable == false) {
  152. serverAvailable = isServerStarted();
  153. if (!serverAvailable) {
  154. Thread.sleep(100);
  155. timeout -= 100;
  156. }
  157. }
  158. if (!serverAvailable) {
  159. destroyProcess();
  160. throw new TimeoutException(String.format("Managed server was not started within [%d] ms", getContainerConfiguration().getStartupTimeout()));
  161. }
  162. provider = getMBeanServerConnectionProvider();
  163. mbeanServerInst.set(getMBeanServerConnection(5000));
  164. } catch (Exception e) {
  165. throw new LifecycleException("Could not start container", e);
  166. }
  167. }
  168. @Override
  169. protected void stopInternal() throws LifecycleException {
  170. if(shutdownThread != null) {
  171. Runtime.getRuntime().removeShutdownHook(shutdownThread);
  172. shutdownThread = null;
  173. }
  174. try {
  175. if (process != null) {
  176. process.destroy();
  177. process.waitFor();
  178. process = null;
  179. }
  180. } catch (Exception e) {
  181. throw new LifecycleException("Could not stop container", e);
  182. }
  183. }
  184. @Override
  185. protected MBeanServerConnection getMBeanServerConnection() {
  186. return provider.getConnection();
  187. }
  188. private boolean isServerStarted() {
  189. try {
  190. ModelNode op = Util.getEmptyOperation(READ_ATTRIBUTE_OPERATION, PathAddress.EMPTY_ADDRESS.toModelNode());
  191. op.get(NAME).set("server-state");
  192. ModelNode rsp = getModelControllerClient().execute(op);
  193. return SUCCESS.equals(rsp.get(OUTCOME).asString()) && !ControlledProcessState.State.STARTING.toString().equals(rsp.get(RESULT).asString());
  194. }
  195. catch (Exception ignored) {
  196. // ignore, as we will get exceptions until the management comm services start
  197. }
  198. return false;
  199. }
  200. private MBeanServerConnectionProvider getMBeanServerConnectionProvider() {
  201. URI jmxSubSystem = getManagementClient().getSubSystemURI("jmx");
  202. InetAddress address = null;
  203. try {
  204. address = InetAddress.getByName(jmxSubSystem.getHost());
  205. } catch (UnknownHostException e) {
  206. throw new RuntimeException("Could not get jmx subsystems InetAddress: " + jmxSubSystem.getHost(), e);
  207. }
  208. return new MBeanServerConnectionProvider(address, jmxSubSystem.getPort());
  209. }
  210. /**
  211. * Runnable that consumes the output of the process. If nothing consumes the output the AS will hang on some platforms
  212. * @author Stuart Douglas
  213. */
  214. private class ConsoleConsumer implements Runnable {
  215. @Override
  216. public void run() {
  217. final InputStream stream = process.getInputStream();
  218. final InputStreamReader reader = new InputStreamReader(stream);
  219. final boolean writeOutput = AccessController.doPrivileged(new PrivilegedAction<Boolean>() {
  220. @Override
  221. public Boolean run() {
  222. // this needs a better name
  223. String val = System.getProperty("org.jboss.as.writeconsole");
  224. return val != null && "true".equals(val);
  225. }
  226. });
  227. final char[] data = new char[100];
  228. try {
  229. for (int read = 0; read != -1; read = reader.read(data)) {
  230. if (writeOutput) {
  231. System.out.print(data);
  232. }
  233. }
  234. } catch (IOException e) {
  235. }
  236. }
  237. }
  238. }