All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.apache.hive.beeline.ClassNameCompleter Maven / Gradle / Ivy

The newest version!
/**
 * Copyright (c) 2002-2006, Marc Prud'hommeaux 
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or
 * without modification, are permitted provided that the following
 * conditions are met:
 *
 * Redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer.
 *
 * Redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer
 * in the documentation and/or other materials provided with
 * the distribution.
 *
 * Neither the name of JLine nor the names of its contributors
 * may be used to endorse or promote products derived from this
 * software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
 * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
 * EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
 * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
 * OF THE POSSIBILITY OF SUCH DAMAGE.
 */
/**
 * 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.beeline;

import jline.console.completer.StringsCompleter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.File;
import java.io.IOException;
import java.io.FileInputStream;
import java.net.JarURLConnection;
import java.net.URL;
import java.net.URLClassLoader;
import java.net.URLConnection;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.ArrayList;
import java.util.Set;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import java.util.Enumeration;
import java.util.TreeSet;
import java.util.zip.ZipInputStream;
import java.util.zip.ZipEntry;

/**
 * the completer is original provided in JLine 0.9.94 and is being removed in 2.12. Add the
 * previous implement for usage of the beeline.
 */
public class ClassNameCompleter extends StringsCompleter {

  private static final Logger LOG = LoggerFactory.getLogger(ClassNameCompleter.class.getName());
  public final static String clazzFileNameExtension = ".class";
  public final static String jarFileNameExtension = ".jar";

  public ClassNameCompleter(String... candidates) {
    super(candidates);
  }

  public static String[] getClassNames() throws IOException {
    Set urls = new HashSet();

    for (ClassLoader loader = Thread.currentThread().getContextClassLoader(); loader != null;
         loader = loader.getParent()) {
      if (!(loader instanceof URLClassLoader)) {
        continue;
      }

      urls.addAll(Arrays.asList(((URLClassLoader) loader).getURLs()));
    }

    // Now add the URL that holds java.lang.String. This is because
    // some JVMs do not report the core classes jar in the list of
    // class loaders.
    Class[] systemClasses = new Class[]{String.class, javax.swing.JFrame.class};

    for (int i = 0; i < systemClasses.length; i++) {
      URL classURL = systemClasses[i]
              .getResource("/" + systemClasses[i].getName().replace('.', '/') + clazzFileNameExtension);

      if (classURL != null) {
        URLConnection uc = classURL.openConnection();

        if (uc instanceof JarURLConnection) {
          urls.add(((JarURLConnection) uc).getJarFileURL());
        }
      }
    }

    Set classes = new HashSet();

    for (Iterator i = urls.iterator(); i.hasNext(); ) {
      URL url = (URL) i.next();
      try {
        File file = new File(url.getFile());

        if (file.isDirectory()) {
          Set files = getClassFiles(file.getAbsolutePath(), new HashSet(), file, new int[] { 200 });
          classes.addAll(files);

          continue;
        }

        if (!isJarFile(file)) {
          continue;
        }

        JarFile jf = new JarFile(file);

        for (Enumeration e = jf.entries(); e.hasMoreElements();) {
          JarEntry entry = (JarEntry) e.nextElement();

          if (entry == null) {
            continue;
          }

          String name = entry.getName();

          if (isClazzFile(name)) {
            /* only use class file */
            classes.add(name);
          } else if (isJarFile(name)) {
            classes.addAll(getClassNamesFromJar(name));
          } else {
            continue;
          }
        }
      } catch (IOException e) {
        throw new IOException(String.format("Error reading classpath entry: %s", url), e);
      }
    }

    // now filter classes by changing "/" to "." and trimming the
    // trailing ".class"
    Set classNames = new TreeSet();

    for (Iterator i = classes.iterator(); i.hasNext(); ) {
      String name = (String) i.next();
      classNames.add(name.replace('/', '.').substring(0, name.length() - 6));
    }

    return (String[]) classNames.toArray(new String[classNames.size()]);
  }

  private static Set getClassFiles(String root, Set holder, File directory, int[] maxDirectories) {
    // we have passed the maximum number of directories to scan
    if (maxDirectories[0]-- < 0) {
      return holder;
    }

    File[] files = directory.listFiles();

    for (int i = 0; (files != null) && (i < files.length); i++) {
      String name = files[i].getAbsolutePath();

      if (!(name.startsWith(root))) {
        continue;
      } else if (files[i].isDirectory()) {
        getClassFiles(root, holder, files[i], maxDirectories);
      } else if (files[i].getName().endsWith(clazzFileNameExtension)) {
        holder.add(files[i].getAbsolutePath().
                substring(root.length() + 1));
      }
    }

    return holder;
  }

  /**
   * Get clazz names from a jar file path
   * @param path specifies the jar file's path
   * @return
   */
  private static List getClassNamesFromJar(String path) {
    List classNames = new ArrayList();
    ZipInputStream zip = null;
    try {
      zip = new ZipInputStream(new FileInputStream(path));
      ZipEntry entry = zip.getNextEntry();
      while (entry != null) {
        if (!entry.isDirectory() && entry.getName().endsWith(clazzFileNameExtension)) {
          StringBuilder className = new StringBuilder();
          for (String part : entry.getName().split("/")) {
            if (className.length() != 0) {
              className.append(".");
            }
            className.append(part);
            if (part.endsWith(clazzFileNameExtension)) {
              className.setLength(className.length() - clazzFileNameExtension.length());
            }
          }
          classNames.add(className.toString());
        }
        entry = zip.getNextEntry();
      }
    } catch (IOException e) {
      LOG.error("Fail to parse the class name from the Jar file due to the exception:" + e);
    } finally {
      if (zip != null) {
        try {
          zip.close();
        } catch (IOException e) {
          LOG.error("Fail to close the file due to the exception:" + e);
        }
      }
    }

    return classNames;
  }

  private static boolean isJarFile(File file) {
    return (file != null && file.isFile() && isJarFile(file.getName()));
  }

  private static boolean isJarFile(String fileName) {
    return fileName.endsWith(jarFileNameExtension);
  }

  private static boolean isClazzFile(String clazzName) {
    return clazzName.endsWith(clazzFileNameExtension);
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy