Java tutorial
package de.alexkamp.sandbox; /** * This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. * * If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/. */ import com.fasterxml.jackson.core.JsonFactory; import de.alexkamp.sandbox.model.Mount; import de.alexkamp.sandbox.model.SandboxData; import java.io.File; import java.io.IOException; import java.nio.file.*; import java.nio.file.attribute.BasicFileAttributes; import java.util.concurrent.atomic.AtomicInteger; /** * A factory to create sandboxes. * * Created by akampmann on 2/8/15. */ public class ChrootSandboxFactory implements SandboxFactory { private final JsonFactory factory = new JsonFactory(); private final String host; private final int port; private final File workDir; public ChrootSandboxFactory(String host, int port, File workDir) { this.host = host; this.port = port; this.workDir = workDir; if (!workDir.exists()) { if (!workDir.mkdirs()) { throw new SandboxException("Could not create workDir: " + workDir.getAbsolutePath()); } } } @Override public Sandbox start(SandboxData data) { return new ChrootSandbox(factory, host, port, data); } @Override public SandboxData copyAsSandbox(String identifier, File baseDir) { try { // create the copy dir File copyDir = new File(workDir, identifier); if (copyDir.exists()) { throw new SandboxException("A sandbox named \"" + identifier + "\" already exists."); } // copy all files SandboxUtils.copyDirectory(baseDir, copyDir); // and return the sandbox return new SandboxData(this, identifier, copyDir); } catch (IOException ex) { throw new SandboxException(ex); } } @Override public SandboxData newSandboxData(String identifier) { return new SandboxData(this, identifier, new File(workDir, identifier)); } @Override public void deleteSandbox(final SandboxData sandbox) { File copyDir = sandbox.getBaseDir(); try { final AtomicInteger depth = new AtomicInteger(0); Files.walkFileTree(copyDir.toPath(), new FileVisitor<Path>() { @Override public FileVisitResult preVisitDirectory(Path path, BasicFileAttributes basicFileAttributes) throws IOException { int d = depth.getAndIncrement(); // see whether the mounts are gone if (1 == d) { for (Mount m : sandbox) { if (path.endsWith(m.getMountPoint().substring(1))) { if (0 != path.toFile().listFiles().length) { throw new IllegalArgumentException( path.getFileName() + " has not been unmounted."); } } } } return FileVisitResult.CONTINUE; } @Override public FileVisitResult visitFile(Path path, BasicFileAttributes basicFileAttributes) throws IOException { Files.delete(path); return FileVisitResult.CONTINUE; } @Override public FileVisitResult visitFileFailed(Path path, IOException e) throws IOException { return FileVisitResult.CONTINUE; } @Override public FileVisitResult postVisitDirectory(Path path, IOException e) throws IOException { Files.delete(path); depth.decrementAndGet(); return FileVisitResult.CONTINUE; } }); } catch (IOException e) { throw new SandboxException(e); } } }