/**
* 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.hive.hcatalog.templeton.tool;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.StringTokenizer;
/**
* Execute a local program. This is a singleton service that will
* execute a programs on the local box.
*
* Note that is is executed from LaunchMapper which is executed in
* different JVM from WebHCat (Templeton) server. Thus it should not call any classes
* not available on every node in the cluster (outside webhcat jar)
*/
final class TrivialExecService {
private static final Logger LOG = LoggerFactory.getLogger(TrivialExecService.class);
private static volatile TrivialExecService theSingleton;
/**
* Retrieve the singleton.
*/
public static synchronized TrivialExecService getInstance() {
if (theSingleton == null)
theSingleton = new TrivialExecService();
return theSingleton;
}
public Process run(List<String> cmd, List<String> removeEnv,
Map<String, String> environmentVariables) throws IOException {
LOG.info("run(cmd, removeEnv, environmentVariables)");
LOG.info("Starting cmd: " + cmd);
ProcessBuilder pb = new ProcessBuilder(cmd);
for (String key : removeEnv) {
if(pb.environment().containsKey(key)) {
LOG.info("Removing env var: " + key + "=" + pb.environment().get(key));
}
pb.environment().remove(key);
}
pb.environment().putAll(environmentVariables);
logDebugInfo("========Starting process with env:========", pb.environment());
printContentsOfDir(".");
return pb.start();
}
private static void logDebugInfo(String msg, Map<String, String> props) {
StringBuilder sb = TempletonUtils.dumpPropMap(msg, props);
LOG.info(sb.toString());
String sqoopHome = props.get("SQOOP_HOME");
if(TempletonUtils.isset(sqoopHome)) {
//this is helpful when Sqoop is installed on each node in the cluster to make sure
//relevant jars (JDBC in particular) are present on the node running the command
printContentsOfDir(sqoopHome + File.separator+ "lib");
}
}
/**
* Print files and directories in current {@code dir}.
*/
private static StringBuilder printContentsOfDir(String dir, int depth, StringBuilder sb) {
StringBuilder indent = new StringBuilder();
for(int i = 0; i < depth; i++) {
indent.append("--");
}
File folder = new File(dir);
sb.append(indent).append("Files in '").append(dir).append("' dir:").append(folder.getAbsolutePath()).append('\n');
File[] listOfFiles = folder.listFiles();
if(listOfFiles == null) {
return sb;
}
for (File fileName : listOfFiles) {
if (fileName.isFile()) {
sb.append(indent).append("File: ").append(fileName.getName()).append('\n');
}
else if (fileName.isDirectory()) {
printContentsOfDir(fileName.getName(), depth+1, sb);
}
}
return sb;
}
private static void printContentsOfDir(String dir) {
LOG.info(printContentsOfDir(dir, 0, new StringBuilder()).toString());
}
}