|
25 | 25 | import com.beust.jcommander.Parameters; |
26 | 26 | import com.google.common.annotations.VisibleForTesting; |
27 | 27 | import com.google.common.collect.ImmutableSet; |
| 28 | +import java.io.FileInputStream; |
| 29 | +import java.io.InputStream; |
28 | 30 | import java.util.List; |
| 31 | +import java.util.Properties; |
29 | 32 | import java.util.Set; |
30 | 33 | import org.apache.commons.logging.LogFactory; |
31 | 34 | import org.apache.hadoop.conf.Configurable; |
32 | 35 | import org.apache.hadoop.conf.Configuration; |
33 | 36 | import org.apache.hadoop.conf.Configured; |
| 37 | +import org.apache.hadoop.fs.Path; |
34 | 38 | import org.apache.hadoop.util.Tool; |
35 | 39 | import org.apache.hadoop.util.ToolRunner; |
36 | 40 | import org.apache.log4j.Level; |
@@ -73,6 +77,11 @@ public class Main extends Configured implements Tool { |
73 | 77 | description = "Set a configuration property (format: key=value). Can be specified multiple times.") |
74 | 78 | private List<String> confProperties; |
75 | 79 |
|
| 80 | + @Parameter( |
| 81 | + names = {"--config-file"}, |
| 82 | + description = "Path to a configuration file (properties or Hadoop XML format).") |
| 83 | + private String configFilePath; |
| 84 | + |
76 | 85 | @VisibleForTesting |
77 | 86 | @Parameter(names = "--dollar-zero", description = "A way for the runtime path to be passed in", hidden = true) |
78 | 87 | String programName = DEFAULT_PROGRAM_NAME; |
@@ -172,6 +181,24 @@ public int run(String[] args) throws Exception { |
172 | 181 | // If the command does not support the configs, it would simply be ignored. |
173 | 182 | if (command instanceof Configurable) { |
174 | 183 | Configuration merged = new Configuration(getConf()); |
| 184 | + |
| 185 | + if (configFilePath != null) { |
| 186 | + try { |
| 187 | + if (isXmlConfigFile(configFilePath)) { |
| 188 | + loadXmlConfiguration(merged, configFilePath); |
| 189 | + } else if (isPropertiesConfigFile(configFilePath)) { |
| 190 | + loadPropertiesConfiguration(merged, configFilePath); |
| 191 | + } else { |
| 192 | + throw new IllegalArgumentException( |
| 193 | + "Unsupported config file format. Only .xml and .properties files are supported: " |
| 194 | + + configFilePath); |
| 195 | + } |
| 196 | + } catch (Exception e) { |
| 197 | + throw new IllegalArgumentException( |
| 198 | + "Failed to load config file '" + configFilePath + "': " + e.getMessage(), e); |
| 199 | + } |
| 200 | + } |
| 201 | + |
175 | 202 | if (confProperties != null) { |
176 | 203 | for (String prop : confProperties) { |
177 | 204 | String[] parts = prop.split("=", 2); |
@@ -218,4 +245,27 @@ public static void main(String[] args) throws Exception { |
218 | 245 | int rc = ToolRunner.run(new Configuration(), new Main(console), args); |
219 | 246 | System.exit(rc); |
220 | 247 | } |
| 248 | + |
| 249 | + private boolean isXmlConfigFile(String filePath) { |
| 250 | + return filePath.toLowerCase().endsWith(".xml"); |
| 251 | + } |
| 252 | + |
| 253 | + private boolean isPropertiesConfigFile(String filePath) { |
| 254 | + String lowerPath = filePath.toLowerCase(); |
| 255 | + return lowerPath.endsWith(".properties"); |
| 256 | + } |
| 257 | + |
| 258 | + private void loadXmlConfiguration(Configuration config, String filePath) { |
| 259 | + config.addResource(new Path(filePath)); |
| 260 | + console.debug("Loaded XML configuration from file: {}", filePath); |
| 261 | + } |
| 262 | + |
| 263 | + private void loadPropertiesConfiguration(Configuration config, String filePath) throws Exception { |
| 264 | + try (InputStream in = new FileInputStream(filePath)) { |
| 265 | + Properties props = new Properties(); |
| 266 | + props.load(in); |
| 267 | + props.forEach((key, value) -> config.set(key.toString(), value.toString())); |
| 268 | + console.debug("Loaded properties configuration from file: {}", filePath); |
| 269 | + } |
| 270 | + } |
221 | 271 | } |
0 commit comments