/* * Licensed to the Apache Software Foundation (ASF) under one or more contributor license * agreements. See the NOTICE file distributed with this work for additional information regarding * copyright ownership. The ASF licenses this file to You under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance with the License. You may obtain a * copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express * or implied. See the License for the specific language governing permissions and limitations under * the License. */ package org.apache.geode.test.dunit.rules; import static org.assertj.core.api.Assertions.assertThat; import com.jayway.awaitility.Awaitility; import org.apache.geode.management.cli.Result; import org.apache.geode.management.internal.cli.CliUtil; import org.apache.geode.management.internal.cli.HeadlessGfsh; import org.apache.geode.management.internal.cli.i18n.CliStrings; import org.apache.geode.management.internal.cli.result.CommandResult; import org.apache.geode.management.internal.cli.util.CommandStringBuilder; import org.apache.geode.test.junit.rules.DescribedExternalResource; import org.junit.runner.Description; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicReference; /** * Class which eases the connection to the jmxManager {@link ConnectionConfiguration} it allows for * the creation of per-test connections with different user/password combinations, or no username * and password */ public class GfshShellConnectionRule extends DescribedExternalResource { private int port = 0; private PortType portType = null; private HeadlessGfsh gfsh; private boolean connected; public GfshShellConnectionRule(Locator locator) { this(locator.getPort(), PortType.locator); } public GfshShellConnectionRule(int port, PortType portType) { this.portType = portType; this.port = port; try { this.gfsh = new HeadlessGfsh(getClass().getName(), 30, "gfsh_files"); } catch (Exception e) { e.printStackTrace(); } this.connected = false; } protected void before(Description description) throws Throwable { ConnectionConfiguration config = description.getAnnotation(ConnectionConfiguration.class); if (config != null) { connect(CliStrings.CONNECT__USERNAME, config.user(), CliStrings.CONNECT__PASSWORD, config.password()); } else { connect(); } } public void connect(String... options) throws Exception { CliUtil.isGfshVM = true; final CommandStringBuilder connectCommand = new CommandStringBuilder(CliStrings.CONNECT); String endpoint; if (portType == PortType.locator) { // port is the locator port endpoint = "localhost[" + port + "]"; connectCommand.addOption(CliStrings.CONNECT__LOCATOR, endpoint); } else if (portType == PortType.http) { endpoint = "http://localhost:" + port + "/gemfire/v1"; connectCommand.addOption(CliStrings.CONNECT__USE_HTTP, Boolean.TRUE.toString()); connectCommand.addOption(CliStrings.CONNECT__URL, endpoint); } else { endpoint = "localhost[" + port + "]"; connectCommand.addOption(CliStrings.CONNECT__JMX_MANAGER, endpoint); } // add the extra options if (options != null) { for (int i = 0; i < options.length; i += 2) { connectCommand.addOption(options[i], options[i + 1]); } } // when we connect too soon, we would get "Failed to retrieve RMIServer stub: // javax.naming.CommunicationException [Root exception is java.rmi.NoSuchObjectException: no // such object in table]" Exception. // Tried to wait on jmx connector server being ready, but it doesn't work. AtomicReference<CommandResult> result = new AtomicReference<>(); Awaitility.await().atMost(2, TimeUnit.MINUTES).pollDelay(2, TimeUnit.SECONDS).until(() -> { gfsh.executeCommand(connectCommand.toString()); result.set((CommandResult) gfsh.getResult()); System.out.println("connect result: " + result.get().getContent().toString()); return !gfsh.outputString.contains("no such object in table"); }); connected = (result.get().getStatus() == Result.Status.OK); } /** * Override to tear down your specific external resource. */ protected void after(Description description) throws Throwable { close(); } public void close() throws Exception { if (gfsh != null) { gfsh.clear(); gfsh.executeCommand("disconnect"); gfsh.executeCommand("exit"); gfsh.terminate(); gfsh = null; } CliUtil.isGfshVM = false; } public HeadlessGfsh getGfsh() { return gfsh; } public CommandResult executeCommand(String command) throws Exception { gfsh.executeCommand(command); CommandResult result = (CommandResult) gfsh.getResult(); System.out.println("command result: " + result.getContent().toString()); return result; } public CommandResult executeAndVerifyCommand(String command) throws Exception { CommandResult result = executeCommand(command); assertThat(result.getStatus()).describedAs(result.getContent().toString()) .isEqualTo(Result.Status.OK); return result; } public boolean isConnected() { return connected; } public enum PortType { locator, jmxManger, http } }