// Path: src/main/java/com/poolik/classfinder/ClassFinder.java
// public class ClassFinder {
// 
//   private Map<String, File> placesToSearch = new LinkedHashMap<>();
//   private static Collection<AdditionalResourceLoader> resourceLoaders = Arrays.<AdditionalResourceLoader>asList(new JarClasspathEntriesLoader());
//   private static final Logger log = LoggerFactory.getLogger(ClassFinder.class);
//   private boolean errorIfResultEmpty;
// 
//   /**
//    * Add the contents of the system classpath for classes.
//    */
//   public ClassFinder addClasspath() {
//     try {
//       String path = System.getProperty("java.class.path");
//       StringTokenizer tok = new StringTokenizer(path, File.pathSeparator);
//       while (tok.hasMoreTokens())
//         add(new File(tok.nextToken()));
//     } catch (Exception ex) {
//       log.error("Unable to get class path", ex);
//     }
//     return this;
//   }
// 
//   /**
//    * Add a jar file, zip file or directory to the list of places to search
//    * for classes.
//    *
//    * @param file the jar file, zip file or directory
//    * @return this
//    */
//   public ClassFinder add(File file) {
//     log.info("Adding file to look into: " + file.getAbsolutePath());
// 
//     if (fileCanContainClasses(file)) {
//       String absPath = file.getAbsolutePath();
//       if (placesToSearch.get(absPath) == null) {
//         placesToSearch.put(absPath, file);
//         for (AdditionalResourceLoader resourceLoader : resourceLoaders) {
//           if (resourceLoader.canLoadAdditional(file)) resourceLoader.loadAdditional(file, this);
//         }
//       }
//     } else {
//       log.info("The given path '" + file.getAbsolutePath() + "' cannot contain classes!");
//     }
// 
//     return this;
//   }
// 
//   /**
//    * Add an array jar files, zip files and/or directories to the list of
//    * places to search for classes.
//    *
//    * @param files the array of jar files, zip files and/or directories.
//    *              The array can contain a mixture of all of the above.
//    * @return this
//    */
//   public ClassFinder add(File[] files) {
//     return add(Arrays.asList(files));
//   }
// 
//   /**
//    * Add a <tt>Collection</tt> of jar files, zip files and/or directories
//    * to the list of places to search for classes.
//    *
//    * @param files the collection of jar files, zip files and/or directories.
//    * @return this
//    */
//   public ClassFinder add(Collection<File> files) {
//     for (File file : files)
//       add(file);
// 
//     return this;
//   }
// 
//   /**
//    * Clear the finder's notion of where to search.
//    */
//   public void clear() {
//     placesToSearch.clear();
//   }
// 
//   public ClassFinder setErrorIfResultEmpty(boolean errorIfResultEmpty) {
//     this.errorIfResultEmpty = errorIfResultEmpty;
//     return this;
//   }
// 
//   /**
//    * Find all classes in the search areas, implicitly accepting all of
//    * them.
//    *
//    * @return Collection of found classes
//    */
//   public Collection<ClassInfo> findClasses() {
//     return findClasses(null);
//   }
// 
//   /**
//    * Search all classes in the search areas, keeping only those that
//    * pass the specified filter.
//    *
//    * @param filter  the filter, or null for no filter
//    * @return Collection of found classes
//    */
//   public Collection<ClassInfo> findClasses(ClassFilter filter) {
//     Map<String,ClassInfo> foundClasses = new ParallelClassLoader().loadClassesFrom(placesToSearch.values());
//     log.info("Loaded " + foundClasses.size() + " classes.");
// 
//     Collection<ClassInfo> filteredClasses = filterClasses(filter, foundClasses);
// 
//     if (filteredClasses.size() == 0 && errorIfResultEmpty) {
//       log.warn("Found no classes, throwing exception");
//       throw new ClassFinderException("Didn't find any classes");
//     } else {
//       log.info("Returning " + filteredClasses.size() + " total classes");
//     }
//     foundClasses.clear();
//     return filteredClasses;
//   }
// 
//   private Collection<ClassInfo> filterClasses(ClassFilter filter, Map<String, ClassInfo> foundClasses) {
//     Collection<ClassInfo> classes = new ArrayList<>();
//     for (ClassInfo classInfo : foundClasses.values()) {
//       String className = classInfo.getClassName();
//       String locationName = classInfo.getClassLocation().getPath();
//       log.trace("Looking at " + locationName + " (" + className + ")");
//       if ((filter == null) || (filter.accept(classInfo, new ClassHierarchyResolver(foundClasses)))) {
//         log.trace("Filter accepted " + className);
//         classes.add(classInfo);
//       } else {
//         log.trace("Filter rejected " + className);
//       }
//     }
//     return classes;
//   }
// }


import com.poolik.classfinder.ClassFinder;
import java.io.File;
package com.poolik.classfinder.resourceLoader;



