/** * A JavaScript wrapper for {@linkplain Path} * * @author B. Piwowarski <*****@*****.**> */ @Exposed public class ScriptingList extends WrapperObject<List> { static final Logger LOGGER = Logger.getLogger(); public ScriptingList(List object) { super(object); } @Expose(mode = ExposeMode.PROPERTY, value = "length") int length() { return object.size(); } @Expose(mode = ExposeMode.FIELDS) public Object get(int index) { return object.get(index); } @Expose(context = true) public void sort(JavaScriptContext jcx, NativeFunction f) { LOGGER.debug("Sorting list"); Collections.sort( object, (a, b) -> { final double result = (Double) f.call(jcx.context(), jcx.scope(), null, new Object[] {a, b}); if (result > 0) return 1; if (result < 0) return -1; return 0; }); } }
/** * Delete everything recursively * * @param path */ public static void recursiveDelete(Path path) throws IOException { logger.debug("Deleting %s", path); final Iterator<Path> it = Files.list(path).iterator(); while (it.hasNext()) { final Path entry = it.next(); logger.debug("Considering " + entry); if (Files.isDirectory(entry)) { recursiveDelete(entry); } else { Files.delete(entry); } } // Deleting self Files.delete(path); }
@Expose(context = true) public void sort(JavaScriptContext jcx, NativeFunction f) { LOGGER.debug("Sorting list"); Collections.sort( object, (a, b) -> { final double result = (Double) f.call(jcx.context(), jcx.scope(), null, new Object[] {a, b}); if (result > 0) return 1; if (result < 0) return -1; return 0; }); }
/** * Static methods for files * * @author B. Piwowarski * @date 17/11/2006 */ public class FileSystem { /** A filter for directories */ public static final FileFilter DIRECTORY_FILTER = pathname -> pathname.isDirectory(); /** A filter for files */ public static final FileFilter FILE_FILTER = pathname -> pathname.isFile(); private static final Logger logger = Logger.getLogger(); /** * Get a file filter * * @param extFilter * @param skipRegExp * @return */ public static FileFilter newRegexpFileFilter(final String extFilter, final String skipRegExp) { return new FileFilter() { final Pattern pattern = skipRegExp != null ? Pattern.compile(skipRegExp) : null; public boolean accept(File file) { return (file.getName().endsWith(extFilter) && (pattern == null || !pattern.matcher(file.getName()).find())); } }; } /** * Create a new file object from a list of names * * @param names A list of strings */ public static File createFileFromPath(String... names) { return createFileFromPath(null, names); } /** * Creates a file from a list of strings and a base directory * * @param baseDirectory * @param names * @return */ public static File createFileFromPath(File baseDirectory, String... names) { for (String name : names) if (baseDirectory == null) baseDirectory = new File(name); else baseDirectory = new File(baseDirectory, name); return baseDirectory; } /** * Delete everything recursively * * @param directory The directory to delete */ public static void recursiveDelete(File directory) throws IOException { recursiveDelete(directory.toPath()); } /** * Delete everything recursively * * @param path */ public static void recursiveDelete(Path path) throws IOException { logger.debug("Deleting %s", path); final Iterator<Path> it = Files.list(path).iterator(); while (it.hasNext()) { final Path entry = it.next(); logger.debug("Considering " + entry); if (Files.isDirectory(entry)) { recursiveDelete(entry); } else { Files.delete(entry); } } // Deleting self Files.delete(path); } }
/** Global context when executing a javascript */ public class PythonRunner implements AutoCloseable { private static final Logger LOGGER = Logger.getLogger(); private static Map<String, PythonType> TYPES; private static Map<Class, Constructor> WRAPPERS; private final Map<String, String> environment; private final StaticContext staticContext; private final PythonInterpreter interpreter; private final ScriptContext scriptContext; public PythonRunner( Map<String, String> environment, Repositories repositories, Scheduler scheduler, Hierarchy loggerRepository, String pythonPath, BufferedWriter out, BufferedWriter err) throws Exception { init(); this.staticContext = new StaticContext(scheduler, loggerRepository).repository(repositories); this.environment = environment; final PySystemState systemState = new PySystemState(); interpreter = new PythonInterpreter(null, systemState); for (String path : pythonPath.split(":")) { systemState.path.add(new PyString(path)); } interpreter.setOut(out); interpreter.setErr(err); scriptContext = staticContext.scriptContext(); // XPM module final PyModule xpmModule = new PyModule("xpm", (PyObject) null); systemState.modules.__setitem__("xpm", xpmModule); // Add classes for (PyType type : TYPES.values()) { xpmModule.__setattr__(type.getName(), type); } // Add constants Scripting.forEachConstant( (name, value) -> { xpmModule.__setattr__(name, wrap(value)); }); // Add functions Scripting.forEachFunction( m -> { xpmModule.__setattr__(m.getKey(), new PythonMethod(null, m)); }); // Add Python specific functions for (MethodFunction m : Scripting.getMethodFunctions(PythonFunctions.class)) { xpmModule.__setattr__(m.getKey(), new PythonMethod(null, m)); } // XPM object: wrap properties final XPM xpm = new XPM(); ClassDescription xpmDescription = ClassDescription.analyzeClass(XPM.class); for (Map.Entry<Object, MethodFunction> x : xpmDescription.getMethods().entrySet()) { final Object key = x.getKey(); if (key instanceof String) { xpmModule.__setattr__((String) key, new PythonMethod(xpm, x.getValue())); } else { throw new XPMRuntimeException("Could not handle key ", key); } } // Add properties xpmModule.__setattr__("tasks", wrap(new Tasks())); xpmModule.__setattr__("logger", wrap(new ScriptingLogger("xpm"))); xpmModule.__setattr__("env", wrap(environment)); } /** Gather types, etc. */ public static void init() { if (TYPES == null) { TYPES = new HashMap<>(); WRAPPERS = new HashMap<>(); Scripting.forEachType( Functional.propagate( aClass -> { final PythonType type = new PythonType(aClass); TYPES.put(type.getName(), type); if (WrapperObject.class.isAssignableFrom(aClass)) { final Class<?> wrappedClass = (Class<?>) ((ParameterizedType) TypeToken.of(aClass).getSupertype(WrapperObject.class).getType()) .getActualTypeArguments()[0]; final Constructor constructor = aClass.getConstructor(wrappedClass); WRAPPERS.put(wrappedClass, constructor); } })); } } public static PyObject wrap(Object object) { // Simple case if (object == null) return Py.None; if (object instanceof PyObject) return (PyObject) object; final Class<?> objectClass = object.getClass(); if (object.getClass().isArray()) { final PyList pyList = new PyList(); for (int i = Array.getLength(object); --i >= 0; ) { pyList.add(wrap(Array.get(object, i))); } return pyList; } // Wrapper case // Wrapper case -- go up in the hierarchy for (Map.Entry<Class, Constructor> entry : WRAPPERS.entrySet()) { if (entry.getKey().isAssignableFrom(objectClass)) { try { return new PythonObject(entry.getValue().newInstance(object)); } catch (Exception e) { throw new UnsupportedOperationException( "Could not wrap object of class " + objectClass, e); } } } // Simple types if (object instanceof String) { return new PyString((String) object); } if (object instanceof Boolean) { return new PyBoolean(((Boolean) object).booleanValue()); } if (object instanceof Long) { return new PyLong((long) object); } if (object instanceof Number) { return new PyFloat(((Number) object).doubleValue()); } // Exposed objects final Exposed exposed = objectClass.getAnnotation(Exposed.class); if (exposed != null) { return new PythonObject(object); } // Map entry as tuple if (object instanceof Map.Entry) { Map.Entry entry = (Map.Entry) object; return new PyTuple(wrap(entry.getKey()), wrap(entry.getValue())); } // Entry set if (object instanceof Set) { Set set = (Set) object; final AbstractSet wrappedSet = new AbstractSet() { @Override public Iterator iterator() { return new Iterator() { Iterator iterator = set.iterator(); @Override public boolean hasNext() { return iterator.hasNext(); } @Override public Object next() { return wrap(iterator.next()); } }; } @Override public int size() { return 0; } }; return new PySet(wrappedSet, null); } if (object instanceof Iterator) { return PythonUtils.wrapIterator((Iterator) object); } throw new IllegalArgumentException( format("Cannot wrap class %s into python object", objectClass)); } public static Object unwrap(PyObject arg) { return arg.__tojava__(Object.class); } public static Object[] unwrap(PyObject[] args) { Object[] unwrapped = new Object[args.length]; for (int i = 0; i < args.length; ++i) { unwrapped[i] = unwrap(args[i]); } return unwrapped; } @Override public void close() throws Exception { interpreter.close(); scriptContext.close(); staticContext.close(); } public Object evaluateReader( LocalhostConnector connector, Path locator, FileReader reader, String filename, int lineno, Object security) throws Exception { ScriptContext.get().setCurrentScriptPath(Paths.get(filename)); final PyCode code = interpreter.compile(reader, filename); return interpreter.eval(code); } public Object evaluateString( LocalhostConnector connector, Path locator, String content, String name, int lineno, Object security) throws Exception { final PyCode code = interpreter.compile(content, name); return interpreter.eval(code); } }