From 5e11942d25d589c1a60839d1eac605558a802051 Mon Sep 17 00:00:00 2001
From: ribeaudc <ribeaudc>
Date: Mon, 6 Oct 2008 13:14:02 +0000
Subject: [PATCH] [LMS-587] change: - Improve BDS read-only mode.

SVN: 8552
---
 .../cisd/bds/storage/DirectoryProxy.java      |  91 +++++++++
 .../systemsx/cisd/bds/storage/FileProxy.java  |  69 +++++++
 .../systemsx/cisd/bds/storage/NodeProxy.java  |  80 ++++++++
 .../cisd/bds/v1_0/DataStructureProxyV1_0.java |  10 +-
 .../cisd/bds/v1_0/ReadOnlyDirectory.java      | 181 ++++++++++++++++++
 .../systemsx/cisd/bds/v1_0/ReadOnlyFile.java  |  74 +++++++
 .../systemsx/cisd/bds/v1_0/ReadOnlyNode.java  |  79 ++++++++
 7 files changed, 581 insertions(+), 3 deletions(-)
 create mode 100644 bds/source/java/ch/systemsx/cisd/bds/storage/DirectoryProxy.java
 create mode 100644 bds/source/java/ch/systemsx/cisd/bds/storage/FileProxy.java
 create mode 100644 bds/source/java/ch/systemsx/cisd/bds/storage/NodeProxy.java
 create mode 100644 bds/source/java/ch/systemsx/cisd/bds/v1_0/ReadOnlyDirectory.java
 create mode 100644 bds/source/java/ch/systemsx/cisd/bds/v1_0/ReadOnlyFile.java
 create mode 100644 bds/source/java/ch/systemsx/cisd/bds/v1_0/ReadOnlyNode.java

