/*
* This file is part of VLCJ.
*
* VLCJ is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* VLCJ is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with VLCJ. If not, see <http://www.gnu.org/licenses/>.
*
* Copyright 2009-2016 Caprica Software Limited.
*/
package uk.co.caprica.vlcj.discovery;
import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Base implementation for a component that attempts to locate the libvlc native
* resources.
* <p>
* This implementation looks for libvlc shared libraries by name in pre-defined
* directory locations.
* <p>
* Extra directory names can be provided by implementations of the {@link #getDirectoryNames(List)}
* template method in sub-classes.
* <p>
* If the named native libraries are found in a particular directory, then that
* directory is registered as a native library search path for JNA.
*/
public abstract class AbstractNativeDiscoveryStrategy implements NativeDiscoveryStrategy {
/**
* Log.
*/
private final Logger logger = LoggerFactory.getLogger(AbstractNativeDiscoveryStrategy.class);
/**
* Name of the system environment variable containing the VLC plugin path location.
* <p>
* This is optional, and might not be set.
*/
protected static final String PLUGIN_ENV_NAME = "VLC_PLUGIN_PATH";
@Override
public final String discover() {
logger.debug("discover()");
String result = null;
// Get the list of directories to search
List<String> directoryNames = new ArrayList<String>();
getDirectoryNames(directoryNames);
logger.debug("directoryNames={}", directoryNames);
// Process each declared directory name
for(String directoryName : directoryNames) {
logger.debug("directoryName={}", directoryName);
if(find(directoryName)) {
result = directoryName;
break;
}
}
logger.debug("result={}", result);
return result;
}
/**
* Attempt to match all required files in a particular directory.
* <p>
* The directory is <em>not</em> searched <em>recursively</em>.
*
* @param directoryName name of the directory to search
* @return <code>true</code> if all required files were found; <code>false</code> otherwise
*/
private boolean find(String directoryName) {
File dir = new File(directoryName);
File[] files = dir.listFiles();
if(files != null) {
Pattern[] patternsToMatch = getFilenamePatterns();
int matchedCount = 0;
for(File file : files) {
for(Pattern pattern : patternsToMatch) {
Matcher matcher = pattern.matcher(file.getName());
if(matcher.matches()) {
logger.debug("Matched '{}' in '{}'", file.getName(), directoryName);
matchedCount++ ;
if(matchedCount == patternsToMatch.length) {
logger.debug("Matched all required files");
return true;
}
}
}
}
}
logger.debug("Failed to matched all required files");
return false;
}
/**
* Get the system search path components.
*
* @return path components
*/
protected final List<String> getSystemPath() {
String path = System.getenv("PATH");
if(path != null) {
String[] paths = path.split(File.pathSeparator);
return Arrays.asList(paths);
}
else {
return Collections.emptyList();
}
}
/**
* Get the filename patterns to search for.
*
* @return filename patterns
*/
protected abstract Pattern[] getFilenamePatterns();
/**
* Get the names of the directories that should be searched.
*
* @return collection of directories to search
*/
protected abstract void getDirectoryNames(List<String> directoryNames);
@Override
public void onFound(String path) {
// Default implementation does nothing
}
}