Java tutorial
/* * This file is part of experimaestro. * Copyright (c) 2012 B. Piwowarski <benjamin@bpiwowar.net> * * experimaestro is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * experimaestro is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with experimaestro. If not, see <http://www.gnu.org/licenses/>. */ package sf.net.experimaestro.manager.js; import org.apache.commons.vfs2.FileDepthSelector; import org.apache.commons.vfs2.FileFilterSelector; import org.apache.commons.vfs2.FileObject; import org.apache.commons.vfs2.FileSystemException; import org.mozilla.javascript.Context; import org.mozilla.javascript.NativeArray; import org.mozilla.javascript.Wrapper; import sf.net.experimaestro.manager.json.Json; import sf.net.experimaestro.manager.json.JsonArray; import sf.net.experimaestro.manager.json.JsonFileObject; import sf.net.experimaestro.scheduler.Scheduler; import sf.net.experimaestro.utils.log.Logger; import java.io.*; import java.util.List; import java.util.regex.Pattern; /** * @author B. Piwowarski <benjamin@bpiwowar.net> * @date 26/11/12 */ public class JSFileObject extends JSBaseObject implements Wrapper { public static final String JSCLASSNAME = "FileObject"; final static Logger LOGGER = Logger.getLogger(); private FileObject file; public JSFileObject() { } @JSFunction public JSFileObject(FileObject file) { this.file = file; } @JSFunction public JSFileObject(String path) throws FileSystemException { this.file = Scheduler.getVFSManager().resolveFile(path); } @Override @JSFunction("toString") public String toString() { return file == null ? "[null]" : file.toString(); } @JSFunction("toSource") public String toSource() { return String.format("new FileObject(%s)", file.toString()); } @JSHelp(value = "Get the parent file object") @JSFunction("get_parent") public JSFileObject getParent() throws FileSystemException { return get_ancestor(1); } @JSFunction("resolve") public JSFileObject resolve(String path) throws FileSystemException { return new JSFileObject(file.resolveFile(path)); } @JSHelp(value = "Get the n<sup>th</sup> ancestor of this file object", arguments = @JSArguments(@JSArgument(type = "Integer", name = "levels"))) @JSFunction("get_ancestor") public JSFileObject get_ancestor(int level) throws FileSystemException { if (level < 0) throw new IllegalArgumentException("Level is negative (" + level + ")"); FileObject ancestor = this.file; while (--level >= 0) ancestor = ancestor.getParent(); return new JSFileObject(ancestor); } @JSFunction("path") @JSHelp(value = "Returns a file object corresponding to the path given in the arguments. " + "Each name given corresponds to a new path component starting from this file object.", arguments = @JSArguments({ @JSArgument(type = "String", name = "name"), @JSArgument(name = "...") })) public JSFileObject path(Object... args) throws FileSystemException { FileObject current = file; for (int i = 0; i < args.length; i++) { current = path(current, i, args[i]); } return new JSFileObject(current); } private FileObject path(FileObject current, int i, Object arg) throws FileSystemException { if (arg == null) throw new IllegalArgumentException(String.format("Undefined element (index %d) in path", i)); if (arg instanceof NativeArray) return path(current, (NativeArray) arg); if (arg instanceof JSJson) { Json json = ((JSJson) arg).getJson(); if (json instanceof JsonArray) return path(current, (JsonArray) json); } String name = Context.toString(arg); current = current.resolveFile(name); return current; } private FileObject path(FileObject current, List array) throws FileSystemException { for (int i = 0; i < array.size(); i++) { Object value = array.get(i); current = path(current, i, value); } return current; } @JSFunction("mkdirs") @JSHelp("Creates this folder, if it does not exist. Also creates any ancestor\n" + "folders which do not exist. This method does nothing if the folder\n" + "already exists.") public void mkdirs() throws FileSystemException { file.createFolder(); } @JSFunction("exists") public boolean exists() throws FileSystemException { return file.exists(); } @JSFunction("get_size") public long get_size() throws FileSystemException { return file.getContent().getSize(); } @JSFunction("add_extension") @JSHelp("Adds an extension to the current filename") public Object add_extension(String extension) throws FileSystemException { return file.getParent().resolveFile(file.getName().getBaseName() + extension); } @JSFunction @JSHelp("Removes extension to the current filename") public Object remove_extension(String extension) throws FileSystemException { String baseName = file.getName().getBaseName(); if (baseName.endsWith(extension)) baseName = baseName.substring(0, baseName.length() - extension.length()); return file.getParent().resolveFile(baseName); } @JSFunction @JSHelp("Find all the matching files within this folder") public JSJson find_matching_files( @JSArgument(name = "regexp", type = "String", help = "The regular expression") String regexp) throws FileSystemException { final Pattern pattern = Pattern.compile(regexp); final JsonArray array = new JsonArray(); FileObject[] files = file.findFiles(new FileFilterSelector(fileSelectInfo -> { LOGGER.info("Looking at %s", fileSelectInfo.getFile().getName()); return pattern.matcher(fileSelectInfo.getFile().getName().getBaseName()).matches(); })); for (FileObject file : files) { array.add(new JsonFileObject(file)); } return new JSJson(array); } @JSFunction public void copy_to(@JSArgument(name = "destination") JSFileObject destination) throws FileSystemException { destination.file.copyFrom(file, new FileDepthSelector(0, 0)); } @Override public Object unwrap() { return file; } @JSFunction public PrintWriter output_stream() throws FileSystemException { final OutputStream output = file.getContent().getOutputStream(); final PrintWriter writer = new MyPrintWriter(xpm(), output); return writer; } @JSFunction public BufferedReader input_stream() throws FileSystemException { final BufferedReader reader = new BufferedReader( new MyInputStreamReader(xpm(), file.getContent().getInputStream())); return reader; } public FileObject getFile() { return file; } @JSFunction("get_path") @JSHelp("Get the file path, ignoring the file scheme") public String get_path() { return file.getName().getPath(); } static class MyPrintWriter extends PrintWriter { final XPMObject xpm; public MyPrintWriter(XPMObject xpm, OutputStream out) { super(out); this.xpm = xpm; xpm.register(this); } @Override public void close() { super.close(); xpm.unregister(this); } } static class MyInputStreamReader extends InputStreamReader { final XPMObject xpm; public MyInputStreamReader(XPMObject xpm, InputStream in) { super(in); this.xpm = xpm; xpm.register(this); } @Override public void close() throws IOException { super.close(); xpm.unregister(this); } } }