All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.sikuli.script.ImagePath Maven / Gradle / Ivy

There is a newer version: 2.0.5
Show newest version
/*
 * Copyright 2010-2014, Sikuli.org, sikulix.com
 * Released under the MIT License.
 *
 * added RaiMan 2013
 */
package org.sikuli.script;

import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.URISyntaxException;
import java.net.URL;
import java.security.CodeSource;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import org.sikuli.basics.Debug;
import org.sikuli.basics.FileManager;
import org.sikuli.basics.Settings;

/**
 * runtain the path list of locations, where images will be searched.
 * 
the first entry always is the bundlepath used on the scripting level
* Python import automatically adds a sikuli bundle here
* supported locations:
* - absolute filesystem paths
* - inside jars relative to root level given by a class found on classpath
* - a location in the web given as string starting with http[s]://
* - any location as a valid URL, from where image files can be loaded
*/ public class ImagePath { static RunTime runTime = RunTime.get(); private static final String me = "ImagePath: "; private static final int lvl = 3; private static void log(int level, String message, Object... args) { Debug.logx(level, me + message, args); } /** * represents an imagepath entry */ public static class PathEntry { public URL pathURL; public String path; /** * create a new image path entry * * @param givenName the given path relative or absolute * @param eqivalentURL the evaluated URL */ public PathEntry(String givenName, URL eqivalentURL) { path = FileManager.normalize(givenName); if (eqivalentURL != null) { pathURL = eqivalentURL; } else { pathURL = makePathURL(path, null).pathURL; } log(lvl+1, "PathEntry: %s \nas %s", path, pathURL); } public String getPath() { if (pathURL == null) { return "-- empty --"; } String uPath = pathURL.toExternalForm(); if (isFile() && uPath.startsWith("file:")) { uPath = uPath.substring(5); } return uPath; } public boolean isFile() { if (pathURL == null) { return false; } return "file".equals(pathURL.getProtocol()); } public boolean isJar() { if (pathURL == null) { return false; } return "jar".equals(pathURL.getProtocol()); } public boolean isHTTP() { if (pathURL == null) { return false; } return pathURL.getProtocol().startsWith("http"); } public boolean exists() { if (pathURL == null) { return false; } return new File(getPath()).exists(); } @Override public boolean equals(Object other) { if (pathURL == null) { return false; } if (! (other instanceof PathEntry)) { if (other instanceof URL) { if (pathURL.equals((URL) other)) { return true; } } else if (other instanceof String) { if (isFile()) { return FileManager.pathEquals(pathURL.getPath(), (String) other); } return false; } return false; } if (pathURL.equals(((PathEntry) other).pathURL)) { return true; } return false; } @Override public String toString() { return getPath(); } } private static final List imagePaths = Collections.synchronizedList(new ArrayList()); private static PathEntry bundlePath = null; static { imagePaths.add(null); } /** * get the list of path entries (as PathEntry) * * @return pathentries */ public static List getPaths() { return imagePaths; } private static int getCount() { int count = imagePaths.size(); for (PathEntry path : imagePaths) { if (path == null) { count--; } } return count; } /** * the path list as string array * * @return an array of the file path's currently in the path list */ public static String[] get() { int i = 0; for (PathEntry p : imagePaths) { if (p == null) { continue; } i++; } String[] paths = new String[i]; i = 0; for (PathEntry p : imagePaths) { if (p == null) { continue; } paths[i++] = p.getPath(); } return paths; } /** * print the list of path entries */ public static void dump(int lvl) { log(lvl, "ImagePath has %d entries (valid %d)", imagePaths.size(), getCount()); String bundle = "(taken as bundle path)"; for (PathEntry p : imagePaths) { if (p == null) { log(lvl, "Path: NULL %s", bundle); } else { log(lvl, "Path: given: %s\nis: %s", p.path, p.getPath()); } bundle = ""; } } private static boolean bundleEquals(Object path) { if (bundlePath != null) { return bundlePath.equals(path); } return false; } public static boolean isImageBundled(URL fURL) { if ("file".equals(fURL.getProtocol())) { return bundleEquals(new File(fURL.getPath()).getParent()); } return false; } /** * try to find the given relative image file name on the image path
* starting from entry 0, the first found existence is taken
* absolute file names are checked for existence * * @param fname relative or absolute filename * @return a valid URL or null if not found/exists */ public static URL find(String fname) { URL fURL = null; String proto = ""; fname = FileManager.normalize(fname); if (new File(fname).isAbsolute()) { if (new File(fname).exists()) { fURL = FileManager.makeURL(fname); } else { log(-1, "find: File does not exist: " + fname); } return fURL; } else { if (bundlePath == null) { setBundlePath(null); } for (PathEntry path : getPaths()) { if (path == null) { continue; } proto = path.pathURL.getProtocol(); if ("file".equals(proto)) { fURL = FileManager.makeURL(path.pathURL, fname); if (new File(fURL.getPath()).exists()) { break; } } else if ("jar".equals(proto) || proto.startsWith("http")) { fURL = FileManager.getURLForContentFromURL(path.pathURL, fname); if (fURL != null) { break; } } else { log(-1, "find: URL not supported: " + path.pathURL); return fURL; } } if (fURL == null) { log(-1, "find: not on image path: " + fname); dump(lvl); } return fURL; } } /** * given absolute or relative (searched on image path) file name
* is tried to open as a BufferedReader
* BE AWARE: use br.close() when finished * * @param fname relative or absolute filename * @return the BufferedReader to be used or null if not possible */ public static BufferedReader open(String fname) { log(lvl, "open: " + fname); URL furl = find(fname); if (furl != null) { BufferedReader br = null; try { br = new BufferedReader(new InputStreamReader(furl.openStream())); } catch (IOException ex) { log(-1, "open: %s", ex.getMessage()); return null; } try { br.mark(10); if (br.read() < 0) { br.close(); return null; } br.reset(); return br; } catch (IOException ex) { log(-1, "open: %s", ex.getMessage()); try { br.close(); } catch (IOException ex1) { log(-1, "open: %s", ex1.getMessage()); return null; } return null; } } return null; } /** * create a new PathEntry from the given absolute path name and add it to the * end of the current image path
* for usage with jars see; {@link #add(String, String)} * * @param mainPath relative or absolute path * @return true if successful otherwise false */ public static boolean add(String mainPath) { return add(mainPath, null); } /** * create a new PathEntry from the given net resource folder accessible via HTTP at * end of the current image path
* BE AWARE:
* Files stored in the given remote folder must allow HTTP HEAD-requests (checked)
* redirections are not followed (suppressed) * * @param pathHTTP folder address like siteaddress or siteaddress/folder/subfolder (e.g. download.sikuli.de/images) * @return true if successful otherwise false */ public static boolean addHTTP(String pathHTTP) { try { String proto = "http://"; String protos = "https://"; if (pathHTTP.startsWith(proto) || pathHTTP.startsWith(protos)) { proto = ""; } pathHTTP = FileManager.slashify(pathHTTP, false); URL aURL = new URL(proto + pathHTTP); if (0 != FileManager.isUrlUseabel(new URL(aURL.toString() + "/THIS_FILE_SHOULD_RETURN_404"))) { return false; } PathEntry path = new PathEntry(pathHTTP, aURL); if (hasPath(path) < 0) { log(lvl, "add: %s", path); imagePaths.add(path); } else { log(lvl, "duplicate not added: %s", path); } } catch (Exception ex) { log (-1, "addHTTP: not possible: %s\n%s", pathHTTP, ex); return false; } return true; } public static boolean removeHTTP(String pathHTTP) { try { String proto = "http://"; String protos = "https://"; if (pathHTTP.startsWith(proto) || pathHTTP.startsWith(protos)) { proto = ""; } pathHTTP = FileManager.slashify(pathHTTP, false); return remove(new URL(proto + pathHTTP)); } catch (Exception ex) { log (-1, "removeHTTP: not possible: %s\n%s", pathHTTP, ex); return false; } } /** * create a new PathEntry from the given absolute path name and add it to the * end of the current image path
* for images stored in jars:
* Set the primary image path to the top folder level of a jar based on the * given class name (must be found on class path). When not running from a jar (e.g. running in some IDE) the path will be the path to the compiled classes (for Maven based projects this is target/classes that contains all stuff copied from src/run/resources automatically)
* For situations, where the images cannot be found automatically in the non-jar situation, you * might give an alternative path either absolute or relative to the working folder. * @param mainPath absolute path name or a valid classname optionally followed by /subfolder... * @param altPath alternative image folder, when not running from jar * @return true if successful otherwise false */ public static boolean add(String mainPath, String altPath) { PathEntry path = null; File fPath = new File(mainPath); if (!fPath.isAbsolute() && mainPath.contains(":")) { return addHTTP(mainPath); } path = makePathURL(mainPath, altPath); if (path != null) { if (hasPath(path) < 0) { log(lvl, "add: %s", path); imagePaths.add(path); } else { log(lvl, "duplicate not added: %s", path); } return true; } else { log(-1, "add: not valid: %s %s", mainPath, (altPath == null ? "" : " / " + altPath)); } return false; } public static boolean addJar(String fpJar, String fpImage) { URL pathURL = null; if (new File(fpJar).exists()) { if (fpImage == null) { fpImage = ""; } pathURL = FileManager.makeURL(fpJar + "!/" + fpImage, "jar"); add(pathURL); } return true; } private static int hasPath(PathEntry path) { PathEntry pe = imagePaths.get(0); if (imagePaths.size() == 1 && pe == null) { return -1; } if (pe != null && pe.equals(path)) { return 0; } for (PathEntry p : imagePaths.subList(1, imagePaths.size())) { if (p != null && p.equals(path)) { return 1; } } return -1; } /** * add entry to end of list (the given URL is not checked) * * @param pURL a valid URL (not checked) */ public static void add(URL pURL) { imagePaths.add(new PathEntry("__PATH_URL__", pURL)); } /** * remove entry with given path (same as given with add) * * @param path relative or absolute path * @return true on success, false otherwise */ public static boolean remove(String path) { File fPath = new File(path); if (!fPath.isAbsolute() && path.contains(":")) { return removeHTTP(path); } return remove(makePathURL(FileManager.normalize(path), null).pathURL); } /** * remove entry with given URL
* bundlepath (entry 0) cannot be removed * loaded images are removed from cache * * @param pURL a valid URL (not checked) * @return true on success, false ozherwise */ private static boolean remove(URL pURL) { if (bundleEquals(pURL)) { Image.purge(pURL); bundlePath = null; Settings.BundlePath = null; imagePaths.set(0, null); } Iterator it = imagePaths.subList(1, imagePaths.size()).iterator(); PathEntry p, p0; p0 = imagePaths.get(0); while (it.hasNext()) { p = it.next(); if (!p.equals(pURL)) { continue; } it.remove(); Image.purge(p.pathURL); } return true; } /** * empty path list and add given path as first entry * Image cache is cleared completely * * @param path absolute path * @return true on success, false otherwise */ public static boolean reset(String path) { if (bundleEquals(path)) { return true; } reset(); return setBundlePath(path); } /** * empty path list and keep bundlePath (entry 0)
* Image cache is cleared completely * convenience for the scripting level * @return true */ public static boolean reset() { log(lvl, "reset"); if (imagePaths.isEmpty()) { return false; } for (PathEntry p : imagePaths) { if (p == null) { continue; } Image.purge(p.pathURL); } PathEntry bp = imagePaths.get(0); imagePaths.clear(); imagePaths.add(bp); return true; } /** * the given path replaces bundlepath (entry 0) * and Settings.bundlePath is set to given path * * @param bPath an absolute file path * @return true on success, false otherwise */ public static boolean setBundlePath(String bPath) { PathEntry path = null; if (bPath == null) { // called on first find, if bundlepath still null path = makePathURL(FileManager.normalizeAbsolute(Settings.BundlePath, false), null); } else { path = makePathURL(FileManager.normalizeAbsolute(bPath, false), null); } if (path != null && path.isFile()) { if (bundleEquals(path)) { return true; } Image.purge(bundlePath); if (path.exists()) { imagePaths.set(0, path); Settings.BundlePath = path.getPath(); bundlePath = path; log(lvl, "new BundlePath:\n%s", path); return true; } } if (getCount() ==0) { String wf = System.getProperty("user.dir"); log(-1, "setBundlePath: invalid BundlePath: %s \nusing working folder: %s", bPath, wf); if (!new File(wf).exists()) { log(-1, "setBundlePath: Fatal error: working folder does not exist --- terminating"); System.exit(1); } return setBundlePath(wf); } return true; } /** * no trailing path separator * @return the current bundle path (might be the fallback working folder) */ public static String getBundlePath() { if (bundlePath == null) { setBundlePath(null); } return new File(FileManager.slashify(bundlePath.getPath(), false)).getAbsolutePath(); } /** * no trailing path separator * @return the current bundle path (might be the fallback working folder) */ public static String getBundlePathSet() { if (bundlePath == null) { return null; } return new File(FileManager.slashify(bundlePath.getPath(), false)).getAbsolutePath(); } /** * no trailing path separator * @return the current bundle path (might be the fallback working folder) */ public static String getBundleFolder() { if (bundlePath == null) { setBundlePath(null); } return new File(FileManager.slashify(bundlePath.getPath(), true)).getAbsolutePath(); } private static PathEntry makePathURL(String fpMainPath, String fpAltPath) { if (fpMainPath == null || fpMainPath.isEmpty()) { return null; } URL pathURL = null; File fPath = new File(FileManager.normalizeAbsolute(fpMainPath, false)); if (fPath.exists()) { pathURL = FileManager.makeURL(fPath.getAbsolutePath()); } else { if (fpMainPath.contains("\\")) { return null; } Class cls = null; String klassName; String fpSubPath = ""; int n = fpMainPath.indexOf("/"); if (n > 0) { klassName = fpMainPath.substring(0, n); if (n < fpMainPath.length() - 2) { fpSubPath = fpMainPath.substring(n + 1); } } else { klassName = fpMainPath; } try { cls = Class.forName(klassName); } catch (ClassNotFoundException ex) { log(-1,"add: class %s not found on classpath.", klassName); } if (cls != null) { CodeSource codeSrc = cls.getProtectionDomain().getCodeSource(); if (codeSrc != null && codeSrc.getLocation() != null) { URL jarURL = codeSrc.getLocation(); if (runTime.runningWinApp || jarURL.getPath().endsWith(".jar")) { pathURL = FileManager.makeURL(jarURL.toString() + "!/" + fpSubPath, "jar"); } else { if (fpAltPath == null || fpAltPath.isEmpty()) { fpAltPath = jarURL.getPath(); } if (new File(FileManager.normalizeAbsolute(fpAltPath, false), fpSubPath).exists()) { File fAltPath = new File(FileManager.normalizeAbsolute(fpAltPath, false), fpSubPath); pathURL = FileManager.makeURL(fAltPath.getPath()); } } } } } if (pathURL != null) { return new PathEntry(fpMainPath, pathURL); } return null; } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy