diff --git a/.classpath b/.classpath index bded8da..32d8ef3 100644 --- a/.classpath +++ b/.classpath @@ -25,6 +25,6 @@ - + diff --git a/src/fr/devinsy/sikevadb/SikevaDBLauncher.java b/src/fr/devinsy/sikevadb/SikevaDBLauncher.java index c734f40..51b53b9 100644 --- a/src/fr/devinsy/sikevadb/SikevaDBLauncher.java +++ b/src/fr/devinsy/sikevadb/SikevaDBLauncher.java @@ -20,12 +20,14 @@ package fr.devinsy.sikevadb; import java.io.File; +import org.apache.commons.lang3.ArrayUtils; import org.apache.log4j.BasicConfigurator; import org.apache.log4j.PropertyConfigurator; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import fr.devinsy.sikevadb.cli.SikevaDBCLI; +import fr.devinsy.sikevadb.demo.SikevaDBDemo; /** * This class Siba stands for Simple Backup. This is the main class. @@ -70,6 +72,10 @@ public final class SikevaDBLauncher // TODO // SikevaGUI.run(); } + else if (ArrayUtils.contains(args, "-demo")) + { + SikevaDBDemo.run(args); + } else { SikevaDBCLI.run(args); diff --git a/src/fr/devinsy/sikevadb/core/Archiver.java b/src/fr/devinsy/sikevadb/core/Archiver.java index 5e09052..26829b1 100644 --- a/src/fr/devinsy/sikevadb/core/Archiver.java +++ b/src/fr/devinsy/sikevadb/core/Archiver.java @@ -36,6 +36,8 @@ public interface Archiver void clear() throws SikevaDBException; + void close(); + boolean isActivated(); boolean isSuspended(); diff --git a/src/fr/devinsy/sikevadb/core/SikevaDB.java b/src/fr/devinsy/sikevadb/core/SikevaDB.java index add98c6..0a1632f 100644 --- a/src/fr/devinsy/sikevadb/core/SikevaDB.java +++ b/src/fr/devinsy/sikevadb/core/SikevaDB.java @@ -41,6 +41,8 @@ public interface SikevaDB public void create() throws SikevaDBException; + public void destroy() throws SikevaDBException; + public Element getElement(String key) throws SikevaDBException; public Element getElement(String key, String subkey) throws SikevaDBException; diff --git a/src/fr/devinsy/sikevadb/core/SikevaDBFactory.java b/src/fr/devinsy/sikevadb/core/SikevaDBFactory.java index 8f3ee41..870c1d4 100644 --- a/src/fr/devinsy/sikevadb/core/SikevaDBFactory.java +++ b/src/fr/devinsy/sikevadb/core/SikevaDBFactory.java @@ -34,8 +34,9 @@ public class SikevaDBFactory * * @param path * @return + * @throws SikevaDBException */ - public static SikevaDB get(final File path) + public static SikevaDB get(final File path) throws SikevaDBException { SikevaDB result; diff --git a/src/fr/devinsy/sikevadb/demo/SikevaDBDemo.java b/src/fr/devinsy/sikevadb/demo/SikevaDBDemo.java new file mode 100644 index 0000000..bdb19bd --- /dev/null +++ b/src/fr/devinsy/sikevadb/demo/SikevaDBDemo.java @@ -0,0 +1,256 @@ +/** + * Copyright (C) 2013-2017 Christian Pierre MOMON + * + * This file is part of SikevaDB, simple key value database. + * + * SikevaDB is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * SikevaDB 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with SikevaDB. If not, see . + */ + +package fr.devinsy.sikevadb.demo; + +import java.io.File; + +import org.apache.commons.lang3.StringUtils; +import org.apache.log4j.BasicConfigurator; +import org.apache.log4j.PropertyConfigurator; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import utils.BuildInformation; +import fr.devinsy.sikevadb.core.SikevaDB; +import fr.devinsy.sikevadb.core.SikevaDBException; +import fr.devinsy.sikevadb.core.SikevaDBFactory; +import fr.devinsy.util.strings.StringList; + +/** + * This class manage a Command Line Interface for SikevaDB. + * + * + */ +public final class SikevaDBDemo +{ + private static Logger logger = LoggerFactory.getLogger(SikevaDBDemo.class); + + /** + * + */ + private SikevaDBDemo() + { + } + + /** + * @throws SikevaDBException + * + */ + public static void demo() throws SikevaDBException + { + SikevaDB database = null; + try + { + File homeDirectory = new File("/tmp/footest"); + database = SikevaDBFactory.get(homeDirectory); + + if (database.isCreated()) + { + database.destroy(); + } + + database.create(); + database.open(); + + // Single key value. + { + database.put("alpha", "alpha value"); + database.put("bravo", "bravo value"); + database.put("charlie", "charlie value"); + + String value = database.getValue("alpha"); + if (StringUtils.equals(value, "alpha value")) + { + System.out.println("alpha is correctly stored."); + } + else + { + System.out.println("alpha is NOT correctly stored."); + } + + // + database.remove("alpha"); + if (database.getValue("alpha") == null) + { + System.out.println("alpha is correctly removed."); + } + else + { + System.out.println("alpha is NOT correctly removed."); + } + } + + // Double key values. + { + for (int index = 0; index < 10; index++) + { + database.put("victor", String.valueOf(index), "victor" + index); + } + + String value = database.getValue("victor", String.valueOf(7)); + if (StringUtils.equals(value, "victor7")) + { + System.out.println("victor is correctly stored."); + } + else + { + System.out.println("victor is NOT correctly stored."); + } + + // + database.remove("victor", String.valueOf(5)); + if (database.getValue("victor", String.valueOf(5)) == null) + { + System.out.println("(victor, 5) is correctly removed."); + } + else + { + System.out.println("(victor, 5) is NOT correctly removed."); + } + } + + // + database.close(); + } + finally + { + if ((database != null) && (database.isCreated())) + { + database.destroy(); + } + } + } + + /** + * This method displays the CLI help. + * + */ + public static void help() + { + StringList message = new StringList(); + + message.append("SikevaDB Demo version ").appendln(BuildInformation.instance().version()); + message.appendln("Usage:"); + message.appendln(" sikevadbdemo [ -h | -help | --help ]"); + message.appendln(" sikevadb -demo [ -h | -help | --help ]"); + + System.out.println(message.toString()); + } + + /** + * + * @param args + */ + public static void main(final String[] args) + { + // Configure log. + File loggerConfig = new File("log4j.properties"); + if (loggerConfig.exists()) + { + PropertyConfigurator.configure(loggerConfig.getAbsolutePath()); + logger.info("Dedicated log configuration done."); + logger.info("Configuration file was found in [{}].", loggerConfig.getAbsoluteFile()); + } + else + { + BasicConfigurator.configure(); + logger.info("Basic log configuration done."); + logger.info("Configuration file was not found in [{}].", loggerConfig.getAbsoluteFile()); + } + + // Run. + SikevaDBDemo.run(args); + } + + /** + * + * This method launch CLI. + * + * @param args + * necessary arguments + */ + public static void run(final String[] args) + { + try + { + // Set default catch. + Thread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() + { + @Override + public void uncaughtException(final Thread thread, final Throwable exception) + { + String message; + if (exception instanceof OutOfMemoryError) + { + message = "Java ran out of memory!\n\n"; + } + else + { + message = String.format("An error occured: %1s(%2s)", exception.getClass(), exception.getMessage()); + } + + logger.error("uncaughtException ", exception); + logger.error(message); + logger.info("Oups, an unexpected error occured. Please try again."); + } + }); + + // This part implements an automate. + int parameterCount = args.length; + if (parameterCount == 0) + { + demo(); + } + else if (StringUtils.equals(args[0], "-h") || StringUtils.equals(args[0], "-help") || StringUtils.equals(args[0], "--help")) + { + help(); + } + else if (StringUtils.equals(args[0], "get")) + { + switch (parameterCount) + { + case 2: + { + } + break; + + case 3: + { + } + break; + + default: + throw new SikevaDBException("Bad parameter count."); + } + } + else + { + System.out.println("Bad usage detected."); + help(); + } + } + catch (SikevaDBException exception) + { + System.err.println("SibaException = " + exception.getMessage()); + logger.error(exception.getMessage(), exception); + help(); + } + } +} diff --git a/src/fr/devinsy/sikevadb/demo/SikevaDBDemoException.java b/src/fr/devinsy/sikevadb/demo/SikevaDBDemoException.java new file mode 100644 index 0000000..49afc4e --- /dev/null +++ b/src/fr/devinsy/sikevadb/demo/SikevaDBDemoException.java @@ -0,0 +1,65 @@ +/** + * Copyright (C) 2013-2017 Christian Pierre MOMON + * + * This file is part of SikevaDB, simple key value database. + * + * SikevaDB is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * SikevaDB 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with SikevaDB. If not, see . + */ +package fr.devinsy.sikevadb.demo; + +import fr.devinsy.sikevadb.core.SikevaDBException; + +/** + * + */ +public class SikevaDBDemoException extends SikevaDBException +{ + private static final long serialVersionUID = 1162267847144476595L; + + /** + * + */ + public SikevaDBDemoException() + { + super(); + } + + /** + * + * @param message + */ + public SikevaDBDemoException(final String message) + { + super(message); + } + + /** + * + * @param message + * @param cause + */ + public SikevaDBDemoException(final String message, final Throwable cause) + { + super(message, cause); + } + + /** + * + * @param cause + */ + public SikevaDBDemoException(final Throwable cause) + { + super(cause); + } +} \ No newline at end of file diff --git a/src/fr/devinsy/sikevadb/filetree/FileTreeArchiver.java b/src/fr/devinsy/sikevadb/filetree/FileTreeArchiver.java index 8bc9058..529b618 100644 --- a/src/fr/devinsy/sikevadb/filetree/FileTreeArchiver.java +++ b/src/fr/devinsy/sikevadb/filetree/FileTreeArchiver.java @@ -97,6 +97,15 @@ public class FileTreeArchiver implements Archiver } + /** + * + */ + @Override + public void close() + { + // TODO + } + /** * * @return diff --git a/src/fr/devinsy/sikevadb/filetree/FileTreeSikevaDB.java b/src/fr/devinsy/sikevadb/filetree/FileTreeSikevaDB.java index 96000cf..e8d6da0 100644 --- a/src/fr/devinsy/sikevadb/filetree/FileTreeSikevaDB.java +++ b/src/fr/devinsy/sikevadb/filetree/FileTreeSikevaDB.java @@ -22,6 +22,8 @@ import java.io.File; import java.io.IOException; import org.apache.commons.io.FileUtils; +import org.apache.commons.lang3.StringUtils; +import org.apache.commons.lang3.SystemUtils; import org.joda.time.format.DateTimeFormatter; import org.joda.time.format.ISODateTimeFormat; import org.slf4j.Logger; @@ -32,6 +34,7 @@ import fr.devinsy.sikevadb.core.Element; import fr.devinsy.sikevadb.core.Elements; import fr.devinsy.sikevadb.core.SikevaDB; import fr.devinsy.sikevadb.core.SikevaDBException; +import fr.devinsy.util.ToolBox; import fr.devinsy.util.strings.StringList; /** @@ -63,7 +66,7 @@ public class FileTreeSikevaDB implements SikevaDB private Status status; private String login; private String password; - private File fileTreeDirectory; + private File homeDirectory; private File dataDirectory; private Archiver archiver; private File configDirectory; @@ -71,16 +74,28 @@ public class FileTreeSikevaDB implements SikevaDB /** * * @param contextName + * @throws SikevaDBException */ - public FileTreeSikevaDB(final File fileTreeDirectory, final String login, final String password) + public FileTreeSikevaDB(final File homeDirectory, final String login, final String password) throws SikevaDBException { - this.status = Status.CLOSED; - this.fileTreeDirectory = fileTreeDirectory; - this.dataDirectory = new File(this.fileTreeDirectory, "data"); - this.configDirectory = new File(this.fileTreeDirectory, "config"); - this.login = login; - this.password = password; - this.archiver = null; + if (homeDirectory == null) + { + throw new SikevaDBException("Invalid home directory (null)."); + } + else if (StringUtils.equals(homeDirectory.getAbsolutePath(), "/")) + { + throw new SikevaDBException("Invalide home directory (file system root)."); + } + else + { + this.status = Status.CLOSED; + this.homeDirectory = homeDirectory; + this.dataDirectory = new File(this.homeDirectory, "data"); + this.configDirectory = new File(this.homeDirectory, "config"); + this.login = login; + this.password = password; + this.archiver = null; + } } /** @@ -118,7 +133,7 @@ public class FileTreeSikevaDB implements SikevaDB @Override public void close() { - this.archiver = null; + this.archiver.close(); this.status = Status.CLOSED; } @@ -224,22 +239,83 @@ public class FileTreeSikevaDB implements SikevaDB { throw new SikevaDBException("Invalid state."); } - else if (this.fileTreeDirectory == null) + else if (this.homeDirectory == null) { throw new SikevaDBException("Invalid root directory."); } - else if (this.fileTreeDirectory.exists()) + else if (this.homeDirectory.exists()) { throw new SikevaDBException("Root directory already is existing."); } else { - this.fileTreeDirectory.mkdir(); + this.homeDirectory.mkdir(); this.dataDirectory.mkdir(); this.configDirectory.mkdir(); } } + /** + * + */ + @Override + public void destroy() throws SikevaDBException + { + if (this.homeDirectory == null) + { + throw new SikevaDBException("Invalid home directory (undefined), destroy operation is cancelled."); + } + else + { + String databaseHome = this.homeDirectory.getAbsolutePath(); + databaseHome = StringUtils.removeEnd(databaseHome, "/."); + + if (StringUtils.isBlank(databaseHome)) + { + throw new SikevaDBException("Invalid home directory (blank), destroy operation is cancelled."); + } + else if (this.dataDirectory == null) + { + throw new SikevaDBException("Invalid data directory (undefined), destroy operation is cancelled."); + } + else if (StringUtils.isBlank(this.dataDirectory.getAbsolutePath())) + { + throw new SikevaDBException("Invalid data directory (blank), destroy operation is cancelled."); + } + else if (this.configDirectory == null) + { + throw new SikevaDBException("Invalid config directory (undefined), destroy operation is cancelled."); + } + else if (StringUtils.isBlank(this.configDirectory.getAbsolutePath())) + { + throw new SikevaDBException("Invalid config directory (blank), destroy operation is cancelled."); + } + else if (ToolBox.matchesAny(databaseHome, "/", "/root", "/usr", "/home", "/tmp", "/var", "/srv", "/boot")) + { + throw new SikevaDBException("Invalid home directory (system file), destroy operation is cancelled."); + } + else if (StringUtils.equals(databaseHome, SystemUtils.USER_HOME)) + { + throw new SikevaDBException("Invalid config directory (), destroy operation is cancelled."); + } + else if (isCreated()) + { + try + { + FileUtils.deleteDirectory(this.homeDirectory); + } + catch (IOException exception) + { + throw new SikevaDBException("Error destroying database. You have to achieve the operation manually.", exception); + } + } + else + { + throw new SikevaDBException("Impossible to destroy a none existing database."); + } + } + } + /** * * @return @@ -397,7 +473,7 @@ public class FileTreeSikevaDB implements SikevaDB */ public File getFileTreeDirectory() { - return this.fileTreeDirectory; + return this.homeDirectory; } /** @@ -657,7 +733,7 @@ public class FileTreeSikevaDB implements SikevaDB { boolean result; - if ((this.fileTreeDirectory.isDirectory()) && (this.dataDirectory.isDirectory()) && (this.configDirectory.isDirectory())) + if ((this.homeDirectory.isDirectory()) && (this.dataDirectory.isDirectory()) && (this.configDirectory.isDirectory())) { result = true; } @@ -819,12 +895,22 @@ public class FileTreeSikevaDB implements SikevaDB @Override public void open() throws SikevaDBException { - // - close(); - - // - this.status = Status.OPENED; - this.archiver = new FileTreeArchiver(this); + if (isCreated()) + { + if (isOpened()) + { + throw new SikevaDBException("Database already opened."); + } + else + { + this.status = Status.OPENED; + this.archiver = new FileTreeArchiver(this); + } + } + else + { + throw new SikevaDBException("Database is not existing."); + } } /** diff --git a/src/fr/devinsy/sikevadb/sql/SQLSikevaDB.java b/src/fr/devinsy/sikevadb/sql/SQLSikevaDB.java index 192de8d..6c1fcbb 100644 --- a/src/fr/devinsy/sikevadb/sql/SQLSikevaDB.java +++ b/src/fr/devinsy/sikevadb/sql/SQLSikevaDB.java @@ -445,6 +445,15 @@ public class SQLSikevaDB implements SikevaDB } } + /** + * + */ + @Override + public void destroy() throws SikevaDBException + { + // TODO + } + /** * * @param id