package ecologylab.bigsemantics.collecting; import java.io.BufferedReader; import java.io.File; import java.io.FileFilter; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FilenameFilter; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.List; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import ecologylab.appframework.EnvironmentGeneric; import ecologylab.appframework.PropertiesAndDirectories; import ecologylab.appframework.SingletonApplicationEnvironment; import ecologylab.bigsemantics.metametadata.MetaMetadataRepositoryFileFormats; import ecologylab.bigsemantics.namesandnums.SemanticsAssetVersions; import ecologylab.generic.Debug; import ecologylab.io.Assets; import ecologylab.io.AssetsRoot; import ecologylab.io.Files; import ecologylab.io.NamedInputStream; import ecologylab.net.ParsedURL; import ecologylab.serialization.formatenums.Format; /** * Locate meta-metadata wrapper repository and open input streams to them. * * @author quyin * */ public class MetaMetadataRepositoryLocator extends Debug { static final Logger logger; private static final String SEMANTICS; private static final String[] DEFAULT_REPOSITORY_LOCATIONS; static { logger = LoggerFactory.getLogger(MetaMetadataRepositoryLocator.class); SEMANTICS = "semantics/"; DEFAULT_REPOSITORY_LOCATIONS = new String[] { "../../BigSemanticsWrapperRepository/BigSemanticsWrappers/repository", "../../MetaMetadataRepository/repository", "../ecologylabSemantics/repository", }; } private boolean useAssetsCache; /** * * @param useAssetsCache * (Used by loading from assets only) */ MetaMetadataRepositoryLocator(boolean useAssetsCache) { this.useAssetsCache = useAssetsCache; } /** * Locate meta-metadata repository files and open input streams to them. It will try the following * places in order: 1) the assets, if app framework is used; 2) default locations; 3) java * resources. * * @param repositoryLocation * the location of the repository. this can be null, in which case the locator will try * to locate the repository automatically. * @param repositoryFormat * @return */ public List<NamedInputStream> locateRepositoryAndOpenStreams(File repositoryLocation, Format repositoryFormat) { List<NamedInputStream> result = new ArrayList<NamedInputStream>(); if (repositoryLocation == null) { // try default locations if (repositoryLocation == null) { repositoryLocation = locateRepositoryByDefaultLocations(); debug("meta-metadata repository located by default location at " + repositoryLocation); } } int n = 0; if (repositoryLocation != null) { debug("tentative meta-metadata repository location: " + repositoryLocation); n = openStreams(result, repositoryLocation, repositoryFormat); } else { // at last, try java resources debug("trying to locate meta-metadata repository as java resources..."); n = locateRepositoryAsJavaResourcesAndOpenStreams(result); } debug(n + " repository file(s) or resource(s) found."); return result; } public static File locateRepositoryByDefaultLocations() { for (String defaultLocation : DEFAULT_REPOSITORY_LOCATIONS) { File possibleRepositoryDir = new File(defaultLocation); if (possibleRepositoryDir.exists() && possibleRepositoryDir.isDirectory()) return possibleRepositoryDir; } return null; } static File locateRepositoryForAndroid() { Class environmentClass; try { environmentClass = Class.forName("android.os.Environment"); if (environmentClass != null) { Method m = environmentClass.getMethod("getExternalStorageDirectory"); File sdCard = (File) m.invoke(null, null); File ecologylabDir = new File(sdCard.getAbsolutePath() + "/Android/data/com.ecologyAndroid.ecoDroidTest/files/"); File mmdrepositoryDir = new File(ecologylabDir + "/mmdrepository/"); return mmdrepositoryDir; } } catch (ClassNotFoundException e) { e.printStackTrace(); } catch (SecurityException e) { e.printStackTrace(); } catch (NoSuchMethodException e) { e.printStackTrace(); } catch (IllegalArgumentException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (InvocationTargetException e) { e.printStackTrace(); } return null; } int locateRepositoryAsJavaResourcesAndOpenStreams(List<NamedInputStream> result) { InputStream repositoryListStream = this.getClass().getResourceAsStream("/repositoryFiles.lst"); BufferedReader br = new BufferedReader(new InputStreamReader(repositoryListStream)); int n = 0; while (true) { String line = null; try { line = br.readLine(); } catch (IOException e) { error("Cannot read repositoryFiles.lst"); e.printStackTrace(); } if (line == null) break; line = line.trim(); if (line.length() > 0) { String repositoryFileResourceName = "/" + line; result.add(new NamedInputStream(repositoryFileResourceName, this.getClass().getResourceAsStream(repositoryFileResourceName))); n++; } } return n; } public static List<File> listRepositoryFiles(File repositoryDir, Format repositoryFormat) { FileFilter fileFilter = MetaMetadataRepositoryFileFormats.getFileFilter(repositoryFormat); assert fileFilter != null; List<File> allFiles = new ArrayList<File>(); List<File> allDirectories = getSubDirectories(repositoryDir); allDirectories.add(repositoryDir); for(int i = 0; i < allDirectories.size(); i++){ addFilesInDirToList(allDirectories.get(i), fileFilter, allFiles); } return allFiles; } private static List<File> getSubDirectories(File rootDirectory){ List<File> subdirectories = new ArrayList<File>(); String[] directories = rootDirectory.list(new FilenameFilter() { @Override public boolean accept(File current, String name) { return new File(current, name).isDirectory(); } }); for(int i = 0; i < directories.length; i++){ File directory = new File(rootDirectory, directories[i]); subdirectories.add(directory); subdirectories.addAll(getSubDirectories(directory)); } return subdirectories; } private static void addFilesInDirToList(File dir, FileFilter filter, List<File> buf) { if (dir == null || !dir.exists()) return; for (File f : dir.listFiles(filter)) buf.add(f); } public int openStreams(List<NamedInputStream> result, File repositoryDir, Format repositoryFormat) { List<File> repoFiles = listRepositoryFiles(repositoryDir, repositoryFormat); for (File file : repoFiles) { try { result.add(new NamedInputStream(file)); } catch (FileNotFoundException e) { Debug.error(MetaMetadataRepositoryLocator.class, "Cannot open input stream for " + file); } } return repoFiles.size(); } }