/*
* 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.management.internal.cli.remote;
import org.apache.geode.internal.ClassPathLoader;
import org.apache.geode.management.ManagementService;
import org.apache.geode.management.cli.CliMetaData;
import org.apache.geode.management.cli.Result;
import org.apache.geode.management.cli.Result.Status;
import org.apache.geode.management.internal.cli.CliAroundInterceptor;
import org.apache.geode.management.internal.cli.GfshParseResult;
import org.apache.geode.management.internal.cli.LogWrapper;
import org.apache.geode.management.internal.cli.result.FileResult;
import org.apache.geode.management.internal.cli.result.ResultBuilder;
import org.springframework.shell.event.ParseResult;
import org.springframework.util.Assert;
import org.springframework.util.ReflectionUtils;
import java.lang.reflect.Method;
/**
*
*
* @since GemFire 7.0
*/
// Doesn't have to be org.springframework.roo.shell.ExecutionStrategy
public class RemoteExecutionStrategy {
private LogWrapper logWrapper = LogWrapper.getInstance();
public Object execute(ParseResult parseResult) throws RuntimeException {
Result result = null;
try {
Assert.notNull(parseResult, "Parse result required");
if (!GfshParseResult.class.isInstance(parseResult)) {
// Remote command means implemented for Gfsh and ParseResult should be GfshParseResult.
// TODO: should this message be more specific?
throw new IllegalArgumentException("Command Configuration/Definition error.");
}
GfshParseResult gfshParseResult = (GfshParseResult) parseResult;
Method method = gfshParseResult.getMethod();
if (!isShellOnly(method)) {
Boolean fromShell = CommandExecutionContext.isShellRequest();
boolean sentFromShell = fromShell != null && fromShell.booleanValue();
String interceptorClass = getInterceptor(gfshParseResult.getMethod());
CliAroundInterceptor interceptor = null;
// 1. Pre Execution
if (!sentFromShell && !CliMetaData.ANNOTATION_NULL_VALUE.equals(interceptorClass)) {
try {
interceptor = (CliAroundInterceptor) ClassPathLoader.getLatest()
.forName(interceptorClass).newInstance();
} catch (InstantiationException e) {
logWrapper.info(e.getMessage());
} catch (IllegalAccessException e) {
logWrapper.info(e.getMessage());
} catch (ClassNotFoundException e) {
logWrapper.info(e.getMessage());
}
if (interceptor != null) {
Result preExecResult = interceptor.preExecution(gfshParseResult);
if (Status.ERROR.equals(preExecResult.getStatus())) {
return preExecResult;
} else if (preExecResult instanceof FileResult) {
FileResult fileResult = (FileResult) preExecResult;
byte[][] fileData = fileResult.toBytes();
CommandExecutionContext.setBytesFromShell(fileData);
}
} else {
return ResultBuilder
.createBadConfigurationErrorResult("Interceptor Configuration Error");
}
}
logWrapper.info("Executing " + gfshParseResult.getUserInput());
result = (Result) ReflectionUtils.invokeMethod(gfshParseResult.getMethod(),
gfshParseResult.getInstance(), gfshParseResult.getArguments());
if (result != null && Status.ERROR.equals(result.getStatus())) {
logWrapper
.info("Error occurred while executing \"" + gfshParseResult.getUserInput() + "\".");
}
if (interceptor != null) {
Result postExecResult = interceptor.postExecution(gfshParseResult, result);
if (postExecResult != null) {
if (Status.ERROR.equals(postExecResult.getStatus())) {
logWrapper.warning(postExecResult.toString(), null);
} else if (logWrapper.fineEnabled()) {
logWrapper.fine(String.valueOf(postExecResult));
}
result = postExecResult;
}
CommandExecutionContext.setBytesFromShell(null); // for remote commands with bytes
}
} else {
throw new IllegalArgumentException(
"Only Remote command can be executed through " + ManagementService.class.getSimpleName()
+ ".processCommand() or ManagementMBean's processCommand "
+ "operation. Please refer documentation for the list of " + "commands.");
}
} catch (RuntimeException e) {
throw e;
}
return result;
}
private boolean isShellOnly(Method method) {
CliMetaData cliMetadata = method.getAnnotation(CliMetaData.class);
return cliMetadata != null && cliMetadata.shellOnly();
}
private String getInterceptor(Method method) {
CliMetaData cliMetadata = method.getAnnotation(CliMetaData.class);
return cliMetadata != null ? cliMetadata.interceptor() : CliMetaData.ANNOTATION_NULL_VALUE;
}
public void terminate() {}
}