public interface AdditionalResourceLoader {
  public boolean canLoadAdditional(File file);
// Path: src/main/java/com/poolik/classfinder/ClassFinder.java
// public class ClassFinder {
// 
//   private Map<String, File> placesToSearch = new LinkedHashMap<>();
//   private static Collection<AdditionalResourceLoader> resourceLoaders = Arrays.<AdditionalResourceLoader>asList(new JarClasspathEntriesLoader());
//   private static final Logger log = LoggerFactory.getLogger(ClassFinder.class);
//   private boolean errorIfResultEmpty;
// 
//   /**
//    * Add the contents of the system classpath for classes.
//    */
//   public ClassFinder addClasspath() {
//     try {
//       String path = System.getProperty("java.class.path");
//       StringTokenizer tok = new StringTokenizer(path, File.pathSeparator);
//       while (tok.hasMoreTokens())
//         add(new File(tok.nextToken()));
//     } catch (Exception ex) {
//       log.error("Unable to get class path", ex);
//     }
//     return this;
//   }
// 
//   /**
//    * Add a jar file, zip file or directory to the list of places to search
//    * for classes.
//    *
//    * @param file the jar file, zip file or directory
//    * @return this
//    */
//   public ClassFinder add(File file) {
//     log.info("Adding file to look into: " + file.getAbsolutePath());
// 
//     if (fileCanContainClasses(file)) {
//       String absPath = file.getAbsolutePath();
//       if (placesToSearch.get(absPath) == null) {
//         placesToSearch.put(absPath, file);
//         for (AdditionalResourceLoader resourceLoader : resourceLoaders) {
//           if (resourceLoader.canLoadAdditional(file)) resourceLoader.loadAdditional(file, this);
//         }
//       }
//     } else {
//       log.info("The given path '" + file.getAbsolutePath() + "' cannot contain classes!");
//     }
// 
//     return this;
//   }
// 
//   /**
//    * Add an array jar files, zip files and/or directories to the list of
//    * places to search for classes.
//    *
//    * @param files the array of jar files, zip files and/or directories.
//    *              The array can contain a mixture of all of the above.
//    * @return this
//    */
//   public ClassFinder add(File[] files) {
//     return add(Arrays.asList(files));
//   }
// 
//   /**
//    * Add a <tt>Collection</tt> of jar files, zip files and/or directories
//    * to the list of places to search for classes.
//    *
//    * @param files the collection of jar files, zip files and/or directories.
//    * @return this
//    */
//   public ClassFinder add(Collection<File> files) {
//     for (File file : files)
//       add(file);
// 
//     return this;
//   }
// 
//   /**
//    * Clear the finder's notion of where to search.
//    */
//   public void clear() {
//     placesToSearch.clear();
//   }
// 
//   public ClassFinder setErrorIfResultEmpty(boolean errorIfResultEmpty) {
//     this.errorIfResultEmpty = errorIfResultEmpty;
//     return this;
//   }
// 
//   /**
//    * Find all classes in the search areas, implicitly accepting all of
//    * them.
//    *
//    * @return Collection of found classes
//    */
//   public Collection<ClassInfo> findClasses() {
//     return findClasses(null);
//   }
// 
//   /**
//    * Search all classes in the search areas, keeping only those that
//    * pass the specified filter.
//    *
//    * @param filter  the filter, or null for no filter
//    * @return Collection of found classes
//    */
//   public Collection<ClassInfo> findClasses(ClassFilter filter) {
//     Map<String,ClassInfo> foundClasses = new ParallelClassLoader().loadClassesFrom(placesToSearch.values());
//     log.info("Loaded " + foundClasses.size() + " classes.");
// 
//     Collection<ClassInfo> filteredClasses = filterClasses(filter, foundClasses);
// 
//     if (filteredClasses.size() == 0 && errorIfResultEmpty) {
//       log.warn("Found no classes, throwing exception");
//       throw new ClassFinderException("Didn't find any classes");
//     } else {
//       log.info("Returning " + filteredClasses.size() + " total classes");
//     }
//     foundClasses.clear();
//     return filteredClasses;
//   }
// 
//   private Collection<ClassInfo> filterClasses(ClassFilter filter, Map<String, ClassInfo> foundClasses) {
//     Collection<ClassInfo> classes = new ArrayList<>();
//     for (ClassInfo classInfo : foundClasses.values()) {
//       String className = classInfo.getClassName();
//       String locationName = classInfo.getClassLocation().getPath();
//       log.trace("Looking at " + locationName + " (" + className + ")");
//       if ((filter == null) || (filter.accept(classInfo, new ClassHierarchyResolver(foundClasses)))) {
//         log.trace("Filter accepted " + className);
//         classes.add(classInfo);
//       } else {
//         log.trace("Filter rejected " + className);
//       }
//     }
//     return classes;
//   }
// }


// Path: src/main/java/com/poolik/classfinder/resourceLoader/AdditionalResourceLoader.java
import com.poolik.classfinder.ClassFinder;
import java.io.File;

package com.poolik.classfinder.resourceLoader;



public interface AdditionalResourceLoader {
  public boolean canLoadAdditional(File file);
  public void loadAdditional(File file, ClassFinder classFinder);