hadoop FindClass 源码

  • 2022-10-20
  • 浏览 (213)

haddop FindClass 代码

文件路径:/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/util/FindClass.java

/*
 * 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 org.apache.hadoop.classification.VisibleForTesting;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.conf.Configured;
import org.apache.hadoop.util.Tool;
import org.apache.hadoop.util.ToolRunner;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintStream;
import java.net.URL;
import java.security.CodeSource;

/**
 * This entry point exists for diagnosing classloader problems:
 * is a class or resource present -and if so, where?
 *
 * <p>
 * Actions
 * <br>
 * <ul>
 *   <li><pre>load</pre>: load a class but do not attempt to create it </li>
 *   <li><pre>create</pre>: load and create a class, print its string value</li>
 *   <li><pre>printresource</pre>: load a resource then print it to stdout</li>
 *   <li><pre>resource</pre>: load a resource then print the URL of that
 *   resource</li>
 * </ul>
 *
 * It returns an error code if a class/resource cannot be loaded/found
 * -and optionally a class may be requested as being loaded.
 * The latter action will call the class's constructor -it must support an
 * empty constructor); any side effects from the
 * constructor or static initializers will take place.
 *
 * All error messages are printed to {@link System#out}; errors
 * to {@link System#err}.
 * 
 */
@SuppressWarnings("UseOfSystemOutOrSystemErr")
public final class FindClass extends Configured implements Tool {

  /**
   * create command: {@value}
   */
  public static final String A_CREATE = "create";

  /**
   * Load command: {@value}
   */
  public static final String A_LOAD = "load";

  /**
   * Command to locate a resource: {@value}
   */
  public static final String A_RESOURCE = "locate";

  /**
   * Command to locate and print a resource: {@value}
   */
  public static final String A_PRINTRESOURCE = "print";

  /**
   * Exit code when the operation succeeded: {@value}
   */
  public static final int SUCCESS = 0;

  /**
   * generic error {@value}
   */
  protected static final int E_GENERIC = 1;

  /**
   * usage error -bad arguments or similar {@value}
   */
  protected static final int E_USAGE = 2;

  /**
   * class or resource not found {@value}
   */
  protected static final int E_NOT_FOUND = 3;

  /**
   * class load failed {@value}
   */
  protected static final int E_LOAD_FAILED = 4;

  /**
   * class creation failed {@value}
   */
  protected static final int E_CREATE_FAILED = 5;

  /**
   * Output stream. Defaults to {@link System#out}
   */
  private static PrintStream stdout = System.out;
  
  /**
   * Error stream. Defaults to {@link System#err}
   */
  private static PrintStream stderr = System.err;

  /**
   * Empty constructor; passes a new Configuration
   * object instance to its superclass's constructor
   */
  public FindClass() {
    super(new Configuration());
  }

  /**
   * Create a class with a specified configuration
   * @param conf configuration
   */
  public FindClass(Configuration conf) {
    super(conf);
  }

  /**
   * Change the output streams to be something other than the 
   * System.out and System.err streams
   * @param out new stdout stream
   * @param err new stderr stream
   */
  @VisibleForTesting
  public static void setOutputStreams(PrintStream out, PrintStream err) {
    stdout = out;
    stderr = err;
  }

  /**
   * Get a class fromt the configuration
   * @param name the class name
   * @return the class
   * @throws ClassNotFoundException if the class was not found
   * @throws Error on other classloading problems
   */
  private Class getClass(String name) throws ClassNotFoundException {
    return getConf().getClassByName(name);
  }

  /**
   * Get the resource
   * @param name resource name
   * @return URL or null for not found
   */
  private URL getResource(String name) {
    return getConf().getResource(name);
  }

  /**
   * Load a resource
   * @param name resource name
   * @return the status code
   */
  private int loadResource(String name) {
    URL url = getResource(name);
    if (url == null) {
      err("Resource not found: %s", name);
      return E_NOT_FOUND;
    }
    out("%s: %s", name, url);
    return SUCCESS;
  }

  /**
   * Dump a resource to out
   * @param name resource name
   * @return the status code
   */
  @SuppressWarnings("NestedAssignment")
  private int dumpResource(String name) {
    URL url = getResource(name);
    if (url == null) {
      err("Resource not found:" + name);
      return E_NOT_FOUND;
    }
    try {
      //open the resource
      InputStream instream = url.openStream();
      //read it in and print
      int data;
      while (-1 != (data = instream.read())) {
        stdout.print((char) data);
      }
      //end of file
      stdout.print('\n');
      return SUCCESS;
    } catch (IOException e) {
      printStack(e, "Failed to read resource %s at URL %s", name, url);
      return E_LOAD_FAILED;
    }
  }

  /**
   * print something to stderr
   * @param s string to print
   */
  private static void err(String s, Object... args) {
    stderr.format(s, args);
    stderr.print('\n');
  }

