001 package com.github.sarxos.webcam;
002
003 import java.io.File;
004 import java.io.IOException;
005 import java.net.URL;
006 import java.util.ArrayList;
007 import java.util.Enumeration;
008 import java.util.List;
009
010 import org.slf4j.Logger;
011 import org.slf4j.LoggerFactory;
012
013
014 public 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 }