diff --git a/bds/source/java/ch/systemsx/cisd/bds/storage/DirectoryProxy.java b/bds/source/java/ch/systemsx/cisd/bds/storage/DirectoryProxy.java
new file mode 100644
index 00000000000..26b0277be72
--- /dev/null
+++ b/bds/source/java/ch/systemsx/cisd/bds/storage/DirectoryProxy.java
@@ -0,0 +1,91 @@
+/*
+ * Copyright 2008 ETH Zuerich, CISD
+ *
+ * Licensed 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 ch.systemsx.cisd.bds.storage;
+
+import java.io.File;
+import java.util.Iterator;
+import java.util.List;
+
+/**
+ * A {@link IDirectory} implementation which getDirectory()s all the interface method calls to the
+ * encapsulated object.
+ * 
+ * @author Christian Ribeaud
+ */
+public class DirectoryProxy extends NodeProxy implements IDirectory
+{
+    public DirectoryProxy(final IDirectory delegate)
+    {
+        super(delegate);
+        assert delegate instanceof DirectoryProxy == false;
+    }
+
+    protected final IDirectory getDirectory()
+    {
+        return (IDirectory) delegate;
+    }
+
+    //
+    // IDirectory
+    //
+
+    public INode addFile(final File file, final String nameOrNull, final boolean move)
+    {
+        return getDirectory().addFile(file, nameOrNull, move);
+    }
+
+    public IFile addKeyValuePair(final String key, final String value)
+    {
+        return getDirectory().addKeyValuePair(key, value);
+    }
+
+    public Iterator<INode> iterator()
+    {
+        return getDirectory().iterator();
+    }
+
+    public List<IDirectory> listDirectories(final boolean recursive)
+    {
+        return getDirectory().listDirectories(recursive);
+    }
+
+    public List<IFile> listFiles(final String[] extensionsOrNull, final boolean recursive)
+    {
+        return getDirectory().listFiles(extensionsOrNull, recursive);
+    }
+
+    public IDirectory makeDirectory(final String name)
+    {
+        return getDirectory().makeDirectory(name);
+    }
+
+    public void removeNode(final INode node)
+    {
+        getDirectory().removeNode(node);
+    }
+
+    public ILink tryAddLink(final String name, final INode node)
+    {
+        return getDirectory().tryAddLink(name, node);
+    }
+
+    public INode tryGetNode(final String name)
+    {
+        return getDirectory().tryGetNode(name);
+    }
+
+}
\ No newline at end of file
diff --git a/bds/source/java/ch/systemsx/cisd/bds/storage/FileProxy.java b/bds/source/java/ch/systemsx/cisd/bds/storage/FileProxy.java
new file mode 100644
index 00000000000..65fb90a556f
--- /dev/null
+++ b/bds/source/java/ch/systemsx/cisd/bds/storage/FileProxy.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright 2008 ETH Zuerich, CISD
+ *
+ * Licensed 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 ch.systemsx.cisd.bds.storage;
+
+import java.io.InputStream;
+import java.util.List;
+
+/**
+ * A {@link IFile} implementation which delegates all the interface method calls to the encapsulated
+ * object.
+ * 
+ * @author Christian Ribeaud
+ */
+public class FileProxy extends NodeProxy implements IFile
+{
+    public FileProxy(final IFile delegate)
+    {
+        super(delegate);
+        assert delegate instanceof FileProxy == false;
+    }
+
+    protected final IFile getFile()
+    {
+        return (IFile) delegate;
+    }
+
+    //
+    // IFile
+    //
+
+    public byte[] getBinaryContent()
+    {
+        return getFile().getBinaryContent();
+    }
+
+    public String getExactStringContent()
+    {
+        return getFile().getExactStringContent();
+    }
+
+    public InputStream getInputStream()
+    {
+        return getFile().getInputStream();
+    }
+
+    public String getStringContent()
+    {
+        return getFile().getStringContent();
+    }
+
+    public List<String> getStringContentList()
+    {
+        return getFile().getStringContentList();
+    }
+}
diff --git a/bds/source/java/ch/systemsx/cisd/bds/storage/NodeProxy.java b/bds/source/java/ch/systemsx/cisd/bds/storage/NodeProxy.java
new file mode 100644
index 00000000000..a31a6a61e75
--- /dev/null
+++ b/bds/source/java/ch/systemsx/cisd/bds/storage/NodeProxy.java
@@ -0,0 +1,80 @@
+/*
+ * Copyright 2008 ETH Zuerich, CISD
+ *
+ * Licensed 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 ch.systemsx.cisd.bds.storage;
+
+import java.io.File;
+
+/**
+ * A {@link INode} implementation which delegates all the interface method calls to the encapsulated
+ * object.
+ * 
+ * @author Christian Ribeaud
+ */
+public class NodeProxy implements INode
+{
+    final INode delegate;
+
+    public NodeProxy(final INode delegate)
+    {
+        this.delegate = delegate;
+        assert delegate instanceof NodeProxy == false;
+    }
+
+    //
+    // INode
+    //
+
+    public void extractTo(final File directory)
+    {
+        delegate.extractTo(directory);
+    }
+
+    public String getName()
+    {
+        return delegate.getName();
+    }
+
+    public String getPath()
+    {
+        return delegate.getPath();
+    }
+
+    public boolean isValid()
+    {
+        return delegate.isValid();
+    }
+
+    public void moveTo(final File directory)
+    {
+        delegate.moveTo(directory);
+    }
+
+    public IDirectory tryAsDirectory()
+    {
+        return delegate.tryAsDirectory();
+    }
+
+    public IFile tryAsFile()
+    {
+        return delegate.tryAsFile();
+    }
+
+    public IDirectory tryGetParent()
+    {
+        return delegate.tryGetParent();
+    }
+}
diff --git a/bds/source/java/ch/systemsx/cisd/bds/v1_0/DataStructureProxyV1_0.java b/bds/source/java/ch/systemsx/cisd/bds/v1_0/DataStructureProxyV1_0.java
index 01408fa4b70..0ab339f7280 100644
--- a/bds/source/java/ch/systemsx/cisd/bds/v1_0/DataStructureProxyV1_0.java
+++ b/bds/source/java/ch/systemsx/cisd/bds/v1_0/DataStructureProxyV1_0.java
@@ -55,7 +55,7 @@ public class DataStructureProxyV1_0 implements IDataStructureV1_0
     {
         if (mode == Mode.READ_ONLY)
         {
-            throw new UnsupportedOperationException("Unsupported operation in read-only mode.");
+            ReadOnlyNode.denyAccess();
         }
     }
 
@@ -173,12 +173,16 @@ public class DataStructureProxyV1_0 implements IDataStructureV1_0
 
     public final IDirectory getOriginalData()
     {
-        return dataStructure.getOriginalData();
+        final IDirectory originalData = dataStructure.getOriginalData();
+        return mode == Mode.READ_ONLY ? ReadOnlyDirectory.tryCreateReadOnlyDirectory(originalData)
+                : originalData;
     }
 
     public final IDirectory getStandardData()
     {
-        return dataStructure.getStandardData();
+        final IDirectory standardData = dataStructure.getStandardData();
+        return mode == Mode.READ_ONLY ? ReadOnlyDirectory.tryCreateReadOnlyDirectory(standardData)
+                : standardData;
     }
 
     public final Sample getSample()