  /**
   * print something to stdout
   * @param s string to print
   */
  private static void out(String s, Object... args) {
    stdout.format(s, args);
    stdout.print('\n');
  }

  /**
   * print a stack trace with text
   * @param e the exception to print
   * @param text text to print
   */
  private static void printStack(Throwable e, String text, Object... args) {
    err(text, args);
    e.printStackTrace(stderr);
  }

  /**
   * Loads the class of the given name
   * @param name classname
   * @return outcome code
   */
  private int loadClass(String name) {
    try {
      Class clazz = getClass(name);
      loadedClass(name, clazz);
      return SUCCESS;
    } catch (ClassNotFoundException e) {
      printStack(e, "Class not found " + name);
      return E_NOT_FOUND;
    } catch (Exception e) {
      printStack(e, "Exception while loading class " + name);
      return E_LOAD_FAILED;
    } catch (Error e) {
      printStack(e, "Error while loading class " + name);
      return E_LOAD_FAILED;
    }
  }

  /**
   * Log that a class has been loaded, and where from.
   * @param name classname
   * @param clazz class
   */
  private void loadedClass(String name, Class clazz) {
    out("Loaded %s as %s", name, clazz);
    CodeSource source = clazz.getProtectionDomain().getCodeSource();
    URL url = source.getLocation();
    out("%s: %s", name, url);
  }

  /**
   * Create an instance of a class
   * @param name classname
   * @return the outcome
   */
  private int createClassInstance(String name) {
    try {
      Class clazz = getClass(name);
      loadedClass(name, clazz);
      Object instance = clazz.newInstance();
      try {
        //stringify
        out("Created instance " + instance.toString());
      } catch (Exception e) {
        //catch those classes whose toString() method is brittle, but don't fail the probe
        printStack(e,
                   "Created class instance but the toString() operator failed");
      }
      return SUCCESS;
    } catch (ClassNotFoundException e) {
      printStack(e, "Class not found " + name);
      return E_NOT_FOUND;
    } catch (Exception e) {
      printStack(e, "Exception while creating class " + name);
      return E_CREATE_FAILED;
    } catch (Error e) {
      printStack(e, "Exception while creating class " + name);
      return E_CREATE_FAILED;
    }
  }

  /**
   * Run the class/resource find or load operation
   * @param args command specific arguments.
   * @return the outcome
   * @throws Exception if something went very wrong
   */
  @Override
  public int run(String[] args) throws Exception {
    if (args.length != 2) {
      return usage(args);
    }
    String action = args[0];
    String name = args[1];
    int result;
    if (A_LOAD.equals(action)) {
      result = loadClass(name);
    } else if (A_CREATE.equals(action)) {
      //first load to separate load errors from create
      result = loadClass(name);
      if (result == SUCCESS) {
        //class loads, so instantiate it
        result = createClassInstance(name);
      }
    } else if (A_RESOURCE.equals(action)) {
      result = loadResource(name);
    } else if (A_PRINTRESOURCE.equals(action)) {
      result = dumpResource(name);
    } else {
      result = usage(args);
    }
    return result;
  }

  /**
   * Print a usage message
   * @param args the command line arguments
   * @return an exit code
   */
  private int usage(String[] args) {
    err(
      "Usage : [load | create] <classname>");
    err(
      "        [locate | print] <resourcename>]");
    err("The return codes are:");
    explainResult(SUCCESS,
                  "The operation was successful");
    explainResult(E_GENERIC,
                  "Something went wrong");
    explainResult(E_USAGE,
                  "This usage message was printed");
    explainResult(E_NOT_FOUND,
                  "The class or resource was not found");
    explainResult(E_LOAD_FAILED,
                  "The class was found but could not be loaded");
    explainResult(E_CREATE_FAILED,
                  "The class was loaded, but an instance of it could not be created");
    return E_USAGE;
  }

  /**
   * Explain an error code as part of the usage
   * @param errorcode error code returned
   * @param text error text
   */
  private void explainResult(int errorcode, String text) {
    err(" %2d -- %s ", errorcode , text);
  }

  /**
   * Main entry point. 
   * Runs the class via the {@link ToolRunner}, then
   * exits with an appropriate exit code. 
   * @param args argument list
   */
  public static void main(String[] args) {
    try {
      int result = ToolRunner.run(new FindClass(), args);
      System.exit(result);
    } catch (Exception e) {
      printStack(e, "Running FindClass");
      System.exit(E_GENERIC);
    }
  }
}

相关信息

hadoop 源码目录

相关文章

hadoop ApplicationClassLoader 源码

hadoop AsyncDiskService 源码

hadoop AutoCloseableLock 源码

hadoop BasicDiskValidator 源码

hadoop BlockingThreadPoolExecutorService 源码

hadoop CacheableIPList 源码

hadoop ChunkedArrayList 源码

hadoop ClassUtil 源码

hadoop Classpath 源码

hadoop CleanerUtil 源码

0  赞