001package com.github.sarxos.webcam; 002 003import java.io.File; 004import java.io.IOException; 005import java.net.URL; 006import java.util.ArrayList; 007import java.util.Enumeration; 008import java.util.List; 009 010import org.slf4j.Logger; 011import org.slf4j.LoggerFactory; 012 013 014public class WebcamDriverUtils { 015 016 private static final Logger LOG = LoggerFactory.getLogger(WebcamDriverUtils.class); 017 018 private WebcamDriverUtils() { 019 } 020 021 /** 022 * Find webcam driver. Scan packages to search drivers specified in the 023 * argument. 024 * 025 * @param names array of driver names to search for 026 * @return Driver if found or throw exception 027 * @throw WebcamException 028 */ 029 protected static WebcamDriver findDriver(List<String> names, List<Class<?>> classes) { 030 031 for (String name : names) { 032 033 LOG.info("Searching driver {}", name); 034 035 Class<?> clazz = null; 036 037 for (Class<?> c : classes) { 038 if (c.getCanonicalName().equals(name)) { 039 clazz = c; 040 break; 041 } 042 } 043 044 if (clazz == null) { 045 try { 046 clazz = Class.forName(name); 047 } catch (ClassNotFoundException e) { 048 LOG.trace("Class not found {}, fall thru", name); 049 } 050 } 051 052 if (clazz == null) { 053 LOG.debug("Driver {} not found", name); 054 continue; 055 } 056 057 LOG.info("Webcam driver {} has been found", name); 058 059 try { 060 return (WebcamDriver) clazz.newInstance(); 061 } catch (InstantiationException e) { 062 throw new RuntimeException(e); 063 } catch (IllegalAccessException e) { 064 throw new RuntimeException(e); 065 } 066 } 067 068 return null; 069 } 070 071 /** 072 * Scans all classes accessible from the context class loader which belong 073 * to the given package and subpackages. 074 * 075 * @param packageName The base package 076 * @param flat scan only one package level, do not dive into subdirectories 077 * @return The classes 078 * @throws ClassNotFoundException 079 * @throws IOException 080 */ 081 protected static Class<?>[] getClasses(String pkgname, boolean flat) { 082 083 List<File> dirs = new ArrayList<File>(); 084 List<Class<?>> classes = new ArrayList<Class<?>>(); 085 086 ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); 087 String path = pkgname.replace('.', '/'); 088 089 Enumeration<URL> resources = null; 090 try { 091 resources = classLoader.getResources(path); 092 } catch (IOException e) { 093 throw new RuntimeException("Cannot read path " + path, e); 094 } 095 096 while (resources.hasMoreElements()) { 097 URL resource = resources.nextElement(); 098 dirs.add(new File(resource.getFile())); 099 } 100 101 for (File directory : dirs) { 102 try { 103 classes.addAll(findClasses(directory, pkgname, flat)); 104 } catch (ClassNotFoundException e) { 105 throw new RuntimeException("Class not found", e); 106 } 107 } 108 109 return classes.toArray(new Class<?>[classes.size()]); 110 } 111 112 /** 113 * Recursive method used to find all classes in a given directory and 114 * subdirectories. 115 * 116 * @param dir base directory 117 * @param pkgname package name for classes found inside the base directory 118 * @param flat scan only one package level, do not dive into subdirectories 119 * @return Classes list 120 * @throws ClassNotFoundException 121 */ 122 private static List<Class<?>> findClasses(File dir, String pkgname, boolean flat) throws ClassNotFoundException { 123 124 List<Class<?>> classes = new ArrayList<Class<?>>(); 125 if (!dir.exists()) { 126 return classes; 127 } 128 129 File[] files = dir.listFiles(); 130 for (File file : files) { 131 if (file.isDirectory() && !flat) { 132 classes.addAll(findClasses(file, pkgname + "." + file.getName(), flat)); 133 } else if (file.getName().endsWith(".class")) { 134 classes.add(Class.forName(pkgname + '.' + file.getName().substring(0, file.getName().length() - 6))); 135 } 136 } 137 138 return classes; 139 } 140}