package org.simantics.acorn.internal; import java.io.File; import java.io.IOException; import java.nio.file.DirectoryStream; import java.nio.file.FileVisitOption; import java.nio.file.FileVisitResult; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.SimpleFileVisitor; import java.nio.file.attribute.BasicFileAttributes; import java.util.EnumSet; import java.util.Properties; import org.simantics.acorn.GraphClientImpl2; import org.simantics.db.Database; import org.simantics.db.DatabaseUserAgent; import org.simantics.db.ServiceLocator; import org.simantics.db.common.utils.Logger; import org.simantics.db.server.ProCoreException; /** * @author Tuukka Lehtonen */ public class AcornDatabase implements Database { private final Path folder; private DatabaseUserAgent userAgent; public AcornDatabase(Path folder) { this.folder = folder; } @Override public DatabaseUserAgent getUserAgent() { return userAgent; } @Override public void setUserAgent(DatabaseUserAgent dbUserAgent) { userAgent = dbUserAgent; } @Override public Status getStatus() { return Status.Local; } @Override public File getFolder() { return folder.toFile(); } @Override public boolean isFolderOk() { return isFolderOk(folder.toFile()); } @Override public boolean isFolderOk(File aFolder) { if (!aFolder.isDirectory()) return false; return true; } @Override public boolean isFolderEmpty() { return isFolderEmpty(folder.toFile()); } @Override public boolean isFolderEmpty(File aFolder) { Path path = aFolder.toPath(); if (!Files.isDirectory(path)) return false; try (DirectoryStream folderStream = Files.newDirectoryStream(path)) { return !folderStream.iterator().hasNext(); } catch (IOException e) { Logger.defaultLogError("Failed to open folder stream. folder=" + path, e); return false; } } @Override public void initFolder(Properties properties) throws ProCoreException { try { Files.createDirectories(folder); } catch (IOException e) { throw new ProCoreException(e); } } @Override public void deleteFiles() throws ProCoreException { // TODO: somehow check that the acorn client is not active. deleteTree(folder); } @Override public void start() throws ProCoreException { } @Override public boolean isRunning() throws ProCoreException { return true; } @Override public boolean tryToStop() throws ProCoreException { return true; // throw new UnsupportedOperationException(); } @Override public void connect() throws ProCoreException { } @Override public boolean isConnected() throws ProCoreException { return true; } @Override public String execute(String command) throws ProCoreException { throw new UnsupportedOperationException("execute(" + command + ")"); } @Override public void disconnect() throws ProCoreException { } @Override public void clone(File to, int revision, boolean saveHistory) throws ProCoreException { // TODO: implement throw new UnsupportedOperationException(); } @Override public Path createFromChangeSets(int revision) throws ProCoreException { // TODO: implement throw new UnsupportedOperationException(); } @Override public void deleteGuard() throws ProCoreException { // TODO: implement throw new UnsupportedOperationException(); } @Override public Path dumpChangeSets() throws ProCoreException { // TODO: implement throw new UnsupportedOperationException(); } @Override public void purgeDatabase() throws ProCoreException { // TODO: implement throw new UnsupportedOperationException(); } @Override public long serverGetTailChangeSetId() throws ProCoreException { // "We have it all" // But after purging we don't so beware. // TODO: beware for purge return 1; } @Override public Session newSession(ServiceLocator locator) throws ProCoreException { try { return new GraphClientImpl2(this, folder, locator); } catch (IOException e) { throw new ProCoreException(e); } } @Override public Journal getJournal() throws ProCoreException { // TODO: implement throw new UnsupportedOperationException(); } private static void deleteTree(Path path) throws ProCoreException { if (!Files.exists(path)) return; class Visitor extends SimpleFileVisitor { @Override public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException { try { Files.delete(file); } catch (IOException ioe) { ioe.printStackTrace(); throw ioe; } return FileVisitResult.CONTINUE; } @Override public FileVisitResult postVisitDirectory(Path dir, IOException e) throws IOException { if (e == null) { try { Files.delete(dir); } catch (IOException ioe) { ioe.printStackTrace(); throw ioe; } return FileVisitResult.CONTINUE; } throw e; } } try { Visitor v = new Visitor(); EnumSet opts = EnumSet.noneOf(FileVisitOption.class); Files.walkFileTree(path, opts, Integer.MAX_VALUE, v); } catch (IOException e) { throw new ProCoreException("Could not delete " + path, e); } } @Override public String getCompression() { return "LZ4"; } }