diff --git a/tensor-flow-manager/src/main/java/org/bioimageanalysis/icy/system/PlatformDetection.java b/tensor-flow-manager/src/main/java/org/bioimageanalysis/icy/system/PlatformDetection.java index 9752379a483d67663a40d71919dac0e2f933bebd..f1af76dced61afaf0d53a629c4bf3df3ef52f0c0 100644 --- a/tensor-flow-manager/src/main/java/org/bioimageanalysis/icy/system/PlatformDetection.java +++ b/tensor-flow-manager/src/main/java/org/bioimageanalysis/icy/system/PlatformDetection.java @@ -1,40 +1,66 @@ package org.bioimageanalysis.icy.system; +import java.util.Collections; import java.util.HashMap; import java.util.Map; import org.apache.commons.lang.SystemUtils; +/** + * Represents the detected platform in a given system. When a new instance is created it is assigned the local detected platform but it can be changed using the + * available setters. + * + * @author Daniel Felipe Gonzalez Obando + */ public class PlatformDetection { + public static final String OS_WINDOWS = "windows"; + public static final String OS_OSX = "macosx"; + public static final String OS_SOLARIS = "solaris"; + public static final String OS_LINUX = "linux"; + public static final String ARCH_PPC = "ppc"; + public static final String ARCH_X86_32 = "x86"; + public static final String ARCH_X86_64 = "x86_64"; + public static final Map<String, String> archMap; + + static + { + Map<String, String> architectures = new HashMap<>(); + architectures.put("x86", ARCH_X86_32); + architectures.put("i386", ARCH_X86_32); + architectures.put("i486", ARCH_X86_32); + architectures.put("i586", ARCH_X86_32); + architectures.put("i686", ARCH_X86_32); + architectures.put("x86_64", ARCH_X86_64); + architectures.put("amd64", ARCH_X86_64); + architectures.put("powerpc", ARCH_PPC); + archMap = Collections.unmodifiableMap(architectures); + } + private String os; private String arch; - public static String OS_WINDOWS = "windows"; - public static String OS_OSX = "macosx"; - public static String OS_SOLARIS = "solaris"; - public static String OS_LINUX = "linux"; - public static String ARCH_PPC = "ppc"; - public static String ARCH_X86_32 = "x86"; - public static String ARCH_X86_64 = "x86_64"; + /** + * Creates a platform detection using the local platform. + */ public PlatformDetection() { // resolve OS if (SystemUtils.IS_OS_WINDOWS) { - this.os = OS_WINDOWS; + this.setOs(OS_WINDOWS); } else if (SystemUtils.IS_OS_MAC_OSX) { - this.os = OS_OSX; + this.setOs(OS_OSX); } else if (SystemUtils.IS_OS_SOLARIS) { - this.os = OS_SOLARIS; + this.setOs(OS_SOLARIS); } else if (SystemUtils.IS_OS_LINUX) { - this.os = OS_LINUX; + this.setOs(OS_LINUX); } else { @@ -42,42 +68,52 @@ public class PlatformDetection } // resolve architecture - Map<String, String> archMap = new HashMap<String, String>(); - archMap.put("x86", ARCH_X86_32); - archMap.put("i386", ARCH_X86_32); - archMap.put("i486", ARCH_X86_32); - archMap.put("i586", ARCH_X86_32); - archMap.put("i686", ARCH_X86_32); - archMap.put("x86_64", ARCH_X86_64); - archMap.put("amd64", ARCH_X86_64); - archMap.put("powerpc", ARCH_PPC); - this.arch = archMap.get(SystemUtils.OS_ARCH); + this.setArch(archMap.get(SystemUtils.OS_ARCH)); if (this.arch == null) { throw new IllegalArgumentException("Unknown architecture " + SystemUtils.OS_ARCH); } } + /** + * @return The operating system of the platform. e.g. windows, linux, macosx, etc. + */ public String getOs() { return os; } + /** + * The Operating System of this detection. + * + * @param os + * The operating system to be assigned. + */ + public void setOs(String os) + { + this.os = os; + } + + /** + * @return The system architecture. e.g. x86, x86_64, amd64, etc. + */ public String getArch() { return arch; } + /** + * Sets the system architecture of this detection. + * + * @param arch + * The system architecture to be assigned. + */ public void setArch(String arch) { this.arch = arch; } - public void setOs(String os) - { - this.os = os; - } - + @Override public String toString() { diff --git a/tensor-flow-manager/src/main/java/org/bioimageanalysis/icy/tensorflow/versionmanager/loading/LibraryLoadingStatus.java b/tensor-flow-manager/src/main/java/org/bioimageanalysis/icy/tensorflow/versionmanager/loading/LibraryLoadingStatus.java index db76970d0344715901655b3510e5076e80f3724c..9b267a06505d63b08aa67fd406c053806415007a 100644 --- a/tensor-flow-manager/src/main/java/org/bioimageanalysis/icy/tensorflow/versionmanager/loading/LibraryLoadingStatus.java +++ b/tensor-flow-manager/src/main/java/org/bioimageanalysis/icy/tensorflow/versionmanager/loading/LibraryLoadingStatus.java @@ -2,6 +2,11 @@ package org.bioimageanalysis.icy.tensorflow.versionmanager.loading; import org.bioimageanalysis.icy.tensorflow.versionmanager.version.TensorFlowVersion; +/** + * The loading status of the TensorFlow library on the system. By default there are four status prototypes: loaded, alreadyLoaded, notLoaded, and errorLoading. + * + * @author Daniel Felipe Gonzalez Obando + */ public class LibraryLoadingStatus { public static final String LOADED = "Loaded"; @@ -9,21 +14,54 @@ public class LibraryLoadingStatus public static final String NOT_LOADED = "Not loaded"; public static final String ERROR_LOADING = "Error loading"; + /** + * Creates a new status instance indicating the targetVersion has been correctly loaded. + * + * @param targetVersion + * The TensorFlow version associated to the status. + * @return The status instance. + */ public static LibraryLoadingStatus loaded(TensorFlowVersion targetVersion) { return new LibraryLoadingStatus(LOADED, targetVersion, targetVersion); } + /** + * Creates a new status instance indicating a version has previously been loaded. + * + * @param targetVersion + * The target TensorFlow version. + * @param loadedVersion + * The loaded TensorFlow version. + * @return The status instance. + */ public static LibraryLoadingStatus alreadyLoaded(TensorFlowVersion targetVersion, TensorFlowVersion loadedVersion) { return new LibraryLoadingStatus(ALREADY_LOADED, targetVersion, loadedVersion); } + /** + * Creates a new status instance indicating no version has been loaded. + * + * @return The status instance. + */ public static LibraryLoadingStatus notLoaded() { return new LibraryLoadingStatus(NOT_LOADED, null, null); } + /** + * Creates a new status instance indicating that a version has not correctly been loaded. + * + * @param targetVersion + * The target TensorFlow version. + * @param loadedVersion + * The loaded TensorFlow version. + * @param errorMessage + * The error associated to the status. + * @return The status instance. + */ + public static LibraryLoadingStatus errorLoading(TensorFlowVersion targetVersion, TensorFlowVersion loadedVersion, String errorMessage) { @@ -35,6 +73,18 @@ public class LibraryLoadingStatus private TensorFlowVersion loadedVersion; private String message; + /** + * Creates a status with the title, target version, loaded version, and a message. + * + * @param status + * The status title. + * @param targetVersion + * The target version. + * @param loadedVersion + * The loaded version. + * @param message + * The message associated to the status. + */ public LibraryLoadingStatus(String status, TensorFlowVersion targetVersion, TensorFlowVersion loadedVersion, String message) { @@ -44,26 +94,48 @@ public class LibraryLoadingStatus this.message = message; } + /** + * Creates a status with the title, target version, loaded version, and an empty message. + * + * @param status + * The status title. + * @param targetVersion + * The target version. + * @param loadedVersion + * The loaded version. + */ public LibraryLoadingStatus(String status, TensorFlowVersion targetVersion, TensorFlowVersion loadedVersion) { this(status, targetVersion, loadedVersion, ""); } + /** + * @return The status title. + */ public String getStatus() { return status; } + /** + * @return The target version associated to this status. + */ public TensorFlowVersion getTargetVersion() { return targetVersion; } + /** + * @return The loaded version associated to this status. + */ public TensorFlowVersion getLoadedVersion() { return loadedVersion; } + /** + * @return The message associated to this status. + */ public String getMessage() { return message; diff --git a/tensor-flow-manager/src/main/java/org/bioimageanalysis/icy/tensorflow/versionmanager/loading/TensorFlowVersionDownloader.java b/tensor-flow-manager/src/main/java/org/bioimageanalysis/icy/tensorflow/versionmanager/loading/TensorFlowVersionDownloader.java index d41cee29bd6c411bd55df91146c0d61324a7bfc8..445bcb6c92e3f05ac8df9c47f7323253b1f33ee8 100644 --- a/tensor-flow-manager/src/main/java/org/bioimageanalysis/icy/tensorflow/versionmanager/loading/TensorFlowVersionDownloader.java +++ b/tensor-flow-manager/src/main/java/org/bioimageanalysis/icy/tensorflow/versionmanager/loading/TensorFlowVersionDownloader.java @@ -18,10 +18,25 @@ import java.util.stream.Collectors; import org.bioimageanalysis.icy.tensorflow.versionmanager.version.TensorFlowVersion; +/** + * Downloader for TensorFlow versions. + * + * @author Daniel Felipe Gonzalez Obando + */ public class TensorFlowVersionDownloader { + /** + * The path where TF libraries are downloaded. + */ private static Path downloadsPath = Paths.get(".", "downloads").toAbsolutePath(); + /** + * Checks if the target TF version is already downloaded locally. + * + * @param targetVersion + * The TF version to be checked + * @return {@code true} if a local version of the target library version already exists in the current system. {@code false} otherwise. + */ public static boolean isDownloaded(TensorFlowVersion targetVersion) { Path versionDirectory = getVersionDirectoryPath(targetVersion); @@ -50,12 +65,30 @@ public class TensorFlowVersionDownloader return false; } + /** + * Retrieves the download path for the given TensorFlow version. + * + * @param targetVersion + * The target TF version. + * @return Download path for target version. + */ private static Path getVersionDirectoryPath(TensorFlowVersion targetVersion) { return downloadsPath.resolve("tensorflow-" + targetVersion.getVersion() + "-" + targetVersion.getOs() + "-" + targetVersion.getMode()).toAbsolutePath(); } + /** + * Takes the filename of the provided URL and resolves it on the provided version directory. + * + * @param versionDirectory + * The version directory path to resolve the local version. + * @param urlString + * The URL of the target file. + * @return The path in the versionDirectory resolving the file in the given URL. + * @throws MalformedURLException + * If the URL cannot be correctly parsed. + */ private static Path toLocalVersionFile(Path versionDirectory, String urlString) throws MalformedURLException { URL url = new URL(urlString); @@ -63,6 +96,15 @@ public class TensorFlowVersionDownloader return versionDirectory.resolve(fileName); } + /** + * Given a target TF version, files related to it are checked to see if they already exist locally or else they are downloaded to the local directory. + * + * @param targetVersion + * The target version to download. + * @return The list of paths for all resources downloaded or already existing in local storage. + * @throws IOException + * If an error occurs while files are checked or downloaded. + */ public static List<Path> download(TensorFlowVersion targetVersion) throws IOException { Path versionDirectory = getVersionDirectoryPath(targetVersion); @@ -113,6 +155,13 @@ public class TensorFlowVersionDownloader return localFilePath; } + /** + * Retrieves the paths of all resources associated to a given version resolved locally. + * + * @param targetVersion + * The target TF version. + * @return List of paths of all resources associated to a given version resolved locally. + */ public static List<Path> getDownloadedFilePaths(TensorFlowVersion targetVersion) { Path versionDirectory = getVersionDirectoryPath(targetVersion); diff --git a/tensor-flow-manager/src/main/java/org/bioimageanalysis/icy/tensorflow/versionmanager/version/AvailableTensorFlowVersions.java b/tensor-flow-manager/src/main/java/org/bioimageanalysis/icy/tensorflow/versionmanager/version/AvailableTensorFlowVersions.java index 383e56eb101b2c16b3e6664f14cb8d31e8949b79..e63a70606b94576e3fbaa24bcf628a2d063fd70f 100644 --- a/tensor-flow-manager/src/main/java/org/bioimageanalysis/icy/tensorflow/versionmanager/version/AvailableTensorFlowVersions.java +++ b/tensor-flow-manager/src/main/java/org/bioimageanalysis/icy/tensorflow/versionmanager/version/AvailableTensorFlowVersions.java @@ -10,12 +10,17 @@ import org.bioimageanalysis.icy.system.PlatformDetection; import com.google.gson.Gson; /** - * Holds the list of available TensorFlow versions. + * Holds the list of available TensorFlow versions read from the JSON file. * * @author Daniel Felipe Gonzalez Obando */ public class AvailableTensorFlowVersions { + /** + * Creates an instance containing only TF versions compatible with the current system. + * + * @return The available versions instance. + */ public static AvailableTensorFlowVersions loadCompatibleOnly() { AvailableTensorFlowVersions availableVersions = load(); @@ -25,6 +30,11 @@ public class AvailableTensorFlowVersions return availableVersions; } + /** + * Loads all available versions from {@code availableTFVersion.json} file. + * + * @return The instance of all available versions. + */ public static AvailableTensorFlowVersions load() { BufferedReader br = new BufferedReader(new InputStreamReader( @@ -36,11 +46,22 @@ public class AvailableTensorFlowVersions private List<TensorFlowVersion> versions; + /** + * Retrieves the list of available TF versions. + * + * @return The list of TF versions in this instance. + */ public List<TensorFlowVersion> getVersions() { return versions; } + /** + * Sets the list of versions available in this instance. + * + * @param versions + * The versions to be available in this instance. + */ public void setVersions(List<TensorFlowVersion> versions) { this.versions = versions; diff --git a/tensor-flow-manager/src/main/java/org/bioimageanalysis/icy/tensorflow/versionmanager/version/TensorFlowVersion.java b/tensor-flow-manager/src/main/java/org/bioimageanalysis/icy/tensorflow/versionmanager/version/TensorFlowVersion.java index 05b2d83f59419d8bfa6ab6db00a0445e1cde80a3..93ca770c401a5b0506195077e729d347ae125612 100644 --- a/tensor-flow-manager/src/main/java/org/bioimageanalysis/icy/tensorflow/versionmanager/version/TensorFlowVersion.java +++ b/tensor-flow-manager/src/main/java/org/bioimageanalysis/icy/tensorflow/versionmanager/version/TensorFlowVersion.java @@ -3,7 +3,7 @@ package org.bioimageanalysis.icy.tensorflow.versionmanager.version; import java.util.List; /** - * An available tensor flow version with its properties and needed artifact urls. + * An available tensor flow version with its properties and needed artifact URLs. * * @author Daniel Felipe Gonzalez Obando */ @@ -15,56 +15,94 @@ public class TensorFlowVersion private String mode; private List<String> jars; + /** + * @return The API version. + */ public String getVersion() { return version; } + /** + * @param version + * The API version + */ public void setVersion(String version) { this.version = version; } + /** + * @return The TensorFlow library version. + */ public String getTensorFlowVersion() { return tensorFlowVersion; } + /** + * @param tensorFlowVersion + * The TensorFlow library version. + */ public void setTensorFlowVersion(String tensorFlowVersion) { this.tensorFlowVersion = tensorFlowVersion; } + /** + * @return The target operating system. + */ public String getOs() { return os; } + /** + * @param os + * The target operating system. + */ public void setOs(String os) { this.os = os; } + /** + * @return The execution mode for this version. + */ public String getMode() { return mode; } + /** + * @param mode + * The execution mode for this version. + */ public void setMode(String mode) { this.mode = mode; } + /** + * @return The list of associated artifacts for this version. + */ public List<String> getJars() { return jars; } + /** + * @param jars + * The list of associated artifacts for this version. + */ public void setJars(List<String> jars) { this.jars = jars; } + /** + * @implNote The string representation is {@code "TensorFlowVersion[version=x, tensorFlowVersion=y, os=z, mode=u, jars=[...]"}. + */ @Override public String toString() { @@ -116,7 +154,5 @@ public class TensorFlowVersion return false; return true; } - - } diff --git a/tensor-flow-manager/src/main/java/plugins/danyfel80/tensorflowmanager/TensorFlowManager.java b/tensor-flow-manager/src/main/java/plugins/danyfel80/tensorflowmanager/TensorFlowManager.java index f24a392d8884fd7239775ae1a8d4d4d6022a1334..6a0517c12e8fdb380367f0018f31cec256755625 100644 --- a/tensor-flow-manager/src/main/java/plugins/danyfel80/tensorflowmanager/TensorFlowManager.java +++ b/tensor-flow-manager/src/main/java/plugins/danyfel80/tensorflowmanager/TensorFlowManager.java @@ -19,6 +19,8 @@ import icy.plugin.abstract_.Plugin; import icy.plugin.interface_.PluginLibrary; /** + * This plugin handles the loading into the JVM of a SINGLE instance of the TensorFlow API for Java. + * * @author Daniel Felipe Gonzalez Obando */ public class TensorFlowManager extends Plugin implements PluginLibrary @@ -117,28 +119,42 @@ public class TensorFlowManager extends Plugin implements PluginLibrary else { String message = "(loaded: " - + ((getLoadedVersion() == null) ? "Unknown" - : getLoadedVersion().getVersion() - + "-" + getLoadedVersion().getOs() + "-" + getLoadedVersion().getMode()) + + ((getLoadedVersion() == null) + ? "Unknown" + : getLoadedVersion().getVersion() + + "-" + getLoadedVersion().getOs() + "-" + getLoadedVersion().getMode()) + ", target: " - + ((targetVersion == null) ? "Unknown" - : targetVersion.getVersion() + "-" + targetVersion.getOs() + "-" - + targetVersion.getMode()) + + ((targetVersion == null) + ? "Unknown" + : targetVersion.getVersion() + "-" + targetVersion.getOs() + "-" + + targetVersion.getMode()) + ")"; throw new IOException("Tried loading a different TensorFlow version " + message); } } } + /** + * Loads jar artifacts to class loader. + * + * @param targetVersion + * Target version to be loaded. + * @param libraryArtifacts + * Path list of all artifacts to be loaded. + * @throws IOException + * If an error occurs while loading artifacts in the class loader. + */ private static void loadLibraryToPluginLoader(TensorFlowVersion targetVersion, List<Path> libraryArtifacts) throws IOException { - // load jar artifacts to class loader + + // All files to be loaded are placed on the tensorflowlibs folder, which is reachable by the PluginLoader Path pluginPath; pluginPath = Paths.get(".", "plugins", "danyfel80", "tensorflowmanager"); Path libJarsPath = pluginPath.resolve("tensorflowlibs"); FileUtil.delete(libJarsPath.toString(), true); Files.createDirectories(libJarsPath); + for (Path downloadPath : libraryArtifacts) { Path targetPath = libJarsPath.resolve(downloadPath.getFileName()); @@ -146,8 +162,10 @@ public class TensorFlowManager extends Plugin implements PluginLibrary Files.copy(downloadPath, targetPath, StandardCopyOption.REPLACE_EXISTING); } + // Reload plugin loader to include copied files. PluginLoader.reload(); + // Invoke the TensorFlow class to load classes in memory. try { Class<?> cl = PluginLoader.loadClass("org.tensorflow.TensorFlow"); @@ -158,6 +176,7 @@ public class TensorFlowManager extends Plugin implements PluginLibrary e.printStackTrace(); } + // Done. loadedVersion = targetVersion; libraryLoaded = true; } diff --git a/tensor-flow-manager/src/main/java/plugins/danyfel80/tensorflowmanager/TensorFlowVersionSelector.java b/tensor-flow-manager/src/main/java/plugins/danyfel80/tensorflowmanager/TensorFlowVersionSelector.java index 35d50844a16c43e17b500dcac04fe242226170c3..df4b9604f2385a701c2140c7a73414417261cd34 100644 --- a/tensor-flow-manager/src/main/java/plugins/danyfel80/tensorflowmanager/TensorFlowVersionSelector.java +++ b/tensor-flow-manager/src/main/java/plugins/danyfel80/tensorflowmanager/TensorFlowVersionSelector.java @@ -43,7 +43,12 @@ public class TensorFlowVersionSelector extends EzPlug implements EzStoppable, Bl v -> "API " + v.getVersion() + "-" + v.getMode() + " for TF " + v.getTensorFlowVersion(), Function.identity())); } - + + /** + * Main routine launching this plugin. + * + * @param args + */ public static void main(String[] args) { Icy.main(args); @@ -64,8 +69,9 @@ public class TensorFlowVersionSelector extends EzPlug implements EzStoppable, Bl public void declareInput(VarList inputMap) { String lastUsedVersion = getLastUsedVersion(); - lastUsedVersion = (!lastUsedVersion.equals("")) ? lastUsedVersion - : versions.keySet().stream().findFirst().orElse(""); + lastUsedVersion = (!lastUsedVersion.equals("")) + ? lastUsedVersion + : versions.keySet().stream().findFirst().orElse(""); varInBlockVersion = new VarString("Library version", lastUsedVersion); }