diff --git a/bds/source/java/ch/systemsx/cisd/bds/v1_0/ReadOnlyDirectory.java b/bds/source/java/ch/systemsx/cisd/bds/v1_0/ReadOnlyDirectory.java
new file mode 100644
index 00000000000..ec2ed8858f8
--- /dev/null
+++ b/bds/source/java/ch/systemsx/cisd/bds/v1_0/ReadOnlyDirectory.java
@@ -0,0 +1,181 @@
+/*
+ * Copyright 2008 ETH Zuerich, CISD
+ *
+ * Licensed 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 ch.systemsx.cisd.bds.v1_0;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
+
+import ch.systemsx.cisd.bds.storage.DirectoryProxy;
+import ch.systemsx.cisd.bds.storage.IDirectory;
+import ch.systemsx.cisd.bds.storage.IFile;
+import ch.systemsx.cisd.bds.storage.ILink;
+import ch.systemsx.cisd.bds.storage.INode;
+
+/**
+ * An {@link IDirectory} implementation which denies access to write operations.
+ * 
+ * @author Christian Ribeaud
+ */
+final class ReadOnlyDirectory extends DirectoryProxy
+{
+    ReadOnlyDirectory(final IDirectory delegate)
+    {
+        super(delegate);
+    }
+
+    final static ReadOnlyDirectory tryCreateReadOnlyDirectory(final IDirectory directory)
+    {
+        if (directory == null)
+        {
+            return null;
+        }
+        return new ReadOnlyDirectory(directory);
+    }
+
+    //
+    // DirectoryProxy
+    //
+
+    // Access denied
+
+    @Override
+    public final INode addFile(final File file, final String nameOrNull, final boolean move)
+    {
+        ReadOnlyNode.denyAccess();
+        return null;
+    }
+
+    @Override
+    public final IFile addKeyValuePair(final String key, final String value)
+    {
+        ReadOnlyNode.denyAccess();
+        return null;
+    }
+
+    @Override
+    public final IDirectory makeDirectory(final String name)
+    {
+        ReadOnlyNode.denyAccess();
+        return null;
+    }
+
+    @Override
+    public final void moveTo(final File directory)
+    {
+        ReadOnlyNode.denyAccess();
+    }
+
+    @Override
+    public final void removeNode(final INode node)
+    {
+        ReadOnlyNode.denyAccess();
+    }
+
+    @Override
+    public final ILink tryAddLink(final String name, final INode node)
+    {
+        ReadOnlyNode.denyAccess();
+        return null;
+    }
+
+    // Read-only return value
+
+    @Override
+    public final Iterator<INode> iterator()
+    {
+        return new ImmutableIterator(super.iterator());
+    }
+
+    @Override
+    public final List<IDirectory> listDirectories(final boolean recursive)
+    {
+        final List<IDirectory> directories = super.listDirectories(recursive);
+        final List<IDirectory> list = new ArrayList<IDirectory>(directories.size());
+        for (final IDirectory directory : directories)
+        {
+            list.add(tryCreateReadOnlyDirectory(directory));
+        }
+        return Collections.unmodifiableList(list);
+    }
+
+    @Override
+    public final List<IFile> listFiles(final String[] extensionsOrNull, final boolean recursive)
+    {
+        final List<IFile> files = super.listFiles(extensionsOrNull, recursive);
+        final List<IFile> list = new ArrayList<IFile>(files.size());
+        for (final IFile file : files)
+        {
+            list.add(ReadOnlyFile.tryCreateReadOnlyFile(file));
+        }
+        return Collections.unmodifiableList(list);
+    }
+
+    @Override
+    public final IDirectory tryAsDirectory()
+    {
+        return tryCreateReadOnlyDirectory(super.tryAsDirectory());
+    }
+
+    @Override
+    public final IFile tryAsFile()
+    {
+        return ReadOnlyFile.tryCreateReadOnlyFile(super.tryAsFile());
+    }
+
+    @Override
+    public final IDirectory tryGetParent()
+    {
+        return tryCreateReadOnlyDirectory(super.tryGetParent());
+    }
+
+    //
+    // Helper classes
+    //
+
+    private final static class ImmutableIterator implements Iterator<INode>
+    {
+
+        private final Iterator<INode> delegate;
+
+        ImmutableIterator(final Iterator<INode> delegate)
+        {
+            this.delegate = delegate;
+        }
+
+        //
+        // Iterator
+        //
+
+        public final boolean hasNext()
+        {
+            return delegate.hasNext();
+        }
+
+        public final INode next()
+        {
+            return ReadOnlyNode.tryCreateReadOnlyNode(delegate.next());
+        }
+
+        public final void remove()
+        {
+            ReadOnlyNode.denyAccess();
+        }
+    }
+}
diff --git a/bds/source/java/ch/systemsx/cisd/bds/v1_0/ReadOnlyFile.java b/bds/source/java/ch/systemsx/cisd/bds/v1_0/ReadOnlyFile.java
new file mode 100644
index 00000000000..620e26d880f
--- /dev/null
+++ b/bds/source/java/ch/systemsx/cisd/bds/v1_0/ReadOnlyFile.java
@@ -0,0 +1,74 @@
+/*
+ * Copyright 2008 ETH Zuerich, CISD
+ *
+ * Licensed 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 ch.systemsx.cisd.bds.v1_0;
+
+import java.io.File;
+
+import ch.systemsx.cisd.bds.storage.FileProxy;
+import ch.systemsx.cisd.bds.storage.IDirectory;
+import ch.systemsx.cisd.bds.storage.IFile;
+
+/**
+ * An {@link IFile} implementation which denies access to write operations.
+ * 
+ * @author Christian Ribeaud
+ */
+public final class ReadOnlyFile extends FileProxy
+{
+
+    public ReadOnlyFile(final IFile delegate)
+    {
+        super(delegate);
+    }
+
+    final static ReadOnlyFile tryCreateReadOnlyFile(final IFile file)
+    {
+        if (file == null)
+        {
+            return null;
+        }
+        return new ReadOnlyFile(file);
+    }
+
+    //
+    // FileProxy
+    //
+
+    @Override
+    public final void moveTo(final File directory)
+    {
+        ReadOnlyNode.denyAccess();
+    }
+
+    @Override
+    public final IDirectory tryGetParent()
+    {
+        return ReadOnlyDirectory.tryCreateReadOnlyDirectory(super.tryGetParent());
+    }
+
+    @Override
+    public final IFile tryAsFile()
+    {
+        return tryCreateReadOnlyFile(super.tryAsFile());
+    }
+
+    @Override
+    public final IDirectory tryAsDirectory()
+    {
+        return ReadOnlyDirectory.tryCreateReadOnlyDirectory(super.tryAsDirectory());
+    }
+}
diff --git a/bds/source/java/ch/systemsx/cisd/bds/v1_0/ReadOnlyNode.java b/bds/source/java/ch/systemsx/cisd/bds/v1_0/ReadOnlyNode.java
new file mode 100644
index 00000000000..602bac6f858
--- /dev/null
+++ b/bds/source/java/ch/systemsx/cisd/bds/v1_0/ReadOnlyNode.java
@@ -0,0 +1,79 @@
+/*
+ * Copyright 2008 ETH Zuerich, CISD
+ *
+ * Licensed 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 ch.systemsx.cisd.bds.v1_0;
+
+import java.io.File;
+
+import ch.systemsx.cisd.bds.storage.IDirectory;
+import ch.systemsx.cisd.bds.storage.IFile;
+import ch.systemsx.cisd.bds.storage.INode;
+import ch.systemsx.cisd.bds.storage.NodeProxy;
+
+/**
+ * An {@link IDirectory} implementation which denies access to write operations.
+ * 
+ * @author Christian Ribeaud
+ */
+public final class ReadOnlyNode extends NodeProxy
+{
+    public ReadOnlyNode(final INode delegate)
+    {
+        super(delegate);
+    }
+
+    final static ReadOnlyNode tryCreateReadOnlyNode(final INode node)
+    {
+        if (node == null)
+        {
+            return null;
+        }
+        return new ReadOnlyNode(node);
+    }
+
+    final static void denyAccess()
+    {
+        throw new UnsupportedOperationException("Unsupported operation in read-only mode.");
+    }
+
+    //
+    // NodeProxy
+    //
+
+    @Override
+    public final void moveTo(final File directory)
+    {
+        denyAccess();
+    }
+
+    @Override
+    public final IDirectory tryAsDirectory()
+    {
+        return ReadOnlyDirectory.tryCreateReadOnlyDirectory(super.tryAsDirectory());
+    }
+
+    @Override
+    public final IFile tryAsFile()
+    {
+        return ReadOnlyFile.tryCreateReadOnlyFile(super.tryAsFile());
+    }
+
+    @Override
+    public final IDirectory tryGetParent()
+    {
+        return ReadOnlyDirectory.tryCreateReadOnlyDirectory(super.tryGetParent());
+    }
+}
-- 
GitLab