/* * 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.hadoop.util; import java.io.File; import java.io.IOException; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import org.apache.hadoop.classification.InterfaceAudience; import org.apache.hadoop.fs.FileUtil; import org.apache.hadoop.fs.Path; import org.apache.hadoop.fs.shell.CommandFormat; import org.apache.hadoop.fs.shell.CommandFormat.UnknownOptionException; /** * Command-line utility for getting the full classpath needed to launch a Hadoop * client application. If the hadoop script is called with "classpath" as the * command, then it simply prints the classpath and exits immediately without * launching a JVM. The output likely will include wildcards in the classpath. * If there are arguments passed to the classpath command, then this class gets * called. With the --glob argument, it prints the full classpath with wildcards * expanded. This is useful in situations where wildcard syntax isn't usable. * With the --jar argument, it writes the classpath as a manifest in a jar file. * This is useful in environments with short limitations on the maximum command * line length, where it may not be possible to specify the full classpath in a * command. For example, the maximum command line length on Windows is 8191 * characters. */ @InterfaceAudience.Private public final class Classpath { private static final String usage = "classpath [--glob|--jar <path>|-h|--help] :\n" + " Prints the classpath needed to get the Hadoop jar and the required\n" + " libraries.\n" + " Options:\n" + "\n" + " --glob expand wildcards\n" + " --jar <path> write classpath as manifest in jar named <path>\n" + " -h, --help print help\n"; /** * Main entry point. * * @param args command-line arguments */ public static void main(String[] args) { if (args.length < 1 || args[0].equals("-h") || args[0].equals("--help")) { System.out.println(usage); return; } // Copy args, because CommandFormat mutates the list. List<String> argsList = new ArrayList<String>(Arrays.asList(args)); CommandFormat cf = new CommandFormat(0, Integer.MAX_VALUE, "-glob", "-jar"); try { cf.parse(argsList); } catch (UnknownOptionException e) { terminate(1, "unrecognized option"); return; } String classPath = System.getProperty("java.class.path"); if (cf.getOpt("-glob")) { // The classpath returned from the property has been globbed already. System.out.println(classPath); } else if (cf.getOpt("-jar")) { if (argsList.isEmpty() || argsList.get(0) == null || argsList.get(0).isEmpty()) { terminate(1, "-jar option requires path of jar file to write"); return; } // Write the classpath into the manifest of a temporary jar file. Path workingDir = new Path(System.getProperty("user.dir")); final String tmpJarPath; try { tmpJarPath = FileUtil.createJarWithClassPath(classPath, workingDir, System.getenv())[0]; } catch (IOException e) { terminate(1, "I/O error creating jar: " + e.getMessage()); return; } // Rename the temporary file to its final location. String jarPath = argsList.get(0); try { FileUtil.replaceFile(new File(tmpJarPath), new File(jarPath)); } catch (IOException e) { terminate(1, "I/O error renaming jar temporary file to path: " + e.getMessage()); return; } } } /** * Prints a message to stderr and exits with a status code. * * @param status exit code * @param msg message */ private static void terminate(int status, String msg) { System.err.println(msg); ExitUtil.terminate(status, msg); } }