You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@isis.apache.org by da...@apache.org on 2012/12/06 12:09:56 UTC

[22/51] [partial] ISIS-188: moving components into correct directories.

http://git-wip-us.apache.org/repos/asf/isis/blob/cd9f2e4a/framework/objectstore/nosql/src/main/java/org/apache/isis/runtimes/dflt/objectstores/nosql/db/file/server/FileServerException.java
----------------------------------------------------------------------
diff --git a/framework/objectstore/nosql/src/main/java/org/apache/isis/runtimes/dflt/objectstores/nosql/db/file/server/FileServerException.java b/framework/objectstore/nosql/src/main/java/org/apache/isis/runtimes/dflt/objectstores/nosql/db/file/server/FileServerException.java
new file mode 100644
index 0000000..dc0a2fc
--- /dev/null
+++ b/framework/objectstore/nosql/src/main/java/org/apache/isis/runtimes/dflt/objectstores/nosql/db/file/server/FileServerException.java
@@ -0,0 +1,38 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+
+package org.apache.isis.runtimes.dflt.objectstores.nosql.db.file.server;
+
+import java.io.IOException;
+
+import org.apache.isis.core.commons.exceptions.IsisException;
+
+public class FileServerException extends IsisException {
+
+    private static final long serialVersionUID = 1L;
+
+    public FileServerException(final String message, final IOException e) {
+        super(message, e);
+    }
+
+    public FileServerException(final String message) {
+        super(message);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/cd9f2e4a/framework/objectstore/nosql/src/main/java/org/apache/isis/runtimes/dflt/objectstores/nosql/db/file/server/FileServerProcessor.java
----------------------------------------------------------------------
diff --git a/framework/objectstore/nosql/src/main/java/org/apache/isis/runtimes/dflt/objectstores/nosql/db/file/server/FileServerProcessor.java b/framework/objectstore/nosql/src/main/java/org/apache/isis/runtimes/dflt/objectstores/nosql/db/file/server/FileServerProcessor.java
new file mode 100644
index 0000000..8b22d73
--- /dev/null
+++ b/framework/objectstore/nosql/src/main/java/org/apache/isis/runtimes/dflt/objectstores/nosql/db/file/server/FileServerProcessor.java
@@ -0,0 +1,385 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+
+package org.apache.isis.runtimes.dflt.objectstores.nosql.db.file.server;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileFilter;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.UnsupportedEncodingException;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.log4j.Logger;
+
+import org.apache.isis.runtimes.dflt.objectstores.nosql.NoSqlStoreException;
+
+public class FileServerProcessor {
+
+    private static final Logger LOG = Logger.getLogger(FileServerProcessor.class);
+
+    private boolean acceptNewRequests = true;
+    private LockManager locks;
+    private LogWriter logger;
+
+    public void startup() {
+        Util.ensureDirectoryExists();
+        logger = new LogWriter();
+        logger.startup();
+        locks = new LockManager();
+    }
+
+    public void shutdown() {
+        acceptNewRequests = false;
+        locks.waitUntilAllRealeased();
+        logger.shutdown();
+    }
+
+    LogWriter getLogger() {
+        return logger;
+    }
+
+    public void process(final ServerConnection connection) {
+        try {
+            if (acceptNewRequests) {
+                connection.readCommand();
+                final char command = connection.getCommand();
+                switch (command) {
+                case 'L':
+                    list(connection);
+                    break;
+
+                case 'R':
+                    read(connection);
+                    break;
+
+                case 'W':
+                    write(connection);
+                    break;
+
+                case 'I':
+                    hasInstances(connection);
+                    break;
+
+                case 'S':
+                    service(connection);
+                    break;
+
+                case 'T':
+                    saveService(connection);
+                    break;
+
+                case 'N':
+                    nextSerialBatch(connection);
+                    break;
+
+                case 'X':
+                    status(connection);
+                    break;
+
+                default:
+                    LOG.warn("Unrecognised command " + command);
+                    connection.error("Unrecognised command " + command);
+                }
+            } else {
+                connection.abort();
+            }
+        } catch (final Exception e) {
+            LOG.error("Request failed", e);
+            connection.error("Remote exception thrown:\n" + e.getMessage(), e);
+
+        } finally {
+            connection.close();
+        }
+    }
+
+    private void list(final ServerConnection connection) {
+        try {
+            connection.endCommand();
+            final String type = connection.getRequest();
+            int limit = connection.getRequestAsInt();
+            if (limit == 0) {
+                limit = Integer.MAX_VALUE;
+            }
+
+            final File[] listFiles = listFiles(type);
+            if (listFiles != null) {
+                connection.ok();
+                for (final File file : listFiles) {
+                    final String fileName = file.getName();
+                    final String id = fileName.substring(0, fileName.length() - 5);
+                    final DataFileReader reader = findInstance(type, id, connection);
+                    readInstance(reader, connection);
+                    locks.release(id, getTransactionId());
+                    if (limit-- < 0) {
+                        break;
+                    }
+                }
+                connection.endBlock();
+            } else {
+                connection.response("");
+            }
+
+        } catch (final IOException e) {
+            throw new NoSqlStoreException(Util.READ_ERROR, e);
+        }
+    }
+
+    private File[] listFiles(final String type) {
+        final File[] listFiles = Util.directory(type).listFiles(new FileFilter() {
+            @Override
+            public boolean accept(final File pathname) {
+                return pathname.getName().endsWith(".data");
+            }
+        });
+        return listFiles;
+    }
+
+    private void read(final ServerConnection connection) {
+        String type = null;
+        String id = null;
+        try {
+            connection.endCommand();
+            type = connection.getRequest();
+            id = connection.getRequest();
+            final DataFileReader reader = findInstance(type, id, connection);
+            if (reader == null) {
+                connection.notFound(Util.FILE_NOT_FOUND + " for " + type + "/" + id);
+            } else {
+                connection.ok();
+                readInstance(reader, connection);
+            }
+        } catch (final IOException e) {
+            throw new NoSqlStoreException(Util.READ_ERROR + " for " + type + "/" + id, e);
+        } finally {
+            locks.release(id, getTransactionId());
+        }
+
+    }
+
+    private DataFileReader findInstance(final String type, final String id, final ServerConnection connection) throws IOException {
+        LOG.debug("reading file " + id);
+        locks.acquireRead(id, getTransactionId());
+        try {
+            return new DataFileReader(type, id);
+        } catch (final FileNotFoundException e) {
+            LOG.error(Util.FILE_NOT_FOUND + " for " + type + "/" + id, e);
+            return null;
+        }
+    }
+
+    private void readInstance(final DataFileReader reader, final ServerConnection connection) {
+        final String data = reader.getData();
+        reader.close();
+        connection.responseData(data);
+    }
+
+    private void write(final ServerConnection connection) {
+        List<FileContent> files = null;
+        try {
+            files = getWriteRequests(connection);
+            final String error = acquireLocks(files);
+            if (error == null) {
+                logger.logWrites(files);
+                final DataFileWriter content = new DataFileWriter(files);
+                content.writeData();
+                connection.ok();
+            } else {
+                connection.error(error);
+            }
+
+        } catch (final IOException e) {
+            throw new NoSqlStoreException("Failed to write data", e);
+        } finally {
+            if (files != null) {
+                releaseLocks(files);
+            }
+        }
+    }
+
+    private List<FileContent> getWriteRequests(final ServerConnection connection) throws IOException {
+        final ArrayList<FileContent> files = new ArrayList<FileContent>();
+        while (connection.readWriteHeaders()) {
+            final char command = connection.getCommand();
+            final String type = connection.getRequest();
+            final String id = connection.getRequest();
+            final String currentVersion = connection.getRequest();
+            final String newVersion = connection.getRequest();
+            LOG.debug("write for " + type + "@" + id + " v." + newVersion);
+
+            final String buf = connection.getData();
+            files.add(new FileContent(command, id, currentVersion, newVersion, type, buf));
+        }
+        // connection.endCommand();
+        return files;
+    }
+
+    private String acquireLocks(final List<FileContent> list) throws IOException {
+        final Thread transactionId = getTransactionId();
+        for (final FileContent item : list) {
+            if (!locks.acquireWrite(item.id, transactionId)) {
+                return item.type + " being changed by another user, please try again\n" + item.data;
+            }
+            if (Util.shouldFileExist(item.command)) {
+                final DataFileReader dataReader = new DataFileReader(item.type, item.id);
+                final String version = dataReader.getVersion();
+                if (!version.equals(item.currentVersion)) {
+                    // String data = dataReader.getData();
+                    dataReader.close();
+                    return "mismatch between FileContent version (" + item.currentVersion + ") and DataReader version (" + version + ")";
+                }
+                dataReader.close();
+            }
+        }
+        return null;
+    }
+
+    private void releaseLocks(final List<FileContent> list) {
+        final Thread transactionId = getTransactionId();
+        for (final FileContent item : list) {
+            locks.release(item.id, transactionId);
+        }
+    }
+
+    private Thread getTransactionId() {
+        return Thread.currentThread();
+    }
+
+    private void status(final ServerConnection connection) throws IOException {
+        connection.endCommand();
+        final String request = connection.getRequest();
+        if (request.equals("contains-data")) {
+            connection.response(Util.isPopulated());
+
+        } else {
+            connection.error("Unrecognised command " + request);
+        }
+    }
+
+    private void service(final ServerConnection connection) {
+        connection.endCommand();
+        final String name = connection.getRequest();
+        final File file = Util.serviceFile(name);
+        if (file.exists()) {
+            final String id = readServiceFile(file);
+            connection.response(id);
+        } else {
+            connection.response("null");
+        }
+    }
+
+    private String readServiceFile(final File file) {
+        BufferedReader reader = null;
+        try {
+            reader = new BufferedReader(new InputStreamReader(new FileInputStream(file), Util.ENCODING));
+            final String[] split = reader.readLine().split(" ");
+            return split[1];
+        } catch (final IOException e) {
+            LOG.error("failed to read service file", e);
+            throw new FileServerException("Failed to read service file", e);
+        } finally {
+            try {
+                reader.close();
+            } catch (final IOException e) {
+                LOG.error("failed to close file", e);
+            }
+        }
+    }
+
+    private void saveService(final ServerConnection connection) throws IOException {
+        connection.endCommand();
+        final String name = connection.getRequest();
+        final String key = connection.getRequest();
+        logger.logServiceEntry(key, name);
+        saveService(key, name);
+        connection.ok();
+    }
+
+    void saveService(final String key, final String name) throws FileNotFoundException, IOException, UnsupportedEncodingException {
+        FileOutputStream fileOut = null;
+        final File file = Util.serviceFile(name);
+        try {
+            fileOut = new FileOutputStream(file);
+            fileOut.write(name.getBytes(Util.ENCODING));
+            fileOut.write(' ');
+            fileOut.write(key.getBytes(Util.ENCODING));
+        } finally {
+            if (fileOut != null) {
+                try {
+                    fileOut.close();
+                } catch (final IOException e) {
+                    throw new NoSqlStoreException(e);
+                }
+            }
+        }
+    }
+
+    private void nextSerialBatch(final ServerConnection connection) throws IOException {
+        // TODO lock file first
+
+        connection.endCommand();
+        final String name = connection.getRequest();
+        final int batchSize = connection.getRequestAsInt();
+
+        long nextId;
+        final File file = Util.serialNumberFile(name);
+        if (!file.exists()) {
+            nextId = 1;
+            LOG.info("Initial ID batch created at " + nextId);
+        } else {
+            final BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(file), Util.ENCODING));
+            nextId = Long.valueOf(reader.readLine()).longValue();
+            reader.close();
+            LOG.info("New ID batch allocated, from " + nextId);
+        }
+
+        final long newBatchAt = nextId + batchSize;
+        logger.logNextSerialBatch(name, newBatchAt);
+
+        saveNextBatch(file, newBatchAt);
+
+        // TODO remove lock
+
+        connection.response(nextId);
+    }
+
+    private void saveNextBatch(final File file, final long newBatchAt) throws FileNotFoundException, IOException {
+        final FileOutputStream fileOutput = new FileOutputStream(file);
+        fileOutput.write(Long.toString(newBatchAt).getBytes(Util.ENCODING));
+        fileOutput.close();
+    }
+
+    public void saveNextBatch(final String name, final long nextBatch) throws IOException {
+        saveNextBatch(Util.serialNumberFile(name), nextBatch);
+    }
+
+    private void hasInstances(final ServerConnection connection) throws IOException {
+        connection.endCommand();
+        final String type = connection.getRequest();
+        final File[] listFiles = listFiles(type);
+        final boolean hasInstances = listFiles != null && listFiles.length > 0;
+        connection.response(hasInstances);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/cd9f2e4a/framework/objectstore/nosql/src/main/java/org/apache/isis/runtimes/dflt/objectstores/nosql/db/file/server/Lock.java
----------------------------------------------------------------------
diff --git a/framework/objectstore/nosql/src/main/java/org/apache/isis/runtimes/dflt/objectstores/nosql/db/file/server/Lock.java b/framework/objectstore/nosql/src/main/java/org/apache/isis/runtimes/dflt/objectstores/nosql/db/file/server/Lock.java
new file mode 100644
index 0000000..a1f0c93
--- /dev/null
+++ b/framework/objectstore/nosql/src/main/java/org/apache/isis/runtimes/dflt/objectstores/nosql/db/file/server/Lock.java
@@ -0,0 +1,54 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+
+package org.apache.isis.runtimes.dflt.objectstores.nosql.db.file.server;
+
+import java.util.ArrayList;
+import java.util.List;
+
+class Lock {
+
+    private Thread write;
+    private final List<Thread> reads = new ArrayList<Thread>();
+
+    public boolean isWriteLocked() {
+        return write != null;
+    }
+
+    public void addRead(final Thread transaction) {
+        reads.add(transaction);
+    }
+
+    public void setWrite(final Thread transaction) {
+        write = transaction;
+    }
+
+    public void remove(final Thread transaction) {
+        if (write == transaction) {
+            write = null;
+        } else {
+            reads.remove(transaction);
+        }
+    }
+
+    public boolean isEmpty() {
+        return write == null && reads.isEmpty();
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/cd9f2e4a/framework/objectstore/nosql/src/main/java/org/apache/isis/runtimes/dflt/objectstores/nosql/db/file/server/LockManager.java
----------------------------------------------------------------------
diff --git a/framework/objectstore/nosql/src/main/java/org/apache/isis/runtimes/dflt/objectstores/nosql/db/file/server/LockManager.java b/framework/objectstore/nosql/src/main/java/org/apache/isis/runtimes/dflt/objectstores/nosql/db/file/server/LockManager.java
new file mode 100644
index 0000000..e9ab7ba
--- /dev/null
+++ b/framework/objectstore/nosql/src/main/java/org/apache/isis/runtimes/dflt/objectstores/nosql/db/file/server/LockManager.java
@@ -0,0 +1,66 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+
+package org.apache.isis.runtimes.dflt.objectstores.nosql.db.file.server;
+
+import java.util.HashMap;
+import java.util.Map;
+
+public class LockManager {
+
+    private final Map<String, Lock> locks = new HashMap<String, Lock>();
+
+    public synchronized void acquireRead(final String id, final Thread transaction) {
+        final Lock lock = getLock(id);
+        lock.addRead(transaction);
+    }
+
+    public boolean acquireWrite(final String id, final Thread transaction) {
+        final Lock lock = getLock(id);
+        if (lock.isWriteLocked()) {
+            return false;
+        }
+        lock.setWrite(transaction);
+        return true;
+    }
+
+    private Lock getLock(final String id) {
+        Lock lock;
+        synchronized (this) {
+            lock = locks.get(id);
+            if (lock == null) {
+                lock = new Lock();
+                locks.put(id, lock);
+            }
+        }
+        return lock;
+    }
+
+    public synchronized void release(final String id, final Thread transaction) {
+        final Lock lock = getLock(id);
+        lock.remove(transaction);
+        if (lock.isEmpty()) {
+            locks.remove(id);
+        }
+    }
+
+    public void waitUntilAllRealeased() {
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/cd9f2e4a/framework/objectstore/nosql/src/main/java/org/apache/isis/runtimes/dflt/objectstores/nosql/db/file/server/LogRange.java
----------------------------------------------------------------------
diff --git a/framework/objectstore/nosql/src/main/java/org/apache/isis/runtimes/dflt/objectstores/nosql/db/file/server/LogRange.java b/framework/objectstore/nosql/src/main/java/org/apache/isis/runtimes/dflt/objectstores/nosql/db/file/server/LogRange.java
new file mode 100644
index 0000000..1e0c3b3
--- /dev/null
+++ b/framework/objectstore/nosql/src/main/java/org/apache/isis/runtimes/dflt/objectstores/nosql/db/file/server/LogRange.java
@@ -0,0 +1,41 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+package org.apache.isis.runtimes.dflt.objectstores.nosql.db.file.server;
+
+class LogRange {
+    private long first = Long.MAX_VALUE;
+    private long last = 0;
+
+    public long getFirst() {
+        return first;
+    }
+
+    public long getLast() {
+        return last;
+    }
+
+    public boolean noLogFile() {
+        return first == Long.MAX_VALUE && last == 0;
+    }
+
+    public void add(final long sequence) {
+        last = Math.max(last, sequence);
+        first = Math.min(first, sequence);
+    }
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/cd9f2e4a/framework/objectstore/nosql/src/main/java/org/apache/isis/runtimes/dflt/objectstores/nosql/db/file/server/LogWriter.java
----------------------------------------------------------------------
diff --git a/framework/objectstore/nosql/src/main/java/org/apache/isis/runtimes/dflt/objectstores/nosql/db/file/server/LogWriter.java b/framework/objectstore/nosql/src/main/java/org/apache/isis/runtimes/dflt/objectstores/nosql/db/file/server/LogWriter.java
new file mode 100644
index 0000000..5b02a63
--- /dev/null
+++ b/framework/objectstore/nosql/src/main/java/org/apache/isis/runtimes/dflt/objectstores/nosql/db/file/server/LogWriter.java
@@ -0,0 +1,149 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+
+package org.apache.isis.runtimes.dflt.objectstores.nosql.db.file.server;
+
+import java.io.DataOutputStream;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.util.Date;
+import java.util.List;
+
+import org.apache.isis.runtimes.dflt.objectstores.nosql.NoSqlStoreException;
+
+public class LogWriter {
+
+    private DataOutputStream writer;
+    private boolean startNewFile = false;
+    private long nextLogIdToWrite;
+
+    public void startNewFile() {
+        // don't start new file if old one is empty
+        final File file = Util.logFile(nextLogIdToWrite);
+        if (file.exists() && file.length() > 0) {
+            startNewFile = true;
+        }
+    }
+
+    public synchronized void logNextSerialBatch(final String name, final long newBatchAt) {
+        startNewFileIfNeeded();
+        try {
+            writer.write(("#transaction started - " + new Date().toString() + "\n").getBytes());
+            writer.write('B');
+            writer.write(name.getBytes(Util.ENCODING));
+            writer.write(' ');
+            writer.write(Long.toString(newBatchAt).getBytes(Util.ENCODING));
+            writer.write('\n');
+            writer.write('\n');
+            writer.write("#transaction ended\n\n".getBytes());
+            writer.flush();
+        } catch (final IOException e) {
+            throw new NoSqlStoreException("Failed to write serial number data to log file", e);
+        }
+
+    }
+
+    public synchronized void logServiceEntry(final String key, final String name) {
+        startNewFileIfNeeded();
+        try {
+            writer.write(("#transaction started - " + new Date().toString() + "\n").getBytes());
+            writer.write('S');
+            writer.write(key.getBytes(Util.ENCODING));
+            writer.write(' ');
+            writer.write(name.getBytes(Util.ENCODING));
+            writer.write('\n');
+            writer.write('\n');
+            writer.write("#transaction ended\n\n".getBytes());
+            writer.flush();
+        } catch (final IOException e) {
+            throw new NoSqlStoreException("Failed to write service entry data to log file", e);
+        }
+    }
+
+    public synchronized void logWrites(final List<FileContent> items) {
+        startNewFileIfNeeded();
+        try {
+            writer.write(("#transaction started - " + new Date().toString() + "\n").getBytes());
+            for (final FileContent content : items) {
+                writer.write(content.command);
+                content.write(writer);
+                writer.write('\n');
+            }
+            writer.write("#transaction ended\n\n".getBytes());
+            writer.flush();
+        } catch (final IOException e) {
+            throw new NoSqlStoreException("Failed to write data to log file", e);
+        }
+    }
+
+    private void startNewFileIfNeeded() {
+        if (startNewFile) {
+            close();
+            openNewFile();
+            startNewFile = false;
+        }
+    }
+
+    private void openNewFile() {
+        nextLogIdToWrite++;
+        final File file = Util.logFile(nextLogIdToWrite);
+        if (file.exists()) {
+            throw new NoSqlStoreException("Log file already exists");
+        }
+        openFile(file);
+    }
+
+    private void openFile(final File file) {
+        try {
+            writer = new DataOutputStream(new FileOutputStream(file));
+            startNewFile = false;
+        } catch (final IOException e) {
+            throw new NoSqlStoreException("Failed to open log file", e);
+        }
+    }
+
+    public void startup() {
+        nextLogIdToWrite = Util.logFileRange().getLast();
+        startNewFile();
+        if (!startNewFile) {
+            final File file = Util.logFile(nextLogIdToWrite);
+            openFile(file);
+        } else {
+            openNewFile();
+        }
+    }
+
+    public void shutdown() {
+        close();
+    }
+
+    private void close() {
+        try {
+            writer.close();
+        } catch (final IOException e) {
+            throw new NoSqlStoreException("Falied to close log file", e);
+        }
+    }
+
+    public synchronized boolean isWritten(final long logId) {
+        startNewFileIfNeeded();
+        return logId < nextLogIdToWrite;
+    }
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/cd9f2e4a/framework/objectstore/nosql/src/main/java/org/apache/isis/runtimes/dflt/objectstores/nosql/db/file/server/ServerConnection.java
----------------------------------------------------------------------
diff --git a/framework/objectstore/nosql/src/main/java/org/apache/isis/runtimes/dflt/objectstores/nosql/db/file/server/ServerConnection.java b/framework/objectstore/nosql/src/main/java/org/apache/isis/runtimes/dflt/objectstores/nosql/db/file/server/ServerConnection.java
new file mode 100644
index 0000000..9d16e7f
--- /dev/null
+++ b/framework/objectstore/nosql/src/main/java/org/apache/isis/runtimes/dflt/objectstores/nosql/db/file/server/ServerConnection.java
@@ -0,0 +1,237 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+
+package org.apache.isis.runtimes.dflt.objectstores.nosql.db.file.server;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.OutputStream;
+import java.io.OutputStreamWriter;
+import java.io.PrintWriter;
+
+import org.apache.log4j.Logger;
+
+import org.apache.isis.runtimes.dflt.objectstores.nosql.NoSqlStoreException;
+import org.apache.isis.runtimes.dflt.objectstores.nosql.db.file.RemotingException;
+
+public class ServerConnection {
+
+    private static final Logger LOG = Logger.getLogger(ServerConnection.class);
+
+    private final BufferedReader reader;
+    private final PrintWriter writer;
+    private final OutputStream outputStream;
+    private final InputStream inputStream;
+    private int header;
+    private String[] headers;
+    private char command;
+
+    public ServerConnection(final InputStream input, final OutputStream output) {
+        outputStream = Util.trace(output, true);
+        inputStream = Util.trace(input, true);
+        this.reader = new BufferedReader(new InputStreamReader(inputStream, Util.ENCODING));
+        this.writer = new PrintWriter(new OutputStreamWriter(outputStream, Util.ENCODING));
+    }
+
+    public void readCommand() {
+        readHeaders();
+    }
+
+    private void logFailure() {
+        LOG.error("(failed " + inputStream + ")");
+        LOG.error("(failed " + outputStream + ")");
+    }
+
+    public void logComplete() {
+        LOG.debug("(complete " + inputStream + ")");
+        LOG.debug("(complete " + outputStream + ")");
+    }
+
+    boolean readHeaders() {
+        try {
+            final String line = reader.readLine();
+            LOG.debug("header: " + line);
+            if (line == null) {
+                logFailure();
+                throw new RemotingException("stream ended prematurely while reading header, aborting request");
+            }
+            if (line.length() == 0) {
+                return false;
+            } else {
+                command = line.charAt(0);
+                headers = line.substring(1).split(" ");
+                this.header = 0;
+                return true;
+            }
+        } catch (final IOException e) {
+            logFailure();
+            throw new NoSqlStoreException(e);
+        }
+    }
+
+    public boolean readWriteHeaders() {
+        final boolean readHeaders = readHeaders();
+        if (readHeaders && headers.length != 4) {
+            logFailure();
+            throw new RemotingException("invalid header string, aborting request");
+        }
+        return readHeaders;
+    }
+
+    public String getRequest() {
+        return headers[header++];
+    }
+
+    public int getRequestAsInt() {
+        return Integer.valueOf(getRequest()).intValue();
+    }
+
+    public char getCommand() {
+        return command;
+    }
+
+    public void endCommand() {
+        try {
+            final String line = reader.readLine();
+            if (line == null) {
+                logFailure();
+                throw new RemotingException("stream ended prematurely while reading end of command, aborting request");
+            }
+            if (line.length() > 0) {
+                logFailure();
+                throw new RemotingException("command didn't end with an empty blank line, aborting request");
+            }
+        } catch (final IOException e) {
+            logFailure();
+            throw new NoSqlStoreException(e);
+        }
+    }
+
+    /**
+     * Reads all the data up until the next blank line.
+     */
+    public String getData() {
+        try {
+            final StringBuffer buffer = new StringBuffer();
+            String line;
+            while (true) {
+                line = reader.readLine();
+                if (line == null) {
+                    logFailure();
+                    throw new RemotingException("stream ended prematurely while reading data, aborting request");
+                }
+                if (line.length() == 0) {
+                    break;
+                }
+                buffer.append(line);
+                buffer.append('\n');
+            }
+            return buffer.toString();
+        } catch (final IOException e) {
+            logFailure();
+            throw new RemotingException(e);
+        }
+    }
+
+    /*
+     * public void getTermination() { try { String line = reader.readLine(); if
+     * (line == null || !line.equals("***")) { logFailure(); throw new
+     * RemotingException
+     * ("stream ended abruptly while reading data, aborting request"); } } catch
+     * (IOException e) { logFailure(); throw new RemotingException(e); }
+     * 
+     * }
+     */
+    public void notFound(final String message) {
+        writer.print("not-found");
+        writer.print('\n');
+        writer.print(message);
+        writer.print('\n');
+        writer.flush();
+    }
+
+    public void error(final String message) {
+        writer.print("error");
+        writer.print('\n');
+        writer.print(message);
+        writer.print('\n');
+        writer.flush();
+    }
+
+    public void error(final String message, final Exception exception) {
+        error(message);
+        exception.printStackTrace(writer);
+        writer.print('\n');
+        writer.print('\n');
+        writer.flush();
+    }
+
+    private void write(final String result) {
+        writer.print(result);
+        writer.print('\n');
+        writer.flush();
+    }
+
+    public void ok() {
+        response(Util.OK, "");
+    }
+
+    public void abort() {
+        response(Util.ABORT, "");
+    }
+
+    public void response(final boolean flag) {
+        response(Util.OK, " " + (flag ? "true" : "false"));
+    }
+
+    public void response(final long value) {
+        response(Util.OK, " " + Long.toString(value));
+    }
+
+    public void response(final String message) {
+        response(Util.OK, " " + message);
+    }
+
+    private void response(final String status, final String message) {
+        final String response = status + message;
+        LOG.debug("response: " + response);
+        write(response);
+    }
+
+    public void responseData(final String data) {
+        write(data);
+    }
+
+    public void close() {
+        try {
+            reader.close();
+            writer.close();
+        } catch (final IOException e) {
+            logFailure();
+            throw new RemotingException(e);
+        }
+    }
+
+    public void endBlock() {
+        writer.print('\n');
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/cd9f2e4a/framework/objectstore/nosql/src/main/java/org/apache/isis/runtimes/dflt/objectstores/nosql/db/file/server/Util.java
----------------------------------------------------------------------
diff --git a/framework/objectstore/nosql/src/main/java/org/apache/isis/runtimes/dflt/objectstores/nosql/db/file/server/Util.java b/framework/objectstore/nosql/src/main/java/org/apache/isis/runtimes/dflt/objectstores/nosql/db/file/server/Util.java
new file mode 100644
index 0000000..7a94331
--- /dev/null
+++ b/framework/objectstore/nosql/src/main/java/org/apache/isis/runtimes/dflt/objectstores/nosql/db/file/server/Util.java
@@ -0,0 +1,330 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+
+package org.apache.isis.runtimes.dflt.objectstores.nosql.db.file.server;
+
+import java.io.File;
+import java.io.FileFilter;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.nio.charset.Charset;
+
+import org.apache.log4j.Logger;
+
+import org.apache.isis.runtimes.dflt.objectstores.nosql.NoSqlStoreException;
+
+public class Util {
+
+    private static final Logger LOG = Logger.getLogger(Util.class);
+
+    private static final String DEFAULT_DIRECTORY = "data";
+    private static final String SERVICES_DIRECTORY = "services";
+    private static final String LOGS_DIRECTORY = "logs";
+    private static final String LOGS_ARCHIVE_DIRECTORY = "archive";
+    public static final String ABORT = "abort";
+    public static final String OK = "ok";
+    public static final String READ_ERROR = "Read error";
+    public static final String FILE_NOT_FOUND = "File not found";
+    private static final int NEWLINE = '\n';
+
+    private static File dataDirectory = new File(DEFAULT_DIRECTORY);
+    private static File serviceDirectory = new File(DEFAULT_DIRECTORY, SERVICES_DIRECTORY);
+    private static File logDirectory = new File(DEFAULT_DIRECTORY, LOGS_DIRECTORY);
+    private static File logArchiveDirectory = new File(DEFAULT_DIRECTORY, LOGS_ARCHIVE_DIRECTORY);
+
+    static void setDirectory(final String data, final String services, final String logs, final String archive) {
+        final String directory = data == null ? DEFAULT_DIRECTORY : data;
+        Util.dataDirectory = new File(directory);
+        Util.serviceDirectory = new File(directory, services == null ? SERVICES_DIRECTORY : services);
+        Util.logDirectory = new File(directory, logs == null ? LOGS_DIRECTORY : logs);
+        Util.logArchiveDirectory = new File(directory, archive == null ? LOGS_ARCHIVE_DIRECTORY : archive);
+    }
+
+    static void ensureDirectoryExists() {
+        if (!serviceDirectory.exists()) {
+            serviceDirectory.mkdirs();
+        }
+        if (!logDirectory.exists()) {
+            logDirectory.mkdirs();
+        }
+        if (!logArchiveDirectory.exists()) {
+            logArchiveDirectory.mkdirs();
+        }
+    }
+
+    public static boolean isPopulated() {
+        final FileFilter filter = new FileFilter() {
+            @Override
+            public boolean accept(final File pathname) {
+                final String name = pathname.getName();
+                return name.endsWith(".data") || name.endsWith(".id") || name.endsWith(".log");
+            }
+        };
+
+        final File[] data = dataDirectory.listFiles();
+        for (final File directory : data) {
+            if (directory.isDirectory() && directory.listFiles(filter).length > 1) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    public static boolean hasInstances(final String type) {
+        final FileFilter filter = new FileFilter() {
+            @Override
+            public boolean accept(final File pathname) {
+                final String name = pathname.getName();
+                return name.endsWith(".data") || name.endsWith(".id") || name.endsWith(".log");
+            }
+        };
+
+        final File[] data = dataDirectory.listFiles();
+        for (final File directory : data) {
+            if (directory.isDirectory() && directory.listFiles(filter).length > 1) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    public static String xxreadNext(final InputStream input) throws IOException {
+        final byte[] buffer = new byte[100];
+        int c;
+        int i = 0;
+        // TODO deal with buffer overrun
+        while ((c = input.read()) != ' ' && c != '\n' && c != -1) {
+            buffer[i++] = (byte) c;
+        }
+        if (i == 0) {
+            throw new NoSqlStoreException("No data read from " + input);
+        }
+        final String read = new String(buffer, 0, i);
+        LOG.debug("read " + read);
+        return read;
+    }
+
+    public static byte[] xxreadData(final InputStream input) throws IOException {
+        // TODO increase to suitable size
+        byte[] buf = new byte[32];
+        int i = 0;
+        int c1 = input.read();
+        if (c1 == '.') {
+            return null;
+        }
+        int c2 = input.read();
+        boolean isEnd;
+        do {
+            if (i == buf.length) {
+                final byte[] newBuf = new byte[buf.length * 2];
+                System.arraycopy(buf, 0, newBuf, 0, buf.length);
+                buf = newBuf;
+            }
+            buf[i++] = (byte) c1;
+            c1 = c2;
+            c2 = input.read();
+            isEnd = (c1 == NEWLINE && c2 == NEWLINE) || c2 == -1;
+        } while (!isEnd);
+        return buf;
+    }
+
+    static File directory(final String type) {
+        return new File(dataDirectory, type);
+    }
+
+    static File dataFile(final String type, final String id) {
+        final File dir = directory(type);
+        return new File(dir, id + ".data");
+    }
+
+    public static File serviceFile(final String name) {
+        return new File(serviceDirectory, name + ".id");
+    }
+
+    public static File serialNumberFile(final String name) {
+        return new File(dataDirectory, "serialnumbers" + name.trim() + ".data");
+    }
+
+    static File logFile(final long id) {
+        return new File(logDirectory, "recovery" + id + ".log");
+    }
+
+    static File tmpLogFile(final long id) {
+        return new File(logDirectory, "recovery" + id + ".log.tmp");
+    }
+
+    public static File archiveLogFile(final long id) {
+        return new File(logArchiveDirectory, "recovery" + id + ".log");
+    }
+
+    static LogRange logFileRange() {
+        final LogRange logRange = new LogRange();
+        final File[] listFiles = logDirectory.listFiles();
+        if (listFiles != null) {
+            for (final File file : listFiles) {
+                final String name = file.getName();
+                final String substring = name.substring(8, name.length() - 4);
+                try {
+                    final long sequence = Long.parseLong(substring);
+                    logRange.add(sequence);
+                } catch (final NumberFormatException ignore) {
+                }
+            }
+        }
+        return logRange;
+    }
+
+    static final char DELETE = 'D';
+
+    public static final Charset ENCODING = Charset.forName("utf-8");
+
+    public static boolean isDelete(final char command) {
+        return command == Util.DELETE;
+    }
+
+    public static boolean isSave(final char command) {
+        return command != Util.DELETE;
+    }
+
+    public static boolean shouldFileExist(final char command) {
+        return command == 'D' || command == 'U';
+    }
+
+    public static InputStream trace(final InputStream inputStream, final boolean isOn) {
+        return !isOn ? inputStream : new InputStream() {
+            StringBuffer log = new StringBuffer();
+
+            @Override
+            public int read() throws IOException {
+                final int b = inputStream.read();
+                log(b);
+                return b;
+            }
+
+            private void log(final int b) {
+                log.append(b < 32 ? ("<" + b + ">" + (char) b) : (char) b);
+                // System.out.print(b < 32 ? ("<" + b + ">" + (char) b) : (char)
+                // b);
+            }
+
+            @Override
+            public int read(final byte[] b) throws IOException {
+                final int read = inputStream.read(b);
+                for (int i = 0; i < read; i++) {
+                    log(b[i]);
+                }
+                return read;
+            }
+
+            @Override
+            public int read(final byte[] b, final int off, final int len) throws IOException {
+                final int read = inputStream.read(b, off, len);
+                for (int i = 0; i < read; i++) {
+                    log(b[off + i]);
+                }
+                return read;
+            }
+
+            @Override
+            public int available() throws IOException {
+                return inputStream.available();
+            }
+
+            @Override
+            public long skip(final long n) throws IOException {
+                return inputStream.skip(n);
+            }
+
+            @Override
+            public void close() throws IOException {
+                // LOG.debug("in - " + log.toString());
+                inputStream.close();
+            }
+
+            @Override
+            public String toString() {
+                return "in#" + Long.toHexString(hashCode()) + " " + log;
+            }
+        };
+    }
+
+    public static OutputStream trace(final OutputStream outputStream, final boolean isOn) {
+        return !isOn ? outputStream : new OutputStream() {
+            StringBuffer log = new StringBuffer();
+
+            @Override
+            public void write(final int b) throws IOException {
+                log(b);
+                outputStream.write(b);
+            }
+
+            private void log(final int b) {
+                log.append(b < 32 ? ("<" + b + ">" + (char) b) : (char) b);
+                // System.out.print(b < 32 ? ("<" + b + ">" + (char) b) : (char)
+                // b);
+            }
+
+            @Override
+            public void write(final byte[] b) throws IOException {
+                for (final byte element : b) {
+                    log(element);
+                }
+                outputStream.write(b);
+            }
+
+            @Override
+            public void write(final byte[] b, final int off, final int len) throws IOException {
+                for (int i = 0; i < len; i++) {
+                    log(b[off + i]);
+                }
+                outputStream.write(b, off, len);
+            }
+
+            @Override
+            public void flush() throws IOException {
+                outputStream.flush();
+            }
+
+            @Override
+            public void close() throws IOException {
+                // LOG.debug("out - " + log.toString());
+                outputStream.close();
+            }
+
+            @Override
+            public String toString() {
+                return "out#" + Long.toHexString(hashCode()) + " " + log;
+            }
+        };
+    }
+
+    public static void closeSafely(final FileOutputStream output) {
+        if (output != null) {
+            try {
+                output.flush();
+                output.close();
+            } catch (final IOException e) {
+                // throw new ObjectAdapterRuntimeException(e);
+            }
+        }
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/cd9f2e4a/framework/objectstore/nosql/src/main/java/org/apache/isis/runtimes/dflt/objectstores/nosql/db/mongo/MongoClientCommandContext.java
----------------------------------------------------------------------
diff --git a/framework/objectstore/nosql/src/main/java/org/apache/isis/runtimes/dflt/objectstores/nosql/db/mongo/MongoClientCommandContext.java b/framework/objectstore/nosql/src/main/java/org/apache/isis/runtimes/dflt/objectstores/nosql/db/mongo/MongoClientCommandContext.java
new file mode 100644
index 0000000..97775fb
--- /dev/null
+++ b/framework/objectstore/nosql/src/main/java/org/apache/isis/runtimes/dflt/objectstores/nosql/db/mongo/MongoClientCommandContext.java
@@ -0,0 +1,75 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+
+package org.apache.isis.runtimes.dflt.objectstores.nosql.db.mongo;
+
+import org.apache.isis.core.metamodel.adapter.oid.Oid;
+import org.apache.isis.core.metamodel.adapter.version.ConcurrencyException;
+import org.apache.isis.core.metamodel.spec.ObjectSpecId;
+import org.apache.isis.runtimes.dflt.objectstores.nosql.NoSqlCommandContext;
+import org.apache.isis.runtimes.dflt.objectstores.nosql.db.StateWriter;
+import org.apache.log4j.Logger;
+
+import com.mongodb.DB;
+import com.mongodb.DBCollection;
+import com.mongodb.DBObject;
+
+
+public class MongoClientCommandContext implements NoSqlCommandContext {
+
+    private static final Logger LOG = Logger.getLogger(MongoClientCommandContext.class);
+    private final DB db;
+
+    public MongoClientCommandContext(DB db) {
+        this.db = db;
+    }
+
+    @Override
+    public void start() {}
+
+    @Override
+    public void end() {}
+
+    @Override
+    public StateWriter createStateWriter(final ObjectSpecId objectSpecId) {
+        return new MongoStateWriter(db, objectSpecId);
+    }
+
+    @Override
+    public void delete(final ObjectSpecId objectSpecId, final String mongoId, final String version, final Oid oid) {
+        final DBCollection instances = db.getCollection(objectSpecId.asString());
+        final DBObject object = instances.findOne(mongoId);
+        if (!object.get(PropertyNames.VERSION).equals(version)) {
+            throw new ConcurrencyException("Could not delete object of different version", oid);
+        }
+        instances.remove(object);
+        LOG.info("removed " + oid);
+    }
+
+    @Override
+    public void insert(final StateWriter writer) {
+        ((MongoStateWriter) writer).flush();
+    }
+
+    @Override
+    public void update(final StateWriter writer) {
+        ((MongoStateWriter) writer).flush();
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/cd9f2e4a/framework/objectstore/nosql/src/main/java/org/apache/isis/runtimes/dflt/objectstores/nosql/db/mongo/MongoDb.java
----------------------------------------------------------------------
diff --git a/framework/objectstore/nosql/src/main/java/org/apache/isis/runtimes/dflt/objectstores/nosql/db/mongo/MongoDb.java b/framework/objectstore/nosql/src/main/java/org/apache/isis/runtimes/dflt/objectstores/nosql/db/mongo/MongoDb.java
new file mode 100644
index 0000000..39af1e7
--- /dev/null
+++ b/framework/objectstore/nosql/src/main/java/org/apache/isis/runtimes/dflt/objectstores/nosql/db/mongo/MongoDb.java
@@ -0,0 +1,260 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+
+package org.apache.isis.runtimes.dflt.objectstores.nosql.db.mongo;
+
+import java.net.UnknownHostException;
+import java.util.Iterator;
+import java.util.List;
+
+import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
+import org.apache.isis.core.metamodel.spec.ObjectSpecId;
+import org.apache.isis.core.metamodel.spec.feature.ObjectAssociation;
+import org.apache.isis.runtimes.dflt.objectstores.nosql.NoSqlCommandContext;
+import org.apache.isis.runtimes.dflt.objectstores.nosql.NoSqlStoreException;
+import org.apache.isis.runtimes.dflt.objectstores.nosql.db.NoSqlDataDatabase;
+import org.apache.isis.runtimes.dflt.objectstores.nosql.db.StateReader;
+import org.apache.isis.runtimes.dflt.objectstores.nosql.db.StateWriter;
+import org.apache.isis.runtimes.dflt.objectstores.nosql.keys.KeyCreatorDefault;
+import org.apache.isis.runtimes.dflt.runtime.persistence.objectstore.transaction.PersistenceCommand;
+import org.apache.log4j.Logger;
+
+import com.mongodb.BasicDBObject;
+import com.mongodb.DB;
+import com.mongodb.DBCollection;
+import com.mongodb.DBCursor;
+import com.mongodb.DBObject;
+import com.mongodb.Mongo;
+import com.mongodb.MongoException;
+
+public class MongoDb implements NoSqlDataDatabase {
+
+	private static final String SERIALNUMBERS_COLLECTION_NAME = "serialnumbers";
+
+	private static final Logger LOG = Logger.getLogger(MongoDb.class);
+	
+	private static final int DEFAULT_PORT = 27017;
+
+    private final String host;
+    private final int port;
+    private final String dbName;
+    private final KeyCreatorDefault keyCreator;
+    
+	private Mongo mongo;
+	private DB db;
+
+    public MongoDb(final String host, final int port, final String name, final KeyCreatorDefault keyCreator) {
+        this.host = host;
+        this.port = port == 0 ? DEFAULT_PORT : port;
+        this.dbName = name;
+        this.keyCreator = keyCreator;
+    }
+
+    public KeyCreatorDefault getKeyCreator() {
+        return keyCreator;
+    }
+
+    @Override
+    public void open() {
+        try {
+            if (mongo == null) {
+                mongo = new Mongo(host, port);
+                db = mongo.getDB(dbName);
+                db.setWriteConcern(com.mongodb.WriteConcern.SAFE);
+                LOG.info("opened database (" + dbName + "): " + mongo);
+            } else {
+                LOG.info(" using opened database " + db);
+            }
+        } catch (final UnknownHostException e) {
+            throw new NoSqlStoreException(e);
+        } catch (final MongoException e) {
+            throw new NoSqlStoreException(e);
+        }
+    }
+
+    @Override
+    public void close() {
+    }
+
+    public NoSqlCommandContext createTransactionContext() {
+        return null;
+    }
+
+    //////////////////////////////////////////////////
+    // contains data
+    //////////////////////////////////////////////////
+
+    @Override
+    public boolean containsData() {
+        return db.getCollectionNames().size() > 0;
+    }
+
+    
+    //////////////////////////////////////////////////
+    // serial numbers
+    //////////////////////////////////////////////////
+    
+    @Override
+    public long nextSerialNumberBatch(final ObjectSpecId name, final int batchSize) {
+        long next = readSerialNumber();
+        writeSerialNumber(next + batchSize);
+        return next + 1;
+    }
+
+    private void writeSerialNumber(final long serialNumber) {
+        final DBCollection system = db.getCollection(SERIALNUMBERS_COLLECTION_NAME);
+        DBObject object = system.findOne();
+        if (object == null) {
+            object = new BasicDBObject();
+        }
+        object.put("next-id", Long.toString(serialNumber));
+        system.save(object);
+        LOG.info("serial number written: " + serialNumber);
+    }
+
+    private long readSerialNumber() {
+        final DBCollection system = db.getCollection(SERIALNUMBERS_COLLECTION_NAME);
+        final DBObject data = system.findOne();
+        if (data == null) {
+            return 0;
+        } else {
+            final String number = (String) data.get("next-id");
+            LOG.info("serial number read: " + number);
+            return Long.valueOf(number);
+        }
+    }
+
+    //////////////////////////////////////////////////
+    // hasInstances, instancesOf
+    //////////////////////////////////////////////////
+
+    @Override
+    public boolean hasInstances(final ObjectSpecId objectSpecId) {
+        final DBCollection instances = db.getCollection(objectSpecId.asString());
+        return instances.getCount() > 0;
+    }
+
+    @Override
+    public Iterator<StateReader> instancesOf(final ObjectSpecId objectSpecId) {
+        final DBCollection instances = db.getCollection(objectSpecId.asString());
+        final DBCursor cursor = instances.find();
+        LOG.info("searching for instances of: " + objectSpecId);
+        return new Iterator<StateReader>() {
+            @Override
+            public boolean hasNext() {
+                return cursor.hasNext();
+            }
+
+            @Override
+            public StateReader next() {
+                return new MongoStateReader(cursor.next());
+            }
+
+            @Override
+            public void remove() {
+                throw new NoSqlStoreException("Can't remove elements");
+            }
+
+        };
+    }
+    
+    @Override
+    public Iterator<StateReader> instancesOf(ObjectSpecId objectSpecId, ObjectAdapter pattern) {
+        final DBCollection instances = db.getCollection(objectSpecId.asString());
+
+        // REVIEW check the right types are used in matches 
+        final BasicDBObject query = new BasicDBObject();
+        for ( ObjectAssociation association  : pattern.getSpecification().getAssociations()) {
+            ObjectAdapter field = association.get(pattern);
+            if (!association.isEmpty(pattern)) {
+                if (field.isValue()) {
+                    query.put(association.getIdentifier().getMemberName(), field.titleString());
+                } else if (association.isOneToOneAssociation()) {
+                    query.put(association.getIdentifier().getMemberName(), field.getOid());
+                }
+            }
+        }
+        final DBCursor cursor = instances.find(query);
+        LOG.info("searching for instances of: " + objectSpecId);
+        return new Iterator<StateReader>() {
+            @Override
+            public boolean hasNext() {
+                return cursor.hasNext();
+            }
+
+            @Override
+            public StateReader next() {
+                return new MongoStateReader(cursor.next());
+            }
+
+            @Override
+            public void remove() {
+                throw new NoSqlStoreException("Can't remove elements");
+            }
+
+        };
+    }
+
+    @Override
+    public StateReader getInstance(final String key, final ObjectSpecId objectSpecId) {
+        return new MongoStateReader(db, objectSpecId, key);
+    }
+
+    //////////////////////////////////////////////////
+    // write, delete
+    //////////////////////////////////////////////////
+
+    public StateWriter createStateWriter(final ObjectSpecId objectSpecId) {
+        return new MongoStateWriter(db, objectSpecId);
+    }
+
+
+    @Override
+    public void write(final List<PersistenceCommand> commands) {
+        final NoSqlCommandContext context = new MongoClientCommandContext(db);
+        for (final PersistenceCommand command : commands) {
+            command.execute(context);
+        }
+    }
+
+
+    //////////////////////////////////////////////////
+    // services
+    //////////////////////////////////////////////////
+
+    @Override
+    public void addService(final ObjectSpecId objectSpecId, final String key) {
+        final DBCollection services = db.getCollection("services");
+        services.insert(new BasicDBObject().append("name", objectSpecId.asString()).append("key", key));
+        LOG.info("service added " + objectSpecId + ":" + key);
+    }
+
+    @Override
+    public String getService(final ObjectSpecId objectSpecId) {
+        final DBCollection services = db.getCollection("services");
+        final DBObject object = services.findOne(new BasicDBObject().append("name", objectSpecId.asString()));
+        if (object == null) {
+            return null;
+        } else {
+            final String id = (String) object.get("key");
+            LOG.info("service found " + objectSpecId + ":" + id);
+            return id;
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/cd9f2e4a/framework/objectstore/nosql/src/main/java/org/apache/isis/runtimes/dflt/objectstores/nosql/db/mongo/MongoPersistorMechanismInstaller.java
----------------------------------------------------------------------
diff --git a/framework/objectstore/nosql/src/main/java/org/apache/isis/runtimes/dflt/objectstores/nosql/db/mongo/MongoPersistorMechanismInstaller.java b/framework/objectstore/nosql/src/main/java/org/apache/isis/runtimes/dflt/objectstores/nosql/db/mongo/MongoPersistorMechanismInstaller.java
new file mode 100644
index 0000000..cf3832e
--- /dev/null
+++ b/framework/objectstore/nosql/src/main/java/org/apache/isis/runtimes/dflt/objectstores/nosql/db/mongo/MongoPersistorMechanismInstaller.java
@@ -0,0 +1,50 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+
+package org.apache.isis.runtimes.dflt.objectstores.nosql.db.mongo;
+
+import org.apache.isis.core.commons.config.ConfigurationConstants;
+import org.apache.isis.core.commons.config.IsisConfiguration;
+import org.apache.isis.runtimes.dflt.objectstores.nosql.db.NoSqlDataDatabase;
+import org.apache.isis.runtimes.dflt.objectstores.nosql.db.NoSqlPersistorMechanismInstaller;
+import org.apache.isis.runtimes.dflt.objectstores.nosql.keys.KeyCreatorDefault;
+
+public class MongoPersistorMechanismInstaller extends NoSqlPersistorMechanismInstaller {
+
+    private static final String STRING = ConfigurationConstants.ROOT + "nosql.mongodb.";
+    private static final String DB_HOST = STRING + "host";
+    private static final String DB_PORT = STRING + "port";
+    private static final String DB_NAME = STRING + "name";
+
+    public MongoPersistorMechanismInstaller() {
+        super("mongodb");
+    }
+
+    @Override
+    protected NoSqlDataDatabase createNoSqlDatabase(final IsisConfiguration configuration) {
+        NoSqlDataDatabase db;
+        final String host = configuration.getString(DB_HOST, "localhost");
+        final int port = configuration.getInteger(DB_PORT, 0);
+        final String name = configuration.getString(DB_NAME, "isis");
+        final KeyCreatorDefault keyCreator = new KeyCreatorDefault();
+        db = new MongoDb(host, port, name, keyCreator);
+        return db;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/cd9f2e4a/framework/objectstore/nosql/src/main/java/org/apache/isis/runtimes/dflt/objectstores/nosql/db/mongo/MongoStateReader.java
----------------------------------------------------------------------
diff --git a/framework/objectstore/nosql/src/main/java/org/apache/isis/runtimes/dflt/objectstores/nosql/db/mongo/MongoStateReader.java b/framework/objectstore/nosql/src/main/java/org/apache/isis/runtimes/dflt/objectstores/nosql/db/mongo/MongoStateReader.java
new file mode 100644
index 0000000..d4c059b
--- /dev/null
+++ b/framework/objectstore/nosql/src/main/java/org/apache/isis/runtimes/dflt/objectstores/nosql/db/mongo/MongoStateReader.java
@@ -0,0 +1,121 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+
+package org.apache.isis.runtimes.dflt.objectstores.nosql.db.mongo;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.isis.core.metamodel.spec.ObjectSpecId;
+import org.apache.isis.runtimes.dflt.objectstores.nosql.db.StateReader;
+import org.apache.isis.runtimes.dflt.runtime.persistence.ObjectNotFoundException;
+import org.apache.log4j.Logger;
+
+import com.mongodb.BasicDBList;
+import com.mongodb.DB;
+import com.mongodb.DBCollection;
+import com.mongodb.DBObject;
+
+public class MongoStateReader implements StateReader {
+    
+    private static final Logger LOG = Logger.getLogger(MongoStateReader.class);
+    private final DBObject instance;
+
+    public MongoStateReader(final DB db, final ObjectSpecId objectSpecId, final String mongoId) {
+        final DBCollection instances = db.getCollection(objectSpecId.asString());
+        instance = instances.findOne(mongoId);
+        if (instance == null) {
+            throw new ObjectNotFoundException(mongoId);
+        }
+        if(LOG.isDebugEnabled()) {
+            LOG.debug("loading " + instance);
+        }
+    }
+
+    public MongoStateReader(final DBObject instance) {
+        this.instance = instance;
+        if(LOG.isDebugEnabled()) {
+            LOG.debug("loading " + instance);
+        }
+    }
+
+    @Override
+    public long readLongField(final String id) {
+        final Object value = instance.get(id);
+        if (value == null || value.equals("null")) {
+            return 0;
+        } 
+        return Long.valueOf((String) value);
+    }
+
+    @Override
+    public String readField(final String name) {
+        final Object value = instance.get(name);
+        if (value == null || value.equals("null")) {
+            return null;
+        } else {
+            return (String) value;
+        }
+    }
+
+    @Override
+    public String readEncrytionType() {
+        return (String) instance.get(PropertyNames.ENCRYPT);
+    }
+
+    @Override
+    public String readOid() {
+        return readField(PropertyNames.OID);
+    }
+
+    @Override
+    public String readVersion() {
+        return readField(PropertyNames.VERSION);
+    }
+
+    @Override
+    public String readUser() {
+        return readField(PropertyNames.USER);
+    }
+
+    @Override
+    public String readTime() {
+        return readField(PropertyNames.TIME);
+    }
+
+    @Override
+    public StateReader readAggregate(final String id) {
+        DBObject object = (DBObject) instance.get(id);
+        return object == null ? null : new MongoStateReader(object);
+    }
+
+    @Override
+    public List<StateReader> readCollection(final String id) {
+        BasicDBList array = (BasicDBList) instance.get(id);
+        final List<StateReader> readers = new ArrayList<StateReader>();
+        if (array != null) {
+            final int size = array.size();
+            for (int i = 0; i < size; i++) {
+                readers.add(new MongoStateReader((DBObject) array.get(i)));
+            }
+        }
+        return readers;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/cd9f2e4a/framework/objectstore/nosql/src/main/java/org/apache/isis/runtimes/dflt/objectstores/nosql/db/mongo/MongoStateWriter.java
----------------------------------------------------------------------
diff --git a/framework/objectstore/nosql/src/main/java/org/apache/isis/runtimes/dflt/objectstores/nosql/db/mongo/MongoStateWriter.java b/framework/objectstore/nosql/src/main/java/org/apache/isis/runtimes/dflt/objectstores/nosql/db/mongo/MongoStateWriter.java
new file mode 100644
index 0000000..2996b2e
--- /dev/null
+++ b/framework/objectstore/nosql/src/main/java/org/apache/isis/runtimes/dflt/objectstores/nosql/db/mongo/MongoStateWriter.java
@@ -0,0 +1,129 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+
+package org.apache.isis.runtimes.dflt.objectstores.nosql.db.mongo;
+
+import java.util.List;
+
+import org.apache.isis.core.metamodel.adapter.oid.OidMarshaller;
+import org.apache.isis.core.metamodel.adapter.oid.RootOid;
+import org.apache.isis.core.metamodel.adapter.oid.TypedOid;
+import org.apache.isis.core.metamodel.spec.ObjectSpecId;
+import org.apache.isis.runtimes.dflt.objectstores.nosql.db.StateWriter;
+import org.apache.isis.runtimes.dflt.runtime.system.context.IsisContext;
+import org.apache.log4j.Logger;
+
+import com.google.common.collect.Lists;
+import com.mongodb.BasicDBObject;
+import com.mongodb.DB;
+import com.mongodb.DBCollection;
+
+public class MongoStateWriter implements StateWriter {
+    
+    private static final Logger LOG = Logger.getLogger(MongoStateWriter.class);
+    private final DB db;
+    private final BasicDBObject dbObject;
+    private DBCollection instances;
+
+    public MongoStateWriter(final DB db, final ObjectSpecId objectSpecId) {
+        this(db);
+        instances = db.getCollection(objectSpecId.asString());
+    }
+
+    private MongoStateWriter(final DB db) {
+        this.db = db;
+        dbObject = new BasicDBObject();
+    }
+
+    public void flush() {
+        instances.save(dbObject);
+        if(LOG.isDebugEnabled()) {
+            LOG.debug("saved " + dbObject);
+        }
+    }
+
+    @Override
+    public void writeOid(final TypedOid typedOid) {
+        writeField(PropertyNames.OID, typedOid.enString(getOidMarshaller()));
+        if(typedOid instanceof RootOid) {
+            RootOid rootOid = (RootOid) typedOid;
+            writeField(PropertyNames.MONGO_INTERNAL_ID, rootOid.getIdentifier());
+        }
+    }
+
+    @Override
+    public void writeField(final String id, final String data) {
+        dbObject.put(id, data);
+    }
+
+    @Override
+    public void writeField(final String id, final long l) {
+        dbObject.put(id, Long.toString(l));
+    }
+
+    @Override
+    public void writeEncryptionType(final String type) {
+        writeField(PropertyNames.ENCRYPT, type);
+    }
+
+    @Override
+    public void writeVersion(final String currentVersion, final String newVersion) {
+         writeField(PropertyNames.VERSION, newVersion);
+    }
+
+    @Override
+    public void writeTime(final String time) {
+        writeField(PropertyNames.TIME, time);
+    }
+
+    @Override
+    public void writeUser(final String user) {
+        writeField(PropertyNames.USER, user);
+    }
+
+    @Override
+    public StateWriter addAggregate(final String id) {
+        final MongoStateWriter stateWriter = new MongoStateWriter(db);
+        dbObject.put(id, stateWriter.dbObject);
+        return stateWriter;
+    }
+
+    @Override
+    public StateWriter createElementWriter() {
+        return new MongoStateWriter(db);
+    }
+
+    @Override
+    public void writeCollection(final String id, final List<StateWriter> elements) {
+        final List<BasicDBObject> collection = Lists.newArrayList();
+        for (final StateWriter writer : elements) {
+            collection.add(((MongoStateWriter) writer).dbObject);
+        }
+        dbObject.put(id, collection);
+    }
+    
+    // ///////////////////////////////////////////////////////////////////
+    // dependencies
+    // ///////////////////////////////////////////////////////////////////
+
+    protected OidMarshaller getOidMarshaller() {
+		return IsisContext.getOidMarshaller();
+	}
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/cd9f2e4a/framework/objectstore/nosql/src/main/java/org/apache/isis/runtimes/dflt/objectstores/nosql/db/mongo/PropertyNames.java
----------------------------------------------------------------------
diff --git a/framework/objectstore/nosql/src/main/java/org/apache/isis/runtimes/dflt/objectstores/nosql/db/mongo/PropertyNames.java b/framework/objectstore/nosql/src/main/java/org/apache/isis/runtimes/dflt/objectstores/nosql/db/mongo/PropertyNames.java
new file mode 100644
index 0000000..adedb84
--- /dev/null
+++ b/framework/objectstore/nosql/src/main/java/org/apache/isis/runtimes/dflt/objectstores/nosql/db/mongo/PropertyNames.java
@@ -0,0 +1,37 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+
+package org.apache.isis.runtimes.dflt.objectstores.nosql.db.mongo;
+
+public final class PropertyNames {
+    
+    private PropertyNames(){}
+    
+    static final String ENCRYPT = "_encrypt";
+    
+//    static final String TYPE = "_type";
+//    static final String ID = "_id";
+    
+    static final String MONGO_INTERNAL_ID = "_id";
+    static final String OID = "_oid";
+    static final String VERSION = "_version";
+    static final String TIME = "_time";
+    static final String USER = "_user";
+}
+

http://git-wip-us.apache.org/repos/asf/isis/blob/cd9f2e4a/framework/objectstore/nosql/src/main/java/org/apache/isis/runtimes/dflt/objectstores/nosql/encryption/DataEncryption.java
----------------------------------------------------------------------
diff --git a/framework/objectstore/nosql/src/main/java/org/apache/isis/runtimes/dflt/objectstores/nosql/encryption/DataEncryption.java b/framework/objectstore/nosql/src/main/java/org/apache/isis/runtimes/dflt/objectstores/nosql/encryption/DataEncryption.java
new file mode 100644
index 0000000..26a1802
--- /dev/null
+++ b/framework/objectstore/nosql/src/main/java/org/apache/isis/runtimes/dflt/objectstores/nosql/encryption/DataEncryption.java
@@ -0,0 +1,33 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+package org.apache.isis.runtimes.dflt.objectstores.nosql.encryption;
+
+import org.apache.isis.core.commons.config.IsisConfiguration;
+
+public interface DataEncryption {
+
+    void init(IsisConfiguration configuration);
+    
+    String getType();
+
+    String encrypt(String plainText);
+
+    String decrypt(String encryptedText);
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/cd9f2e4a/framework/objectstore/nosql/src/main/java/org/apache/isis/runtimes/dflt/objectstores/nosql/encryption/aes/DataEncryptionAes.java
----------------------------------------------------------------------
diff --git a/framework/objectstore/nosql/src/main/java/org/apache/isis/runtimes/dflt/objectstores/nosql/encryption/aes/DataEncryptionAes.java b/framework/objectstore/nosql/src/main/java/org/apache/isis/runtimes/dflt/objectstores/nosql/encryption/aes/DataEncryptionAes.java
new file mode 100644
index 0000000..ec7185c
--- /dev/null
+++ b/framework/objectstore/nosql/src/main/java/org/apache/isis/runtimes/dflt/objectstores/nosql/encryption/aes/DataEncryptionAes.java
@@ -0,0 +1,74 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+package org.apache.isis.runtimes.dflt.objectstores.nosql.encryption.aes;
+
+import javax.crypto.Cipher;
+import javax.crypto.spec.SecretKeySpec;
+
+import org.apache.isis.core.commons.config.IsisConfiguration;
+import org.apache.isis.runtimes.dflt.objectstores.nosql.NoSqlStoreException;
+import org.apache.isis.runtimes.dflt.objectstores.nosql.encryption.DataEncryption;
+
+/**
+ * NOTE this does not work at the moment
+ */
+public class DataEncryptionAes implements DataEncryption {
+
+    private static final String AES = "AES";
+    private final byte[] specKey;
+
+    public DataEncryptionAes() {
+        specKey = new byte[] { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17 };
+    }
+
+    @Override
+    public void init(final IsisConfiguration configuration) {
+    }
+
+    @Override
+    public String getType() {
+        return AES;
+    }
+
+    @Override
+    public String encrypt(final String plainText) {
+        try {
+            final SecretKeySpec key = new SecretKeySpec(specKey, AES);
+            final Cipher cipher = Cipher.getInstance("AES/ECB/PKCS7Padding");
+            cipher.init(Cipher.ENCRYPT_MODE, key);
+            return new String(cipher.doFinal(plainText.getBytes()));
+        } catch (final Exception e) {
+            throw new NoSqlStoreException(e);
+        }
+    }
+
+    @Override
+    public String decrypt(final String encryptedText) {
+        try {
+            final SecretKeySpec key = new SecretKeySpec(specKey, AES);
+            final Cipher cipher = Cipher.getInstance("AES/ECB/PKCS7Padding");
+            cipher.init(Cipher.DECRYPT_MODE, key);
+            final byte[] decrypted = cipher.doFinal(encryptedText.getBytes());
+            return new String(decrypted);
+        } catch (final Exception e) {
+            throw new NoSqlStoreException(e);
+        }
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/cd9f2e4a/framework/objectstore/nosql/src/main/java/org/apache/isis/runtimes/dflt/objectstores/nosql/encryption/blowfish/DataEncryptionBlowfishAbstract.java
----------------------------------------------------------------------
diff --git a/framework/objectstore/nosql/src/main/java/org/apache/isis/runtimes/dflt/objectstores/nosql/encryption/blowfish/DataEncryptionBlowfishAbstract.java b/framework/objectstore/nosql/src/main/java/org/apache/isis/runtimes/dflt/objectstores/nosql/encryption/blowfish/DataEncryptionBlowfishAbstract.java
new file mode 100644
index 0000000..1c09e84
--- /dev/null
+++ b/framework/objectstore/nosql/src/main/java/org/apache/isis/runtimes/dflt/objectstores/nosql/encryption/blowfish/DataEncryptionBlowfishAbstract.java
@@ -0,0 +1,70 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+package org.apache.isis.runtimes.dflt.objectstores.nosql.encryption.blowfish;
+
+import javax.crypto.Cipher;
+import javax.crypto.spec.SecretKeySpec;
+
+import org.apache.isis.core.commons.config.IsisConfiguration;
+import org.apache.isis.runtimes.dflt.objectstores.nosql.NoSqlStoreException;
+import org.apache.isis.runtimes.dflt.objectstores.nosql.encryption.DataEncryption;
+
+public abstract class DataEncryptionBlowfishAbstract implements DataEncryption {
+
+    private static final String BLOWFISH = "Blowfish";
+    private byte[] specKey;
+
+    @Override
+    public void init(final IsisConfiguration configuration) {
+        specKey = secretKey(configuration);
+    }
+
+    public abstract byte[] secretKey(IsisConfiguration configuration);
+
+    @Override
+    public String getType() {
+        return BLOWFISH;
+    }
+
+    @Override
+    public String encrypt(final String plainText) {
+        try {
+            final SecretKeySpec key = new SecretKeySpec(specKey, BLOWFISH);
+            final Cipher cipher = Cipher.getInstance(BLOWFISH);
+            cipher.init(Cipher.ENCRYPT_MODE, key);
+            return new String(cipher.doFinal(plainText.getBytes()));
+        } catch (final Exception e) {
+            throw new NoSqlStoreException(e);
+        }
+    }
+
+    @Override
+    public String decrypt(final String encryptedText) {
+        try {
+            final SecretKeySpec key = new SecretKeySpec(specKey, BLOWFISH);
+            final Cipher cipher = Cipher.getInstance(BLOWFISH);
+            cipher.init(Cipher.DECRYPT_MODE, key);
+            final byte[] decrypted = cipher.doFinal(encryptedText.getBytes());
+            return new String(decrypted);
+        } catch (final Exception e) {
+            throw new NoSqlStoreException(e);
+        }
+    }
+
+}