package com.yahoo.labs.samoa.moa.core;

/*
 * #%L
 * SAMOA
 * %%
 * Copyright (C) 2014 - 2015 Apache Software Foundation
 * %%
 * Licensed 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.
 * #L%
 */

import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.net.URLClassLoader;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;

/**
 * Class for discovering classes via reflection in the java class path.
 * 
 * @author Richard Kirkby (rkirkby@cs.waikato.ac.nz)
 * @version $Revision: 7 $
 */
public class AutoClassDiscovery {

  protected static final Map<String, String[]> cachedClassNames = new HashMap<String, String[]>();

  public static String[] findClassNames(String packageNameToSearch) {
    String[] cached = cachedClassNames.get(packageNameToSearch);
    if (cached == null) {
      HashSet<String> classNames = new HashSet<String>();
      /*
       * StringTokenizer pathTokens = new StringTokenizer(System
       * .getProperty("java.class.path"), File.pathSeparator);
       */
      String packageDirName = packageNameToSearch.replace('.',
          File.separatorChar);
      String packageJarName = packageNameToSearch.length() > 0 ? (packageNameToSearch.replace('.', '/') + "/")
          : "";
      String part = "";

      AutoClassDiscovery adc = new AutoClassDiscovery();
      URLClassLoader sysLoader = (URLClassLoader) adc.getClass().getClassLoader();
      URL[] cl_urls = sysLoader.getURLs();

      for (int i = 0; i < cl_urls.length; i++) {
        part = cl_urls[i].toString();
        if (part.startsWith("file:")) {
          part = part.replace(" ", "%20");
          try {
            File temp = new File(new java.net.URI(part));
            part = temp.getAbsolutePath();
          } catch (URISyntaxException e) {
            e.printStackTrace();
          }
        }

        // find classes
        ArrayList<File> files = new ArrayList<File>();
        File dir = new File(part);
        if (dir.isDirectory()) {
          File root = new File(dir.toString() + File.separatorChar + packageDirName);
          String[] names = findClassesInDirectoryRecursive(root, "");
          classNames.addAll(Arrays.asList(names));
        } else {
          try {
            JarFile jar = new JarFile(part);
            Enumeration<JarEntry> jarEntries = jar.entries();
            while (jarEntries.hasMoreElements()) {
              String jarEntry = jarEntries.nextElement().getName();
              if (jarEntry.startsWith(packageJarName)) {
                String relativeName = jarEntry.substring(packageJarName.length());
                if (relativeName.endsWith(".class")) {
                  relativeName = relativeName.replace('/',
                      '.');
                  classNames.add(relativeName.substring(0,
                      relativeName.length()
                          - ".class".length()));
                }
              }
            }
          } catch (IOException ignored) {
            // ignore unreadable files
          }
        }
      }

      /*
       * while (pathTokens.hasMoreElements()) { String pathToSearch =
       * pathTokens.nextElement().toString(); if (pathToSearch.endsWith(".jar"))
       * { try { JarFile jar = new JarFile(pathToSearch); Enumeration<JarEntry>
       * jarEntries = jar.entries(); while (jarEntries.hasMoreElements()) {
       * String jarEntry = jarEntries.nextElement() .getName(); if
       * (jarEntry.startsWith(packageJarName)) { String relativeName = jarEntry
       * .substring(packageJarName.length()); if
       * (relativeName.endsWith(".class")) { relativeName =
       * relativeName.replace('/', '.');
       * classNames.add(relativeName.substring(0, relativeName.length() -
       * ".class".length())); } } } } catch (IOException ignored) { // ignore
       * unreadable files } } else { File root = new File(pathToSearch +
       * File.separatorChar + packageDirName); String[] names =
       * findClassesInDirectoryRecursive(root, ""); for (String name : names) {
       * classNames.add(name); } } }
       */
      cached = classNames.toArray(new String[classNames.size()]);
      Arrays.sort(cached);
      cachedClassNames.put(packageNameToSearch, cached);
    }
    return cached;
  }

  protected static String[] findClassesInDirectoryRecursive(File root,
      String packagePath) {
    HashSet<String> classNames = new HashSet<String>();
    if (root.isDirectory()) {
      String[] list = root.list();
      for (String string : list) {
        if (string.endsWith(".class")) {
          classNames.add(packagePath
              + string.substring(0, string.length()
                  - ".class".length()));
        } else {
          File testDir = new File(root.getPath() + File.separatorChar
              + string);
          if (testDir.isDirectory()) {
            String[] names = findClassesInDirectoryRecursive(
                testDir, packagePath + string + ".");
            classNames.addAll(Arrays.asList(names));
          }
        }
      }
    }
    return classNames.toArray(new String[classNames.size()]);
  }

  public static Class[] findClassesOfType(String packageNameToSearch,
      Class<?> typeDesired) {
    ArrayList<Class<?>> classesFound = new ArrayList<Class<?>>();
    String[] classNames = findClassNames(packageNameToSearch);
    for (String className : classNames) {
      String fullName = packageNameToSearch.length() > 0 ? (packageNameToSearch
          + "." + className)
          : className;
      if (isPublicConcreteClassOfType(fullName, typeDesired)) {
        try {
          classesFound.add(Class.forName(fullName));
        } catch (Exception ignored) {
          // ignore classes that we cannot instantiate
        }
      }
    }
    return classesFound.toArray(new Class[classesFound.size()]);
  }

  public static boolean isPublicConcreteClassOfType(String className,
      Class<?> typeDesired) {
    Class<?> testClass = null;
    try {
      testClass = Class.forName(className);
    } catch (Exception e) {
      return false;
    }
    int classModifiers = testClass.getModifiers();
    return (java.lang.reflect.Modifier.isPublic(classModifiers)
        && !java.lang.reflect.Modifier.isAbstract(classModifiers)
        && typeDesired.isAssignableFrom(testClass) && hasEmptyConstructor(testClass));
  }

  public static boolean hasEmptyConstructor(Class<?> type) {
    try {
      type.getConstructor();
      return true;
    } catch (Exception ignored) {
      return false;
    }
  }
}
