From f52cac2c0ee6985dac1026f2302e2f780dbbeca5 Mon Sep 17 00:00:00 2001
From: anttil <anttil>
Date: Tue, 13 Aug 2013 09:17:31 +0000
Subject: [PATCH] BIS-506 / SP-801:  Zip file based archiver consistency checks

SVN: 29639
---
 .../server/plugins/standard/CrcProvider.java  |  53 ++++++++
 .../server/plugins/standard/ICrcProvider.java |  25 ++++
 .../server/plugins/standard/Verifier.java     |  27 ++++
 .../plugins/standard/ZipFileCrcVerifier.java  | 128 ++++++++++++++++++
 .../standard/ZipFilePathInfoVerifier.java     |  77 +++++++++++
 5 files changed, 310 insertions(+)
 create mode 100644 datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/plugins/standard/CrcProvider.java
 create mode 100644 datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/plugins/standard/ICrcProvider.java
 create mode 100644 datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/plugins/standard/Verifier.java
 create mode 100644 datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/plugins/standard/ZipFileCrcVerifier.java
 create mode 100644 datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/plugins/standard/ZipFilePathInfoVerifier.java

diff --git a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/plugins/standard/CrcProvider.java b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/plugins/standard/CrcProvider.java
new file mode 100644
index 00000000000..38ee81ca9dd
--- /dev/null
+++ b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/plugins/standard/CrcProvider.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright 2013 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.openbis.dss.generic.server.plugins.standard;
+
+import java.util.Map;
+
+import ch.systemsx.cisd.openbis.dss.generic.server.DatabaseBasedDataSetPathInfoProvider;
+
+/**
+ * @author anttil
+ */
+public class CrcProvider implements ICrcProvider
+{
+    private Map<String, Integer> checksums;
+
+    public CrcProvider(String dataSetCode)
+    {
+        checksums = new DatabaseBasedDataSetPathInfoProvider().getDataSetChecksums(dataSetCode);
+    }
+
+    @Override
+    public Long getCrc(String name)
+    {
+        Integer crc = checksums.get(name);
+        if (crc == null)
+        {
+            return null;
+        } else
+        {
+            return getUnsignedInt(crc);
+        }
+    }
+
+    public static long getUnsignedInt(int x)
+    {
+        return x & 0x00000000ffffffffL;
+    }
+
+}
diff --git a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/plugins/standard/ICrcProvider.java b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/plugins/standard/ICrcProvider.java
new file mode 100644
index 00000000000..6003ba4b8fc
--- /dev/null
+++ b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/plugins/standard/ICrcProvider.java
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2013 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.openbis.dss.generic.server.plugins.standard;
+
+/**
+ * @author anttil
+ */
+public interface ICrcProvider
+{
+    Long getCrc(String name);
+}
diff --git a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/plugins/standard/Verifier.java b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/plugins/standard/Verifier.java
new file mode 100644
index 00000000000..ce61d68dbec
--- /dev/null
+++ b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/plugins/standard/Verifier.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright 2013 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.openbis.dss.generic.server.plugins.standard;
+
+import java.util.List;
+
+/**
+ * @author anttil
+ */
+public interface Verifier
+{
+    public List<String> verify();
+}
diff --git a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/plugins/standard/ZipFileCrcVerifier.java b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/plugins/standard/ZipFileCrcVerifier.java
new file mode 100644
index 00000000000..0eeb48854dc
--- /dev/null
+++ b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/plugins/standard/ZipFileCrcVerifier.java
@@ -0,0 +1,128 @@
+/*
+ * Copyright 2013 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.openbis.dss.generic.server.plugins.standard;
+
+import java.io.BufferedInputStream;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Enumeration;
+import java.util.List;
+import java.util.zip.CRC32;
+import java.util.zip.ZipException;
+
+import de.schlichtherle.util.zip.ZipEntry;
+import de.schlichtherle.util.zip.ZipFile;
+
+/**
+ * @author anttil
+ */
+public class ZipFileCrcVerifier implements Verifier
+{
+
+    private final File file;
+
+    public ZipFileCrcVerifier(File file)
+    {
+        this.file = file;
+    }
+
+    @Override
+    public List<String> verify()
+    {
+        List<String> errors = new ArrayList<String>();
+        ZipFile zip;
+        try
+        {
+            zip = new ZipFile(file);
+        } catch (ZipException ex)
+        {
+            errors.add("Reading zip file failed: " + ex.getMessage());
+            return errors;
+        } catch (IOException ex)
+        {
+            errors.add("Reading zip file failed: " + ex.getMessage());
+            return errors;
+        }
+
+        Enumeration<?> entries = zip.entries();
+        while (entries.hasMoreElements())
+        {
+            ZipEntry entry = (ZipEntry) entries.nextElement();
+            errors.addAll(checkZipEntry(zip, entry));
+        }
+        return errors;
+    }
+
+    private Collection<String> checkZipEntry(ZipFile zip, ZipEntry entry)
+    {
+        InputStream input = null;
+        try
+        {
+            input = zip.getInputStream(entry);
+
+            long crc = calcCRC32(input);
+
+            if (crc != entry.getCrc())
+            {
+                return Arrays.asList(entry.getName() + ": CRC failure (got " + Long.toHexString(crc) + ", should be "
+                        + Long.toHexString(entry.getCrc()) + ")");
+            }
+
+        } catch (ZipException ex)
+        {
+            return Arrays.asList(ex.getMessage());
+        } catch (IOException ex)
+        {
+            return Arrays.asList(entry.getName() + ": " + ex.getMessage());
+        } finally
+        {
+            if (input != null)
+            {
+                try
+                {
+                    input.close();
+                } catch (IOException ex)
+                {
+                }
+            }
+        }
+        return new ArrayList<String>();
+    }
+
+    private static long calcCRC32(InputStream input) throws IOException
+    {
+        BufferedInputStream inStream = new BufferedInputStream(input);
+        int BLOCK_SIZE = 128 * 1024;
+        int len;
+        byte[] buffer = new byte[BLOCK_SIZE];
+
+        CRC32 crc32 = new CRC32();
+        crc32.reset();
+
+        while ((len = inStream.read(buffer, 0, BLOCK_SIZE)) > 0)
+        {
+            crc32.update(buffer, 0, len);
+            buffer = new byte[BLOCK_SIZE];
+        }
+
+        return crc32.getValue();
+    }
+}
diff --git a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/plugins/standard/ZipFilePathInfoVerifier.java b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/plugins/standard/ZipFilePathInfoVerifier.java
new file mode 100644
index 00000000000..61b570bb7af
--- /dev/null
+++ b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/plugins/standard/ZipFilePathInfoVerifier.java
@@ -0,0 +1,77 @@
+/*
+ * Copyright 2013 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.openbis.dss.generic.server.plugins.standard;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Enumeration;
+import java.util.List;
+import java.util.zip.ZipException;
+
+import de.schlichtherle.util.zip.ZipEntry;
+import de.schlichtherle.util.zip.ZipFile;
+
+/**
+ * @author anttil
+ */
+public class ZipFilePathInfoVerifier implements Verifier
+{
+
+    private final File file;
+
+    private final ICrcProvider crcProvider;
+
+    public ZipFilePathInfoVerifier(File file, ICrcProvider crcProvider)
+    {
+        this.file = file;
+        this.crcProvider = crcProvider;
+    }
+
+    @Override
+    public List<String> verify()
+    {
+        List<String> errors = new ArrayList<String>();
+        ZipFile zip;
+        try
+        {
+            zip = new ZipFile(file);
+        } catch (ZipException ex)
+        {
+            errors.add("Reading zip file failed: " + ex.getMessage());
+            return errors;
+        } catch (IOException ex)
+        {
+            errors.add("Reading zip file failed: " + ex.getMessage());
+            return errors;
+        }
+
+        Enumeration<?> entries = zip.entries();
+        while (entries.hasMoreElements())
+        {
+            ZipEntry entry = (ZipEntry) entries.nextElement();
+
+            Long externalCrc = crcProvider.getCrc(entry.getName());
+            if (externalCrc != null && externalCrc != entry.getCrc())
+            {
+                errors.add(entry.getName() + ": external CRC: " + externalCrc + ", header CRC: " + entry.getCrc());
+            }
+        }
+        return errors;
+    }
+
+}
-- 
GitLab