LocalExecClient.java
/*
* This file is part of Waarp Project (named also Waarp or GG).
*
* Copyright (c) 2019, Waarp SAS, and individual contributors by the @author
* tags. See the COPYRIGHT.txt in the distribution for a full listing of
* individual contributors.
*
* All Waarp Project is free software: you can redistribute it and/or
* modify it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or (at your
* option) any later version.
*
* Waarp is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with
* Waarp . If not, see <http://www.gnu.org/licenses/>.
*/
package org.waarp.gateway.ftp.exec;
import io.netty.bootstrap.Bootstrap;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFuture;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import org.waarp.commandexec.client.LocalExecClientHandler;
import org.waarp.commandexec.client.LocalExecClientInitializer;
import org.waarp.commandexec.utils.LocalExecResult;
import org.waarp.common.crypto.ssl.WaarpSslUtility;
import org.waarp.common.future.WaarpFuture;
import org.waarp.common.logging.SysErrLogger;
import org.waarp.common.logging.WaarpLogger;
import org.waarp.common.logging.WaarpLoggerFactory;
import org.waarp.common.utility.WaarpNettyUtil;
import org.waarp.common.utility.WaarpThreadFactory;
import org.waarp.openr66.protocol.configuration.Configuration;
import java.net.InetSocketAddress;
/**
* Client to execute external command through Waarp Local Exec
*/
public class LocalExecClient {
/**
* Internal Logger
*/
private static final WaarpLogger logger =
WaarpLoggerFactory.getLogger(LocalExecClient.class);
private static InetSocketAddress address;
// Configure the client.
private static Bootstrap bootstrapLocalExec;
// Configure the pipeline factory.
private static LocalExecClientInitializer localExecClientInitializer;
/**
* Initialize the LocalExec Client context
*/
public static void initialize(final int clientThread,
final long maxGlobalMemory) {
final EventLoopGroup localPipelineExecutor =
new NioEventLoopGroup(clientThread * 2,
new WaarpThreadFactory("LocalExecutor"));
// Configure the client.
bootstrapLocalExec = new Bootstrap();
WaarpNettyUtil.setBootstrap(bootstrapLocalExec, localPipelineExecutor,
(int) Configuration.configuration.getTimeoutCon());
// Configure the pipeline factory.
localExecClientInitializer = new LocalExecClientInitializer();
bootstrapLocalExec.handler(localExecClientInitializer);
}
/**
* To be called when the server is shutting down to release the resources
*/
public static void releaseResources() {
if (bootstrapLocalExec == null) {
return;
}
// Shut down all thread pools to exit.
bootstrapLocalExec.config().group().shutdownGracefully();
localExecClientInitializer.releaseResources();
}
private Channel channel;
private LocalExecResult result;
public LocalExecClient() {
// nothing
}
public final LocalExecResult getLocalExecResult() {
return result;
}
/**
* Run one command with a specific allowed delay for execution. The
* connection
* must be ready (done with
* connect()).
*
* @param command
* @param delay
* @param futureCompletion
*/
public final void runOneCommand(final String command, final long delay,
final WaarpFuture futureCompletion) {
// Initialize the command context
final LocalExecClientHandler clientHandler =
(LocalExecClientHandler) channel.pipeline().last();
// Command to execute
clientHandler.initExecClient(delay, command);
// Wait for the end of the exec command
result = clientHandler.waitFor(delay * 2);
if (futureCompletion == null) {
return;
}
if (result.getStatus() == 0) {
futureCompletion.setSuccess();
logger.info("Exec OK with {}", command);
} else if (result.getStatus() == 1) {
logger.warn("Exec in warning with {}", command);
futureCompletion.setSuccess();
} else {
logger.error(
"Status: " + result.getStatus() + " Exec in error with " + command +
'\n' + result.getResult());
futureCompletion.cancel();
}
}
/**
* Connect to the Server
*/
public final boolean connect() {
// Start the connection attempt.
final ChannelFuture future = bootstrapLocalExec.connect(getAddress());
// Wait until the connection attempt succeeds or fails.
try {
channel = future.await().sync().channel();
} catch (final InterruptedException e) {//NOSONAR
SysErrLogger.FAKE_LOGGER.ignoreLog(e);
}
if (!future.isSuccess()) {
logger.error("Client Not Connected", future.cause());
return false;
}
return true;
}
/**
* Disconnect from the server
*/
public final void disconnect() {
// Close the connection. Make sure the close operation ends because
// all I/O operations are asynchronous in Netty.
WaarpNettyUtil.awaitOrInterrupted(
WaarpSslUtility.closingSslChannel(channel));
}
/**
* @return the address
*/
public static InetSocketAddress getAddress() {
return address;
}
/**
* @param address the address to set
*/
public static void setAddress(final InetSocketAddress address) {
LocalExecClient.address = address;
}
}