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}