package divconq.hub; import java.nio.file.Files; import java.nio.file.Path; import java.util.ArrayList; import java.util.Collection; import java.util.List; import divconq.filestore.CommonPath; import divconq.io.CacheFile; import divconq.io.LocalFileStore; import divconq.lang.op.OperationResult; import divconq.log.Logger; import divconq.xml.XElement; public class HubPackages { protected LocalFileStore packagefilestore = null; protected List<HubPackage> packages = new ArrayList<>(); protected List<HubPackage> reversepackages = new ArrayList<>(); public List<HubPackage> getPackages() { return this.packages; } public List<HubPackage> getReversePackages() { return this.reversepackages; } public LocalFileStore getPackageFileStore() { return this.packagefilestore; } public void load(XElement cel) { for (XElement pack : cel.selectAll("Packages/Package")) { HubPackage p = new HubPackage(pack); this.packages.add(p); this.reversepackages.add(0, p); } } /** * Get a reference to a library file (typically a JAR) for this Project. * * @param filename name of the JAR, path relative to the lib/ folder * @return File reference if found, if not error messages in FuncResult * / public FuncResult<File> getLibrary(String filename -- pass in list ) { FuncResult<File> res = new FuncResult<File>(); for (HubPackage rcomponent : this.reversepackages) { File f = new File("./packages/" + rcomponent.getName() + "/lib/" + filename); if (f.exists()) { res.setResult(f); return res; } } res.errorTr(200, "./lib/" + filename); return res; } */ // return the path to the first file that matches, if any, in the package list public Path lookupPath(String path) { return this.lookupPath(this.reversepackages, path); } public Path lookupPath(List<HubPackage> packages, String path) { if (Logger.isDebug()) Logger.debug("lookup path: " + path + " in " + (packages != null ? packages.size() : "[missing packages]")); for (HubPackage rcomponent : packages) { if (Logger.isDebug()) Logger.debug("checking: " + path + " in " + rcomponent.getName()); Path rpath = this.packagefilestore.resolvePath("/" + rcomponent.getName() + path); if (Files.exists(rpath)) return rpath; } if (Logger.isDebug()) Logger.debug("lookup path: " + path + " not found"); return null; } public Path lookupPath(Path path) { return this.lookupPath(this.reversepackages, path); } // only works with relative paths public Path lookupPath(List<HubPackage> packages, Path path) { if (path.isAbsolute()) return null; for (HubPackage rcomponent : packages) { Path rpath = this.packagefilestore.resolvePath("/" + rcomponent.getName()).resolve(path).normalize().toAbsolutePath(); if (Files.exists(rpath)) return rpath; } return null; } public Path lookupPath(CommonPath path) { return this.lookupPath(this.reversepackages, path); } public Path lookupPath(List<HubPackage> packages, CommonPath path) { for (HubPackage rcomponent : packages) { Path rpath = this.packagefilestore.resolvePath("/" + rcomponent.getName() + path); if (Files.exists(rpath)) return rpath; } return null; } // use CacheFile once and then let go, call this every time you need it or you may be holding on to stale content public CacheFile cacheLookupPath(String path) { return this.cacheLookupPath(this.reversepackages, path); } // use CacheFile once and then let go, call this every time you need it or you may be holding on to stale content public CacheFile cacheLookupPath(List<HubPackage> packages, String path) { if (Logger.isDebug()) Logger.debug("cache lookup path: " + path + " in " + (packages != null ? packages.size() : "[missing packages]")); Path rpath = this.lookupPath(packages, path); if (Logger.isDebug()) Logger.debug("cache lookup path: " + path + " got " + rpath + " - " + this.packagefilestore); if (rpath != null) return this.packagefilestore.cacheResolvePath(rpath); if (Logger.isDebug()) Logger.debug("cache lookup path: " + path + " no match "); return null; } // use CacheFile once and then let go, call this every time you need it or you may be holding on to stale content public CacheFile cacheLookupPath(Path path) { return this.cacheLookupPath(this.reversepackages, path); } // use CacheFile once and then let go, call this every time you need it or you may be holding on to stale content public CacheFile cacheLookupPath(List<HubPackage> packages, Path path) { Path rpath = this.lookupPath(packages, path); if (rpath != null) return this.packagefilestore.cacheResolvePath(rpath); return null; } // use CacheFile once and then let go, call this every time you need it or you may be holding on to stale content public CacheFile cacheLookupPath(CommonPath path) { return this.cacheLookupPath(this.reversepackages, path); } // use CacheFile once and then let go, call this every time you need it or you may be holding on to stale content public CacheFile cacheLookupPath(List<HubPackage> packages, CommonPath path) { Path rpath = this.lookupPath(packages, path); if (rpath != null) return this.packagefilestore.cacheResolvePath(rpath); return null; } public boolean cacheHas(String path) { for (HubPackage rcomponent : packages) { boolean file = this.packagefilestore.cacheHas("/" + rcomponent.getName() + "/" + path); if (file) return true; } return false; } // build a subset of the reverse package list from a list of package names // this will give the order in which to lookup stuff for package files public List<HubPackage> buildLookupList(Collection<String> packagenames) { List<HubPackage> res = new ArrayList<>(); for (HubPackage pkg : this.reversepackages) { for (String pname : packagenames) { if (pkg.getName().equals(pname)) { res.add(pkg); break; } } } return res; } public void init(OperationResult or, XElement config) { if (config == null) config = new XElement("PackageFileStore"); this.packagefilestore = new LocalFileStore(); this.packagefilestore.start(or, config); /* this.packagefilestore.register(new FuncCallback<FileStoreEvent>() { @Override public void callback() { // --- TODO //System.out.println("TODO tell all domains to reload"); } }); */ } public void stop(OperationResult or) { this.packagefilestore.stop(or); } }