From 061bab1bd8d24230177fa577bb640b4193e3f19f Mon Sep 17 00:00:00 2001 From: felmer <felmer> Date: Tue, 4 Jun 2013 10:53:23 +0000 Subject: [PATCH] SP-668, BIS-428: handle checksum in case of uncompressed zip file. ZipDataSetpackagerTest added. SVN: 29280 --- .../server/AbstractDataSetPackager.java | 38 ++- .../dss/generic/server/MetaDataBuilder.java | 11 +- .../generic/server/ZipDataSetPackager.java | 23 +- .../plugins/standard/DistributedArchiver.java | 164 ---------- .../server/ZipDataSetPackagerTest.java | 285 ++++++++++++++++++ 5 files changed, 346 insertions(+), 175 deletions(-) delete mode 100644 datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/plugins/standard/DistributedArchiver.java create mode 100644 datastore_server/sourceTest/java/ch/systemsx/cisd/openbis/dss/generic/server/ZipDataSetPackagerTest.java diff --git a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/AbstractDataSetPackager.java b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/AbstractDataSetPackager.java index 27fa640ee66..81700116234 100644 --- a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/AbstractDataSetPackager.java +++ b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/AbstractDataSetPackager.java @@ -19,7 +19,9 @@ package ch.systemsx.cisd.openbis.dss.generic.server; import java.io.ByteArrayInputStream; import java.io.InputStream; import java.util.List; +import java.util.zip.CRC32; +import ch.systemsx.cisd.common.io.IOUtilities; import ch.systemsx.cisd.openbis.common.io.hierarchical_content.api.IHierarchicalContent; import ch.systemsx.cisd.openbis.common.io.hierarchical_content.api.IHierarchicalContentNode; import ch.systemsx.cisd.openbis.dss.generic.shared.IHierarchicalContentProvider; @@ -49,8 +51,16 @@ public abstract class AbstractDataSetPackager /** * Adds an entry with specified entry path and last modification date filled with data from * specified input stream. + * + * @param size Number of bytes. + * @param checksum Checksum. Can be 0 if {@link #isChecksumNeeded()} return <code>false</code>. */ - public abstract void addEntry(String entryPath, long lastModified, InputStream in); + public abstract void addEntry(String entryPath, long lastModified, long size, long checksum, InputStream in); + + /** + * Returns <code>true</code> if the checksum is needed. + */ + protected abstract boolean isChecksumNeeded(); /** * Closes the package. @@ -61,8 +71,15 @@ public abstract class AbstractDataSetPackager { try { - addEntry(rootPath + META_DATA_FILE_NAME, System.currentTimeMillis(), - new ByteArrayInputStream(MetaDataBuilder.createMetaData(externalData).getBytes())); + byte[] bytes = MetaDataBuilder.createMetaData(externalData).getBytes(); + CRC32 checksumCalculator = new CRC32(); + for (byte b : bytes) + { + checksumCalculator.update(0xff & b); + } + Long checksum = checksumCalculator.getValue(); + addEntry(rootPath + META_DATA_FILE_NAME, System.currentTimeMillis(), new Long(bytes.length), checksum, + new ByteArrayInputStream(bytes)); } catch (Exception ex) { throw new RuntimeException( @@ -111,7 +128,20 @@ public abstract class AbstractDataSetPackager } } else { - addEntry(newRootPath + node.getRelativePath(), node.getLastModified(), + long size = node.getFileLength(); + long checksum = 0; + if (isChecksumNeeded()) + { + boolean checksumCRC32Precalculated = node.isChecksumCRC32Precalculated(); + if (checksumCRC32Precalculated) + { + checksum = node.getChecksumCRC32(); + } else + { + checksum = IOUtilities.getChecksumCRC32(node.getInputStream()); + } + } + addEntry(newRootPath + node.getRelativePath(), node.getLastModified(), size, checksum, node.getInputStream()); } } diff --git a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/MetaDataBuilder.java b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/MetaDataBuilder.java index adb91cd1ccb..04d2ebbde41 100644 --- a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/MetaDataBuilder.java +++ b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/MetaDataBuilder.java @@ -19,6 +19,7 @@ package ch.systemsx.cisd.openbis.dss.generic.server; import java.text.DateFormat; import java.text.SimpleDateFormat; import java.util.ArrayList; +import java.util.Collection; import java.util.Collections; import java.util.Comparator; import java.util.Date; @@ -86,10 +87,10 @@ public class MetaDataBuilder builder.dataSetProperties(dataSet.getProperties()); StringBuilder stringBuilder = new StringBuilder(); - List<AbstractExternalData> parents = new ArrayList<AbstractExternalData>(dataSet.getParents()); - Collections.sort(parents, DATA_SET_COMPARATOR); + List<AbstractExternalData> parents = getParents(dataSet); if (parents.isEmpty() == false) { + Collections.sort(parents, DATA_SET_COMPARATOR); for (AbstractExternalData parent : parents) { if (stringBuilder.length() > 0) @@ -123,6 +124,12 @@ public class MetaDataBuilder return builder.getRenderedMetaData(); } + private static List<AbstractExternalData> getParents(AbstractExternalData dataSet) + { + Collection<AbstractExternalData> parents = dataSet.getParents(); + return parents == null ? new ArrayList<AbstractExternalData>() : new ArrayList<AbstractExternalData>(parents); + } + private final StringBuilder builder = new StringBuilder(); private void dataSetProperties(List<IEntityProperty> properties) diff --git a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/ZipDataSetPackager.java b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/ZipDataSetPackager.java index a9088d310f0..5fff70928f5 100644 --- a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/ZipDataSetPackager.java +++ b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/ZipDataSetPackager.java @@ -51,29 +51,42 @@ public class ZipDataSetPackager extends AbstractDataSetPackager } @Override - public void addEntry(String entryPath, long lastModified, InputStream in) + protected boolean isChecksumNeeded() { + return compress == false; + } + + @Override + public void addEntry(String entryPath, long lastModified, long size, long checksum, InputStream in) + { + ZipOutputStream zos = getZipOutputStream(); try { ZipEntry zipEntry = new ZipEntry(entryPath.replace('\\', '/')); zipEntry.setTime(lastModified); zipEntry.setMethod(compress ? ZipEntry.DEFLATED : ZipEntry.STORED); - getZipOutputStream().putNextEntry(zipEntry); + if (compress == false) + { + zipEntry.setSize(size); + zipEntry.setCompressedSize(size); + zipEntry.setCrc(0xffffffffL & checksum); + } + zos.putNextEntry(zipEntry); int len; byte[] buffer = new byte[1024]; while ((len = in.read(buffer)) > 0) { - getZipOutputStream().write(buffer, 0, len); + zos.write(buffer, 0, len); } } catch (IOException ex) { - throw CheckedExceptionTunnel.wrapIfNecessary(ex); + throw new RuntimeException("Error while adding entry " + entryPath, ex); } finally { IOUtils.closeQuietly(in); try { - getZipOutputStream().closeEntry(); + zos.closeEntry(); } catch (IOException ex) { throw CheckedExceptionTunnel.wrapIfNecessary(ex); diff --git a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/plugins/standard/DistributedArchiver.java b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/plugins/standard/DistributedArchiver.java deleted file mode 100644 index 55d3b57d228..00000000000 --- a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/plugins/standard/DistributedArchiver.java +++ /dev/null @@ -1,164 +0,0 @@ -/* - * 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.util.ArrayList; -import java.util.List; -import java.util.Properties; - -import ch.systemsx.cisd.common.exceptions.Status; -import ch.systemsx.cisd.common.filesystem.BooleanStatus; -import ch.systemsx.cisd.common.properties.PropertyUtils; -import ch.systemsx.cisd.common.time.TimingParameters; -import ch.systemsx.cisd.openbis.dss.generic.server.AbstractDataSetPackager; -import ch.systemsx.cisd.openbis.dss.generic.server.ZipDataSetPackager; -import ch.systemsx.cisd.openbis.dss.generic.shared.ArchiverTaskContext; -import ch.systemsx.cisd.openbis.dss.generic.shared.IDataSetDirectoryProvider; -import ch.systemsx.cisd.openbis.dss.generic.shared.IEncapsulatedOpenBISService; -import ch.systemsx.cisd.openbis.dss.generic.shared.IHierarchicalContentProvider; -import ch.systemsx.cisd.openbis.dss.generic.shared.IShareIdManager; -import ch.systemsx.cisd.openbis.dss.generic.shared.utils.DataSetExistenceChecker; -import ch.systemsx.cisd.openbis.generic.shared.basic.dto.AbstractExternalData; -import ch.systemsx.cisd.openbis.generic.shared.basic.dto.IDatasetLocation; -import ch.systemsx.cisd.openbis.generic.shared.dto.DatasetDescription; -import ch.systemsx.cisd.openbis.generic.shared.dto.identifier.ExperimentIdentifierFactory; -import ch.systemsx.cisd.openbis.generic.shared.dto.identifier.SampleIdentifierFactory; - -/** - * - * - * @author Franz-Josef Elmer - */ -public class DistributedArchiver extends AbstractArchiverProcessingPlugin -{ - private static final long serialVersionUID = 1L; - - private final boolean compress; - - private File destination; - - public DistributedArchiver(Properties properties, File storeRoot) - { - super(properties, storeRoot, null, null); - destination = new File(properties.getProperty("destination")); - compress = PropertyUtils.getBoolean(properties, "compress", true); - destination.mkdirs(); - } - - @Override - protected DatasetProcessingStatuses doArchive(List<DatasetDescription> datasets, ArchiverTaskContext context) - { - List<AbstractExternalData> dataSets = getDataSetMetaData(datasets); - IHierarchicalContentProvider contentProvider = context.getHierarchicalContentProvider(); - IDataSetDirectoryProvider directoryProvider = context.getDirectoryProvider(); - IShareIdManager shareIdManager = directoryProvider.getShareIdManager(); - DataSetExistenceChecker dataSetExistenceChecker = - new DataSetExistenceChecker(directoryProvider, TimingParameters.create(new Properties())); - DatasetProcessingStatuses statuses = new DatasetProcessingStatuses(); - for (AbstractExternalData dataSet : dataSets) - { - Status status = Status.OK; - String dataSetCode = dataSet.getCode(); - File file = new File(getArchive(dataSet), dataSetCode + ".zip"); - shareIdManager.lock(dataSetCode); - AbstractDataSetPackager dataSetPackager = null; - try - { - dataSetPackager = createPackager(file, contentProvider, dataSetExistenceChecker); - dataSetPackager.addDataSetTo("", dataSet); - } catch (Exception ex) - { - status = Status.createError(ex.toString()); - operationLog.error("Couldn't create package file: " + file, ex); - } finally - { - if (dataSetPackager != null) - { - try - { - dataSetPackager.close(); - } catch (Exception ex) - { - status = Status.createError("Couldn't close package file: " + file + ": " + ex); - } - } - shareIdManager.releaseLock(dataSetCode); - operationLog.info("Data set " + dataSetCode + " archived: " + file); - } - statuses.addResult(dataSetCode, status, Operation.ARCHIVE); - } - return statuses; - } - - private AbstractDataSetPackager createPackager(File file, IHierarchicalContentProvider contentProvider, - DataSetExistenceChecker dataSetExistenceChecker) - { - return new ZipDataSetPackager(file, compress, contentProvider, dataSetExistenceChecker); - } - - private List<AbstractExternalData> getDataSetMetaData(List<DatasetDescription> datasets) - { - IEncapsulatedOpenBISService service = getService(); - List<AbstractExternalData> dataSets = new ArrayList<AbstractExternalData>(); - for (DatasetDescription datasetDescription : datasets) - { - AbstractExternalData dataSet = service.tryGetDataSet(datasetDescription.getDataSetCode()); - String experimentIdentifier = datasetDescription.getExperimentIdentifier(); - dataSet.setExperiment(service.tryGetExperiment(ExperimentIdentifierFactory.parse(experimentIdentifier))); - String sampleIdentifier = datasetDescription.getSampleIdentifier(); - if (sampleIdentifier != null) - { - dataSet.setSample(service.tryGetSampleWithExperiment(SampleIdentifierFactory.parse(sampleIdentifier))); - } - dataSets.add(dataSet); - } - return dataSets; - } - - private File getArchive(AbstractExternalData dataSet) - { - return destination; - } - - @Override - protected DatasetProcessingStatuses doUnarchive(List<DatasetDescription> datasets, ArchiverTaskContext context) - { - // TODO Auto-generated method stub - return null; - } - - @Override - protected DatasetProcessingStatuses doDeleteFromArchive(List<? extends IDatasetLocation> datasets) - { - // TODO Auto-generated method stub - return null; - } - - @Override - protected BooleanStatus isDataSetSynchronizedWithArchive(DatasetDescription dataset, ArchiverTaskContext context) - { - return BooleanStatus.createFalse(); - } - - @Override - protected BooleanStatus isDataSetPresentInArchive(DatasetDescription dataset) - { - return BooleanStatus.createFalse(); - } - -} diff --git a/datastore_server/sourceTest/java/ch/systemsx/cisd/openbis/dss/generic/server/ZipDataSetPackagerTest.java b/datastore_server/sourceTest/java/ch/systemsx/cisd/openbis/dss/generic/server/ZipDataSetPackagerTest.java new file mode 100644 index 00000000000..beb0763844a --- /dev/null +++ b/datastore_server/sourceTest/java/ch/systemsx/cisd/openbis/dss/generic/server/ZipDataSetPackagerTest.java @@ -0,0 +1,285 @@ +/* + * 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; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.InputStream; +import java.util.Collections; +import java.util.zip.ZipEntry; +import java.util.zip.ZipFile; + +import org.apache.commons.io.IOUtils; +import org.jmock.Expectations; +import org.jmock.Mockery; +import org.testng.annotations.AfterMethod; +import org.testng.annotations.BeforeMethod; +import org.testng.annotations.Test; + +import ch.systemsx.cisd.base.tests.AbstractFileSystemTestCase; +import ch.systemsx.cisd.common.filesystem.FileUtilities; +import ch.systemsx.cisd.common.io.IOUtilities; +import ch.systemsx.cisd.common.server.ISessionTokenProvider; +import ch.systemsx.cisd.common.spring.ExposablePropertyPlaceholderConfigurer; +import ch.systemsx.cisd.common.time.TimingParameters; +import ch.systemsx.cisd.openbis.common.io.hierarchical_content.DefaultFileBasedHierarchicalContentFactory; +import ch.systemsx.cisd.openbis.common.io.hierarchical_content.IHierarchicalContentFactory; +import ch.systemsx.cisd.openbis.dss.generic.shared.DataSetDirectoryProvider; +import ch.systemsx.cisd.openbis.dss.generic.shared.HierarchicalContentProvider; +import ch.systemsx.cisd.openbis.dss.generic.shared.IConfigProvider; +import ch.systemsx.cisd.openbis.dss.generic.shared.IDataSetDirectoryProvider; +import ch.systemsx.cisd.openbis.dss.generic.shared.IEncapsulatedOpenBISService; +import ch.systemsx.cisd.openbis.dss.generic.shared.IShareIdManager; +import ch.systemsx.cisd.openbis.dss.generic.shared.content.DssServiceRpcGenericFactory; +import ch.systemsx.cisd.openbis.dss.generic.shared.content.IContentCache; +import ch.systemsx.cisd.openbis.dss.generic.shared.utils.DataSetExistenceChecker; +import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DatasetLocationNode; +import ch.systemsx.cisd.openbis.generic.shared.basic.dto.PhysicalDataSet; +import ch.systemsx.cisd.openbis.generic.shared.basic.dto.builders.DataSetBuilder; +import ch.systemsx.cisd.openbis.generic.shared.basic.dto.builders.DataStoreBuilder; +import ch.systemsx.cisd.openbis.generic.shared.basic.dto.builders.ExperimentBuilder; +import ch.systemsx.cisd.openbis.generic.shared.basic.dto.builders.SampleBuilder; + +import de.schlichtherle.io.FileInputStream; + +/** + * + * + * @author Franz-Josef Elmer + */ +public class ZipDataSetPackagerTest extends AbstractFileSystemTestCase +{ + private static final String DATA_SET_CODE = "ds1"; + private static final String DSS_CODE = "DSS"; + private static final String SHARE_ID = "1"; + private Mockery context; + private IEncapsulatedOpenBISService openbisService; + private IShareIdManager shareIdManager; + private IConfigProvider configProvider; + private HierarchicalContentProvider contentProvider; + private DataSetExistenceChecker existenceChecker; + private IHierarchicalContentFactory contentProviderFactory; + private File rootFolder; + + @BeforeMethod + public void prepareTestFixture() + { + context = new Mockery(); + openbisService = context.mock(IEncapsulatedOpenBISService.class); + shareIdManager = context.mock(IShareIdManager.class); + configProvider = context.mock(IConfigProvider.class); + context.checking(new Expectations() + { + { + allowing(configProvider).getStoreRoot(); + will(returnValue(workingDirectory)); + + allowing(configProvider).getDataStoreCode(); + will(returnValue(DSS_CODE)); + } + }); + IContentCache contentCache = null; + ISessionTokenProvider sessionTokenProvider = null; + ExposablePropertyPlaceholderConfigurer infoProvider = null; + IDataSetDirectoryProvider dataSetDirectoryProvider = new DataSetDirectoryProvider(workingDirectory, shareIdManager); + contentProviderFactory = new DefaultFileBasedHierarchicalContentFactory(); + contentProvider = new HierarchicalContentProvider(openbisService, dataSetDirectoryProvider, contentProviderFactory, + new DssServiceRpcGenericFactory(), contentCache, sessionTokenProvider, DSS_CODE, infoProvider); + existenceChecker = new DataSetExistenceChecker(dataSetDirectoryProvider, TimingParameters.getDefaultParameters()); + File share = new File(workingDirectory, SHARE_ID); + share.mkdirs(); + rootFolder = new File(share, DATA_SET_CODE); + File subFolder = new File(rootFolder, "subfolder"); + subFolder.mkdirs(); + FileUtilities.writeToFile(new File(rootFolder, "read.me"), "Don't read me!"); + FileUtilities.writeToFile(new File(subFolder, "change-log.txt"), "nothing changed"); + } + + @AfterMethod + public void tearDown() + { + // To following line of code should also be called at the end of each test method. + // Otherwise one does not known which test failed. + context.assertIsSatisfied(); + } + + @Test + public void testCreateCompressed() throws Exception + { + PhysicalDataSet dataSet = new DataSetBuilder().store(new DataStoreBuilder(DSS_CODE).getStore()) + .code(DATA_SET_CODE).type("MY-DATASET").fileFormat("XML").location(DATA_SET_CODE).property("AGE", "42") + .experiment(new ExperimentBuilder().identifier("/S/P/E1").type("MY-EXPERIMENT").property("GREETINGS", "Hello").getExperiment()) + .getDataSet(); + prepareShareIdManager(DATA_SET_CODE); + prepareGetDataSetLocation(dataSet); + File zipFile = new File(workingDirectory, "archived1.zip"); + ZipDataSetPackager packager = new ZipDataSetPackager(zipFile, true, contentProvider, existenceChecker); + + packager.addDataSetTo("", dataSet); + packager.close(); + + checkZipFileContent(zipFile, dataSet, "data_set\tcode\tds1\n" + + "data_set\tproduction_timestamp\t\n" + + "data_set\tproducer_code\t\n" + + "data_set\tdata_set_type\tMY-DATASET\n" + + "data_set\tis_measured\tTRUE\n" + + "data_set\tis_complete\tFALSE\n" + + "data_set\tAGE\t42\n" + + "data_set\tparent_codes\t\n" + + "experiment\tspace_code\tS\n" + + "experiment\tproject_code\tP\n" + + "experiment\texperiment_code\tE1\n" + + "experiment\texperiment_type_code\tMY-EXPERIMENT\n" + + "experiment\tregistration_timestamp\t\n" + + "experiment\tregistrator\t\n" + + "experiment\tGREETINGS\tHello\n"); + context.assertIsSatisfied(); + } + + @Test + public void testCreateUncompressed() throws Exception + { + PhysicalDataSet dataSet = new DataSetBuilder().store(new DataStoreBuilder(DSS_CODE).getStore()) + .code(DATA_SET_CODE).type("MY-DATASET").fileFormat("XML").location(DATA_SET_CODE).property("AGE", "24") + .experiment(new ExperimentBuilder().identifier("/S/P/E1").type("MY-EXPERIMENT").getExperiment()) + .sample(new SampleBuilder().identifier("/S/S1").type("MY-SAMPLE").property("GREETINGS", "Hi").getSample()) + .parent(new DataSetBuilder().code("P1").getDataSet()) + .getDataSet(); + prepareShareIdManager(DATA_SET_CODE); + prepareGetDataSetLocation(dataSet); + File zipFile = new File(workingDirectory, "archived2.zip"); + ZipDataSetPackager packager = new ZipDataSetPackager(zipFile, false, contentProvider, existenceChecker); + + packager.addDataSetTo("", dataSet); + packager.close(); + + checkZipFileContent(zipFile, dataSet, "data_set\tcode\tds1\n" + + "data_set\tproduction_timestamp\t\n" + + "data_set\tproducer_code\t\n" + + "data_set\tdata_set_type\tMY-DATASET\n" + + "data_set\tis_measured\tTRUE\n" + + "data_set\tis_complete\tFALSE\n" + + "data_set\tAGE\t24\n" + + "data_set\tparent_codes\tP1\n" + + "sample\ttype_code\tMY-SAMPLE\n" + + "sample\tcode\tS1\n" + + "sample\tspace_code\tS\n" + + "sample\tregistration_timestamp\t\n" + + "sample\tregistrator\t\n" + + "sample\tGREETINGS\tHi\n" + + "experiment\tspace_code\tS\n" + + "experiment\tproject_code\tP\n" + + "experiment\texperiment_code\tE1\n" + + "experiment\texperiment_type_code\tMY-EXPERIMENT\n" + + "experiment\tregistration_timestamp\t\n" + + "experiment\tregistrator\t\n"); + context.assertIsSatisfied(); + } + + private void checkZipFileContent(File zipFile, PhysicalDataSet dataSet, String metaData) throws Exception + { + assertEquals(true, zipFile.exists()); + ZipFile zFile = new ZipFile(zipFile); + for (ZipEntry zipEntry : Collections.list(zFile.entries())) + { + String relativePath = zipEntry.getName(); + if (relativePath.equals(AbstractDataSetPackager.META_DATA_FILE_NAME)) + { + checkContent(zFile, zipEntry, new ByteArrayInputStream(metaData.getBytes())); + } else + { + checkZipEntry(zFile, zipEntry); + } + } + } + + private void checkZipEntry(ZipFile zf, ZipEntry entry) throws Exception + { + String relativePath = entry.getName(); + File file = new File(rootFolder, relativePath); + assertEquals(relativePath + " exists", true, file.exists()); + assertEquals(relativePath + " folder or file", file.isDirectory(), entry.isDirectory()); + if (entry.isDirectory()) + { + return; + } + assertEquals(relativePath + " size", file.length(), entry.getSize()); + assertEquals(relativePath + " checksum", calculateChecksum(file), (int) entry.getCrc()); + checkContent(zf, entry, new FileInputStream(file)); + } + + private void checkContent(ZipFile zf, ZipEntry entry, InputStream inputStream) throws Exception + { + String expectedContent = getContentAndClose(inputStream); + String actualContent = getContentAndClose(zf.getInputStream(entry)); + assertEquals(entry.getName() + " content", expectedContent, actualContent); + } + + private String getContentAndClose(InputStream inputStream) throws Exception + { + try + { + ByteArrayOutputStream output = new ByteArrayOutputStream(); + IOUtils.copy(inputStream, output); + return output.toString(); + } finally + { + IOUtils.closeQuietly(inputStream); + } + } + + private int calculateChecksum(File file) throws Exception + { + InputStream inputStream = null; + try + { + inputStream = new FileInputStream(file); + return IOUtilities.getChecksumCRC32(inputStream); + } finally + { + IOUtils.closeQuietly(inputStream); + } + } + + private void prepareGetDataSetLocation(final PhysicalDataSet dataSet) + { + context.checking(new Expectations() + { + { + one(openbisService).tryGetDataSetLocation(dataSet.getCode()); + will(returnValue(new DatasetLocationNode(dataSet))); + } + }); + } + + private void prepareShareIdManager(final String dataSetCode) + { + context.checking(new Expectations() + { + { + exactly(2).of(shareIdManager).getShareId(dataSetCode); + will(returnValue(SHARE_ID)); + + one(shareIdManager).lock(dataSetCode); + + one(shareIdManager).releaseLock(dataSetCode); + } + }); + } + +} -- GitLab