diff --git a/bds/.classpath b/bds/.classpath index 32e0c04b0484900f435fdf4cc2c6c8548ecea73f..a672230f3491ce195c4712dd644c1e4e07ded98f 100644 --- a/bds/.classpath +++ b/bds/.classpath @@ -16,5 +16,6 @@ <classpathentry kind="lib" path="/libraries/fast-md5/fast-md5.jar" sourcepath="/libraries/fast-md5/src.zip"/> <classpathentry kind="lib" path="/libraries/restrictionchecker/restrictions.jar"/> <classpathentry combineaccessrules="false" kind="src" path="/args4j"/> + <classpathentry kind="lib" path="/libraries/commons-lang/commons-lang.jar" sourcepath="/libraries/commons-lang/src.zip"/> <classpathentry kind="output" path="targets/classes"/> </classpath> diff --git a/bds/source/java/ch/systemsx/cisd/bds/AbstractDataStructure.java b/bds/source/java/ch/systemsx/cisd/bds/AbstractDataStructure.java index 54fa4e5903e9c42943ad82288e39d1ddd6f4b14a..ea17fb02c90bd43ea377226cf2fa2fa077295e19 100644 --- a/bds/source/java/ch/systemsx/cisd/bds/AbstractDataStructure.java +++ b/bds/source/java/ch/systemsx/cisd/bds/AbstractDataStructure.java @@ -134,7 +134,8 @@ abstract class AbstractDataStructure implements IDataStructure, IDataStructureHa assertOpenOrCreated(); getVersion().saveTo(root); performClosing(); - assertValid(); + //TODO 2008-07-03, Bernd Rinn: make this optional + //assertValid(); storage.unmount(); } } diff --git a/bds/source/java/ch/systemsx/cisd/bds/handler/ChecksumHandler.java b/bds/source/java/ch/systemsx/cisd/bds/handler/ChecksumHandler.java index 6c2a970874c08399e2f90ea3e0b2c458f27b07bf..20d059e00af898b1260531f6504fca1f8245bf69 100644 --- a/bds/source/java/ch/systemsx/cisd/bds/handler/ChecksumHandler.java +++ b/bds/source/java/ch/systemsx/cisd/bds/handler/ChecksumHandler.java @@ -24,6 +24,7 @@ import java.util.Collections; import java.util.List; import org.apache.commons.io.IOUtils; +import org.apache.log4j.Logger; import ch.systemsx.cisd.bds.Constants; import ch.systemsx.cisd.bds.DataStructureV1_0; @@ -37,6 +38,9 @@ import ch.systemsx.cisd.common.collections.CollectionIO; import ch.systemsx.cisd.common.collections.IFromStringConverter; import ch.systemsx.cisd.common.collections.IToStringConverter; import ch.systemsx.cisd.common.exceptions.EnvironmentFailureException; +import ch.systemsx.cisd.common.exceptions.StopException; +import ch.systemsx.cisd.common.logging.LogCategory; +import ch.systemsx.cisd.common.logging.LogFactory; /** * A <code>IDataStructureHandler</code> implementation for the <code>md5sum</code> directory. @@ -45,6 +49,9 @@ import ch.systemsx.cisd.common.exceptions.EnvironmentFailureException; */ public final class ChecksumHandler implements IDataStructureHandler { + private static final Logger operationLog = + LogFactory.getLogger(LogCategory.OPERATION, ChecksumHandler.class); + private static final ChecksumConverter CHECKSUM_CONVERTER = new ChecksumConverter(); public static final String CHECKSUM_DIRECTORY = "md5sum"; @@ -65,9 +72,15 @@ public final class ChecksumHandler implements IDataStructureHandler private final List<Checksum> loadChecksumsForAllFilesIn(final IDirectory directory) { + final long start = System.currentTimeMillis(); assert directory != null : "Unspecified directory"; final List<Checksum> checksums = new ArrayList<Checksum>(); addChecksums(checksums, null, directory); + if (operationLog.isInfoEnabled()) + { + operationLog.info("Computation of MD5 checksums took " + + ((System.currentTimeMillis() - start) / 1000.0) + "s"); + } return checksums; } @@ -89,11 +102,12 @@ public final class ChecksumHandler implements IDataStructureHandler private final void addChecksum(final List<Checksum> checksums, final String path, final INode node) { + StopException.check(); final String nodePath = (path == null ? "" : path + Constants.PATH_SEPARATOR) + node.getName(); if (node instanceof IFile) { - IFile file = (IFile) node; + final IFile file = (IFile) node; final InputStream inputStream = file.getInputStream(); try { @@ -104,7 +118,7 @@ public final class ChecksumHandler implements IDataStructureHandler checksums.add(checksum); } catch (IOException ex) { - throw new EnvironmentFailureException("Couldn't calculate checksum for file '" + throw new EnvironmentFailureException("Can not calculate checksum for file '" + nodePath + "'"); } finally { diff --git a/bds/source/java/ch/systemsx/cisd/bds/hcs/HCSImageFormattedData.java b/bds/source/java/ch/systemsx/cisd/bds/hcs/HCSImageFormattedData.java index 94da08eeab094802c8d7c379c2770ba296a1563e..af3d3a211932cf29989f09d8d1010f653136c924 100644 --- a/bds/source/java/ch/systemsx/cisd/bds/hcs/HCSImageFormattedData.java +++ b/bds/source/java/ch/systemsx/cisd/bds/hcs/HCSImageFormattedData.java @@ -17,7 +17,9 @@ package ch.systemsx.cisd.bds.hcs; import java.io.File; +import java.util.HashMap; import java.util.HashSet; +import java.util.Map; import java.util.Set; import ch.systemsx.cisd.bds.AbstractFormattedData; @@ -42,38 +44,93 @@ import ch.systemsx.cisd.bds.storage.INode; public final class HCSImageFormattedData extends AbstractFormattedData implements IHCSImageFormattedData { - /** The <i>column</i> (or <i>x</i>) coordinate. */ public static final String COLUMN = "column"; /** The <i>row</i> (or <i>y</i>) coordinate. */ public static final String ROW = "row"; + private final DirectoryContentCache standardDataDirectoryCache; + + private final IDirectory originalDataDirectoryOrNull; // set if containsOriginalData is true + + private final boolean containsOriginalData; + + private final Geometry wellGeometry; + + private final Geometry plateGeometry; + + private final int channelCount; + + // It is a kludge to keep this around but IDirectory.addFile() requires a java.io.File and + // INodes can not be checked for equal(), so we need it. + private File currentImageRootDirectory; + + /** The source directory node from where to copy/link all images. */ + private IDirectory currentImageRootDirectoryNode; + public HCSImageFormattedData(final FormattedDataContext context) { super(context); + this.containsOriginalData = figureContainsOriginalData(getFormatParameters()); + if (containsOriginalData) + { + this.originalDataDirectoryOrNull = + Utilities.getSubDirectory(dataDirectory, DataStructureV1_0.DIR_ORIGINAL); + } else + { + this.originalDataDirectoryOrNull = null; + } + + IDirectory standardDataDirectory = + Utilities.getSubDirectory(dataDirectory, DataStructureV1_0.DIR_STANDARD); + this.standardDataDirectoryCache = + new DirectoryContentCache(standardDataDirectory, createChannelDirNameProvider()); + + this.wellGeometry = figureWellGeometry(getFormatParameters()); + this.plateGeometry = figurePlateGeometry(getFormatParameters()); + this.channelCount = figureChannelCount(getFormatParameters()); + } + + private static int figureChannelCount(IFormatParameters params) + { + return ((Integer) params.getValue(HCSImageFormatV1_0.NUMBER_OF_CHANNELS)).intValue(); + } + + private static Geometry figurePlateGeometry(IFormatParameters params) + { + return (Geometry) params.getValue(PlateGeometry.PLATE_GEOMETRY); + } + + private static Geometry figureWellGeometry(IFormatParameters params) + { + return (Geometry) params.getValue(WellGeometry.WELL_GEOMETRY); + } + + private static boolean figureContainsOriginalData(IFormatParameters params) + { + return ((Utilities.Boolean) params.getValue(HCSImageFormatV1_0.CONTAINS_ORIGINAL_DATA)) + .toBoolean(); } public final boolean containsOriginalData() { - return ((Utilities.Boolean) getFormatParameters().getValue( - HCSImageFormatV1_0.CONTAINS_ORIGINAL_DATA)).toBoolean(); + return containsOriginalData; } public final Geometry getWellGeometry() { - return (Geometry) getFormatParameters().getValue(WellGeometry.WELL_GEOMETRY); + return wellGeometry; } public final Geometry getPlateGeometry() { - return (Geometry) getFormatParameters().getValue(PlateGeometry.PLATE_GEOMETRY); + return plateGeometry; } public final int getChannelCount() { - return ((Integer) getFormatParameters().getValue(HCSImageFormatV1_0.NUMBER_OF_CHANNELS)) - .intValue(); + return channelCount; } private final static void checkLocation(final Geometry geometry, final Location location) @@ -93,7 +150,6 @@ public final class HCSImageFormattedData extends AbstractFormattedData implement throw new IndexOutOfBoundsException(String.format( "Channel index must start at 1 (given value is %d).", channel)); } - final int channelCount = getChannelCount(); if (channel > channelCount) { throw new IndexOutOfBoundsException(String.format( @@ -111,24 +167,14 @@ public final class HCSImageFormattedData extends AbstractFormattedData implement return ROW + wellLocation.getY() + "_" + COLUMN + wellLocation.getX() + ".tiff"; } - private final IDirectory getStandardDataDirectory() throws DataStructureException - { - return Utilities.getSubDirectory(dataDirectory, DataStructureV1_0.DIR_STANDARD); - } - - private final IDirectory getOriginalDataDirectory() throws DataStructureException + private final static String getPlateColumnDirName(final int colNumber) { - return Utilities.getSubDirectory(dataDirectory, DataStructureV1_0.DIR_ORIGINAL); + return COLUMN + colNumber; } - private final static String getPlateColumnDir(final Location plateLocation) + private final static String getPlateRowDirName(final int rowNumber) { - return COLUMN + plateLocation.getX(); - } - - private final static String getPlateRowDirName(final Location plateLocation) - { - return ROW + plateLocation.getY(); + return ROW + rowNumber; } private final static String getChannelName(final int channel) @@ -148,14 +194,14 @@ public final class HCSImageFormattedData extends AbstractFormattedData implement private final IDirectory getImageRootDirectoryNode(final File imageRootDirectory) { - final IDirectory originalDataDirectory = getOriginalDataDirectory(); + assert originalDataDirectoryOrNull != null : "original data directrory not set"; final String imageRootDirName = imageRootDirectory.getName(); // If not already present, move the 'imageRootDirectory' to 'original' data directory. - if (originalDataDirectory.tryGetNode(imageRootDirName) == null) + if (originalDataDirectoryOrNull.tryGetNode(imageRootDirName) == null) { - originalDataDirectory.addFile(imageRootDirectory, null, true); + originalDataDirectoryOrNull.addFile(imageRootDirectory, null, true); } - final INode imageRootNode = originalDataDirectory.tryGetNode(imageRootDirName); + final INode imageRootNode = originalDataDirectoryOrNull.tryGetNode(imageRootDirName); if (imageRootNode == null) { throw new DataStructureException(String.format( @@ -176,13 +222,7 @@ public final class HCSImageFormattedData extends AbstractFormattedData implement checkCoordinates(channel, wellLocation, tileLocation); try { - final IDirectory standardDir = getStandardDataDirectory(); - final IDirectory channelDir = - Utilities.getSubDirectory(standardDir, getChannelName(channel)); - final IDirectory plateRowDir = - Utilities.getSubDirectory(channelDir, getPlateRowDirName(wellLocation)); - final IDirectory plateColumnDir = - Utilities.getSubDirectory(plateRowDir, getPlateColumnDir(wellLocation)); + final IDirectory plateColumnDir = getWellImagesParentDir(channel, wellLocation); return plateColumnDir.tryGetNode(createWellFileName(tileLocation)); } catch (final DataStructureException e) { @@ -190,38 +230,157 @@ public final class HCSImageFormattedData extends AbstractFormattedData implement } } + private IDirectory getWellImagesParentDir(final int channel, final Location wellLocation) + { + DirectoryContentCache channelDirCache = standardDataDirectoryCache.getSubdirectory(channel); + DirectoryContentCache rowDirCache = channelDirCache.getSubdirectory(wellLocation.getY()); + DirectoryContentCache colDirCache = rowDirCache.getSubdirectory(wellLocation.getX()); + return colDirCache.getDirectory(); + } + + private final void updateImageRootDirectory(final File imageRootDirectory) + { + assert imageRootDirectory != null : "Given image root directory can not be null."; + + if (imageRootDirectory == currentImageRootDirectory) + { + return; // small performance optimization + } + if (imageRootDirectory.equals(currentImageRootDirectory) == false) + { + this.currentImageRootDirectory = imageRootDirectory; + this.currentImageRootDirectoryNode = getImageRootDirectoryNode(imageRootDirectory); + } + } + + // Allows for easy cached access to sub-directories which are identified by integer numbers. + // Allows to access items in sub-directories using the same cached mechanism. + // Useful when getting access to an existing directory is an expensive operation. + private static class DirectoryContentCache + { + private final IDirectory currentDir; + + private final Map<Integer, DirectoryContentCache> subdirsCache; + + private final INumberedDirNameProvider nameProviderOrNull; + + public DirectoryContentCache(IDirectory currentDir, + INumberedDirNameProvider nameProviderOrNull) + { + this.currentDir = currentDir; + this.nameProviderOrNull = nameProviderOrNull; + this.subdirsCache = new HashMap<Integer, DirectoryContentCache>(); + } + + public DirectoryContentCache getSubdirectory(int directoryNumber) + { + assert nameProviderOrNull != null : "this directory is no expected to have numbered subdirectories"; + DirectoryContentCache subdirCache = subdirsCache.get(directoryNumber); + if (subdirCache == null) + { + String subdirName = nameProviderOrNull.getName(directoryNumber); + // this operation is cached as it can be expensive + IDirectory subdir = currentDir.makeDirectory(subdirName); + INumberedDirNameProvider subdirNameProviderOrNull = + nameProviderOrNull.tryGetSubdirectoryProvider(); + subdirCache = new DirectoryContentCache(subdir, subdirNameProviderOrNull); + subdirsCache.put(directoryNumber, subdirCache); + } + return subdirCache; + } + + public IDirectory getDirectory() + { + return currentDir; + } + } + + private static interface INumberedDirNameProvider + { + // name of a sub-directory with a given number + String getName(int number); + + // naming schema for directories inside sub-directory + INumberedDirNameProvider tryGetSubdirectoryProvider(); + } + + private static INumberedDirNameProvider createChannelDirNameProvider() + { + return new INumberedDirNameProvider() + { + + public String getName(int channel) + { + return getChannelName(channel); + } + + public INumberedDirNameProvider tryGetSubdirectoryProvider() + { + return createRowDirNameProvider(); + } + }; + } + + private static INumberedDirNameProvider createRowDirNameProvider() + { + return new INumberedDirNameProvider() + { + + public String getName(int row) + { + return getPlateRowDirName(row); + } + + public INumberedDirNameProvider tryGetSubdirectoryProvider() + { + return createColumnDirNameProvider(); + } + }; + } + + private static INumberedDirNameProvider createColumnDirNameProvider() + { + return new INumberedDirNameProvider() + { + + public String getName(int column) + { + return getPlateColumnDirName(column); + } + + public INumberedDirNameProvider tryGetSubdirectoryProvider() + { + return null; + } + }; + } + public final NodePath addStandardNode(final File imageRootDirectory, final String imageRelativePath, final int channel, final Location wellLocation, final Location tileLocation) throws DataStructureException { - assert imageRootDirectory != null : "Given image root directory can not be null."; assert imageRelativePath != null : "Given image relative path can not be null."; - INode node = tryGetStandardNodeAt(channel, wellLocation, tileLocation); - if (node != null) - { - throw new DataStructureException( - String - .format( - "A node already exists at channel %d, plate location '%s' and well location '%s'.", - channel, wellLocation, tileLocation)); - } - final IDirectory standardDir = getStandardDataDirectory(); - final IDirectory channelDir = - Utilities.getOrCreateSubDirectory(standardDir, getChannelName(channel)); - final IDirectory plateRowDir = - Utilities.getOrCreateSubDirectory(channelDir, getPlateRowDirName(wellLocation)); - final IDirectory plateColumnDir = - Utilities.getOrCreateSubDirectory(plateRowDir, getPlateColumnDir(wellLocation)); + + check(channel, wellLocation, tileLocation); + DirectoryContentCache channelDirCache = standardDataDirectoryCache.getSubdirectory(channel); + DirectoryContentCache rowDirCache = channelDirCache.getSubdirectory(wellLocation.getY()); + DirectoryContentCache colDirCache = rowDirCache.getSubdirectory(wellLocation.getX()); + final IDirectory plateColumnDir = colDirCache.getDirectory(); + final String wellFileName = createWellFileName(tileLocation); - if (containsOriginalData()) + final INode node; + if (containsOriginalData) { - final IDirectory imageRootDirectoryNode = getImageRootDirectoryNode(imageRootDirectory); - final INode imageNode = imageRootDirectoryNode.tryGetNode(imageRelativePath); + updateImageRootDirectory(imageRootDirectory); + // NOTE: existence of the node is checked, it can be slow for remote file systems + final INode imageNode = currentImageRootDirectoryNode.tryGetNode(imageRelativePath); if (imageNode == null) { - throw new DataStructureException(String.format( - "No image node with path '%s' could be found in the original directory.", - imageRelativePath)); + throw new DataStructureException( + String + .format( + "No image node with path '%s' could be found in the 'original data' directory.", + imageRelativePath)); } node = plateColumnDir.tryAddLink(wellFileName, imageNode); } else @@ -241,11 +400,80 @@ public final class HCSImageFormattedData extends AbstractFormattedData implement } final char sep = Constants.PATH_SEPARATOR; final String standardNodePath = - channelDir.getName() + sep + plateRowDir.getName() + sep + plateColumnDir.getName() + channelDirCache.getDirectory().getName() + sep + + rowDirCache.getDirectory().getName() + sep + plateColumnDir.getName() + sep + wellFileName; return new NodePath(node, standardNodePath); } + /** Am key class for HCS image files. */ + private static class ImageFileKey + { + final private int channel; + + final private Location wellLocation; + + final private Location tileLocation; + + ImageFileKey(final int channel, final Location wellLocation, final Location tileLocation) + { + assert channel >= 0; + assert wellLocation != null; + assert tileLocation != null; + + this.channel = channel; + this.wellLocation = wellLocation; + this.tileLocation = tileLocation; + } + + // + // Object + // + + @Override + public boolean equals(Object obj) + { + if (obj == null || obj instanceof ImageFileKey == false) + { + return false; + } + final ImageFileKey that = (ImageFileKey) obj; + return this.channel == that.channel && this.wellLocation.equals(that.wellLocation) + && this.tileLocation.equals(that.tileLocation); + } + + @Override + public int hashCode() + { + int hashCode = 17; + hashCode = hashCode * 37 + channel; + hashCode = hashCode * 37 + wellLocation.hashCode(); + hashCode = hashCode * 37 + tileLocation.hashCode(); + return hashCode; + } + } + + private final HashSet<ImageFileKey> imageFilesStored = new HashSet<ImageFileKey>(); + + private void check(final int channel, final Location wellLocation, final Location tileLocation) + { + checkCoordinates(channel, wellLocation, tileLocation); + final ImageFileKey key = new ImageFileKey(channel, wellLocation, tileLocation); + final boolean alreadyStored = imageFilesStored.contains(key); + if (alreadyStored == false) + { + imageFilesStored.add(key); + } + if (alreadyStored) + { + throw new DataStructureException( + String + .format( + "A node already exists at channel %d, plate location '%s' and well location '%s'.", + channel, wellLocation, tileLocation)); + } + } + // // AbstractFormattedData // diff --git a/bds/source/java/ch/systemsx/cisd/bds/storage/IDirectory.java b/bds/source/java/ch/systemsx/cisd/bds/storage/IDirectory.java index 62b8e9c4113ddf4e9e45ce83275a1b7baae7cfe6..9f6d7353b940e80f0d9dd761a20572b0334c32a3 100644 --- a/bds/source/java/ch/systemsx/cisd/bds/storage/IDirectory.java +++ b/bds/source/java/ch/systemsx/cisd/bds/storage/IDirectory.java @@ -17,6 +17,7 @@ package ch.systemsx.cisd.bds.storage; import java.io.File; +import java.util.List; /** * Node representing a directory. @@ -32,6 +33,27 @@ public interface IDirectory extends INode, Iterable<INode> */ public INode tryGetNode(final String name); + /** + * Finds file nodes within this directory (and optionally its sub-directories) which match an + * array of extensions. + * + * @param extensionsOrNull An array of extensions, ex. {"tiff","tif"}. If this parameter is + * <code>null</code>, all files are returned. + * @param recursive If <code>true</code> all sub-directories are searched as well. + * @return A list of {@link INode}s with the nodes that matched. This list is <i>not</i> + * ordered. + */ + public List<IFile> listFiles(String[] extensionsOrNull, boolean recursive); + + /** + * Finds directory nodes within this directory (and optionally its sub-directories). + * + * @param recursive If <code>true</code> all sub-directories are searched as well. + * @return A list of {@link INode}s with the nodes that matched. This list is <i>not</i> + * ordered. + */ + public List<IDirectory> listDirectories(boolean recursive); + /** * Makes a new subdirectory in this directory. Does nothing if the subdirectory already exists. * diff --git a/bds/source/java/ch/systemsx/cisd/bds/storage/IFileBasedDirectory.java b/bds/source/java/ch/systemsx/cisd/bds/storage/IFileBasedDirectory.java new file mode 100644 index 0000000000000000000000000000000000000000..6097e934b92690917af0f4e933e025f7ee1de839 --- /dev/null +++ b/bds/source/java/ch/systemsx/cisd/bds/storage/IFileBasedDirectory.java @@ -0,0 +1,26 @@ +/* + * 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; + +/** + * An {@link IDirectory} that also implements {@link IFileBasedNode}. + * + * @author Bernd Rinn + */ +public interface IFileBasedDirectory extends IDirectory, IFileBasedNode +{ +} diff --git a/bds/source/java/ch/systemsx/cisd/bds/storage/IFileBasedFile.java b/bds/source/java/ch/systemsx/cisd/bds/storage/IFileBasedFile.java new file mode 100644 index 0000000000000000000000000000000000000000..1b4e7af51aa8b6b024fcca81b0e29ac03f0709b3 --- /dev/null +++ b/bds/source/java/ch/systemsx/cisd/bds/storage/IFileBasedFile.java @@ -0,0 +1,26 @@ +/* + * 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; + +/** + * An {@link IFile} that also implements {@link IFileBasedNode}. + * + * @author Bernd Rinn + */ +public interface IFileBasedFile extends IFile, IFileBasedNode +{ +} diff --git a/bds/source/java/ch/systemsx/cisd/bds/storage/IFileBasedLink.java b/bds/source/java/ch/systemsx/cisd/bds/storage/IFileBasedLink.java new file mode 100644 index 0000000000000000000000000000000000000000..8ddc1e478ad71718f2f25dff4b339af5facf4443 --- /dev/null +++ b/bds/source/java/ch/systemsx/cisd/bds/storage/IFileBasedLink.java @@ -0,0 +1,28 @@ +/* + * 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; + +/** + * An {@link ILink} that also implements {@link IFileBasedNode}. + * + * @author Bernd Rinn + */ +public interface IFileBasedLink extends ILink, IFileBasedNode +{ + /** Sets the parent of this {@link INode}. */ + public void setParent(final IDirectory parentOrNull); +} diff --git a/bds/source/java/ch/systemsx/cisd/bds/storage/IFileBasedNode.java b/bds/source/java/ch/systemsx/cisd/bds/storage/IFileBasedNode.java new file mode 100644 index 0000000000000000000000000000000000000000..f5683356fdf6fa5d171538a0b87e07b4f3f88f1a --- /dev/null +++ b/bds/source/java/ch/systemsx/cisd/bds/storage/IFileBasedNode.java @@ -0,0 +1,28 @@ +/* + * 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; + +/** + * An {@link INode} which can deliver a node file. + * + * @author Bernd Rinn + */ +public interface IFileBasedNode extends INode +{ + /** Returns the underlying node file of this node. */ + public java.io.File getNodeFile(); +} diff --git a/bds/source/java/ch/systemsx/cisd/bds/storage/INode.java b/bds/source/java/ch/systemsx/cisd/bds/storage/INode.java index 27dcafe7409bd321d3e879ace3a4a0a9113c5b0c..881f4b6afd4e2185e6c80197a0d1df7853b59aab 100644 --- a/bds/source/java/ch/systemsx/cisd/bds/storage/INode.java +++ b/bds/source/java/ch/systemsx/cisd/bds/storage/INode.java @@ -28,13 +28,29 @@ public interface INode */ public String getName(); + /** + * Returns the path of this node. + */ + public String getPath(); + /** * Returns the parent directory of this node or <code>null</code> if it is the root node. */ - public IDirectory tryToGetParent(); + public IDirectory tryGetParent(); /** - * Whether this <code>INode</code> is valid. + * Returns this node as a directory, or <code>null</code>, if this node is no directory. + */ + public IDirectory tryAsDirectory(); + + /** + * Returns this node as a file, or <code>null</code>, if this node is no file. + */ + public IFile tryAsFile(); + + /** + * Whether this <code>INode</code> is valid. As a minimum, a node needs to exist and be readable + * in order to be valid. Sub-classes can define additional requirements of validity. */ public boolean isValid(); diff --git a/bds/source/java/ch/systemsx/cisd/bds/storage/filesystem/AbstractNode.java b/bds/source/java/ch/systemsx/cisd/bds/storage/filesystem/AbstractNode.java index c79cf19f0ec850db2e7115c648e298ab02822de1..9a646adf7389c83bf0d402b94eaf3685d3b6220d 100644 --- a/bds/source/java/ch/systemsx/cisd/bds/storage/filesystem/AbstractNode.java +++ b/bds/source/java/ch/systemsx/cisd/bds/storage/filesystem/AbstractNode.java @@ -18,23 +18,27 @@ package ch.systemsx.cisd.bds.storage.filesystem; import java.io.File; +import org.apache.commons.lang.ObjectUtils; + import ch.systemsx.cisd.bds.exception.StorageException; import ch.systemsx.cisd.bds.storage.IDirectory; -import ch.systemsx.cisd.bds.storage.INode; +import ch.systemsx.cisd.bds.storage.IFileBasedNode; import ch.systemsx.cisd.common.exceptions.EnvironmentFailureException; +import ch.systemsx.cisd.common.filesystem.FileOperations; /** * An abstract implementation of <code>INode</code>. * * @author Franz-Josef Elmer */ -abstract class AbstractNode implements INode +abstract class AbstractNode implements IFileBasedNode { protected final static File moveFileToDirectory(final File source, final File directory, final String nameOrNull) throws EnvironmentFailureException { assert source != null; - assert directory != null && directory.isDirectory(); + assert directory != null + && FileOperations.getMonitoredInstanceForCurrentThread().isDirectory(directory); final String newName; if (nameOrNull == null) { @@ -44,13 +48,15 @@ abstract class AbstractNode implements INode newName = nameOrNull; } final File destination = new File(directory, newName); - if (destination.exists() == false) + if (FileOperations.getMonitoredInstanceForCurrentThread().exists(destination) == false) { - final boolean successful = source.renameTo(destination); + final boolean successful = + FileOperations.getMonitoredInstanceForCurrentThread().rename(source, + destination); if (successful == false) { throw EnvironmentFailureException.fromTemplate( - "Couldn't not move file '%s' to directory '%s'.", source.getAbsolutePath(), + "Can not move file '%s' to directory '%s'.", source.getAbsolutePath(), directory.getAbsolutePath()); } } @@ -71,13 +77,22 @@ abstract class AbstractNode implements INode { throw new StorageException("Unspecified file."); } - if (file.exists() == false) + if (FileOperations.getMonitoredInstanceForCurrentThread().exists(file) == false) { throw new StorageException(String.format("Non existing file '%s'.", file .getAbsolutePath())); } } + // + // IFileBasedNode + // + + public java.io.File getNodeFile() + { + return nodeFile; + } + // // INode // @@ -87,10 +102,15 @@ abstract class AbstractNode implements INode return nodeFile.getName(); } - public final IDirectory tryToGetParent() + public String getPath() + { + return nodeFile.getAbsolutePath(); + } + + public final IDirectory tryGetParent() { File dir = nodeFile.getParentFile(); - return dir == null ? null : new Directory(dir); + return dir == null ? null : NodeFactory.internalCreateDirectoryNode(dir); } public final void moveTo(final File directory) @@ -100,7 +120,7 @@ abstract class AbstractNode implements INode public boolean isValid() { - return nodeFile.exists(); + return FileOperations.getMonitoredInstanceForCurrentThread().canRead(nodeFile); } // @@ -112,4 +132,21 @@ abstract class AbstractNode implements INode { return nodeFile.getAbsolutePath(); } + + @Override + public boolean equals(Object obj) + { + if (obj instanceof IFileBasedNode == false) + { + return false; + } + return ObjectUtils.equals(nodeFile, ((IFileBasedNode) obj).getNodeFile()); + } + + @Override + public int hashCode() + { + return nodeFile.hashCode(); + } + } diff --git a/bds/source/java/ch/systemsx/cisd/bds/storage/filesystem/Directory.java b/bds/source/java/ch/systemsx/cisd/bds/storage/filesystem/Directory.java index ce1edb24fa16b34426d4cb6110e9f29cedd869ac..cf751eb36f4b6e327f03a054368d35351a25544a 100644 --- a/bds/source/java/ch/systemsx/cisd/bds/storage/filesystem/Directory.java +++ b/bds/source/java/ch/systemsx/cisd/bds/storage/filesystem/Directory.java @@ -16,32 +16,36 @@ package ch.systemsx.cisd.bds.storage.filesystem; -import java.io.IOException; +import java.util.ArrayList; +import java.util.Collections; import java.util.Iterator; - -import org.apache.commons.io.FileUtils; +import java.util.List; import ch.systemsx.cisd.bds.Constants; import ch.systemsx.cisd.bds.exception.StorageException; import ch.systemsx.cisd.bds.storage.IDirectory; import ch.systemsx.cisd.bds.storage.IFile; +import ch.systemsx.cisd.bds.storage.IFileBasedDirectory; +import ch.systemsx.cisd.bds.storage.IFileBasedLink; +import ch.systemsx.cisd.bds.storage.IFileBasedNode; import ch.systemsx.cisd.bds.storage.ILink; import ch.systemsx.cisd.bds.storage.INode; import ch.systemsx.cisd.common.exceptions.EnvironmentFailureException; -import ch.systemsx.cisd.common.utilities.FileUtilities; +import ch.systemsx.cisd.common.exceptions.WrappedIOException; +import ch.systemsx.cisd.common.filesystem.FileOperations; /** * An <code>IDirectory</code> implementation. * * @author Franz-Josef Elmer */ -final class Directory extends AbstractNode implements IDirectory +final class Directory extends AbstractNode implements IFileBasedDirectory { Directory(final java.io.File directory) { super(directory); - if (directory.isDirectory() == false) + if (FileOperations.getMonitoredInstanceForCurrentThread().isDirectory(directory) == false) { throw new StorageException(String.format("Not a directory '%s'.", directory .getAbsolutePath())); @@ -50,8 +54,8 @@ final class Directory extends AbstractNode implements IDirectory private final static java.io.File getNodeFile(final INode node) { - assert node instanceof AbstractNode : "Must be an instance of AbstractNode."; - return ((AbstractNode) node).nodeFile; + assert node instanceof IFileBasedNode : "Must be an instance of IFileBasedNode."; + return ((IFileBasedNode) node).getNodeFile(); } private final static String cleanName(final String name) @@ -64,6 +68,16 @@ final class Directory extends AbstractNode implements IDirectory return name; } + public IDirectory tryAsDirectory() + { + return this; + } + + public IFile tryAsFile() + { + return null; + } + // // IDirectory // @@ -74,9 +88,9 @@ final class Directory extends AbstractNode implements IDirectory final String path = cleanName(name.replace('\\', Constants.PATH_SEPARATOR)); java.io.File childrenNodeFile = new java.io.File(this.nodeFile, path); - if (childrenNodeFile.exists()) + if (FileOperations.getMonitoredInstanceForCurrentThread().exists(childrenNodeFile)) { - return NodeFactory.createNode(childrenNodeFile); + return NodeFactory.internalCreateNode(childrenNodeFile); } else { return null; @@ -87,22 +101,22 @@ final class Directory extends AbstractNode implements IDirectory { assert name != null : "Given name can not be null."; java.io.File dir = new java.io.File(nodeFile, name); - if (dir.exists()) + if (FileOperations.getMonitoredInstanceForCurrentThread().exists(dir)) { - if (dir.isDirectory() == false) + if (FileOperations.getMonitoredInstanceForCurrentThread().isDirectory(dir) == false) { throw new StorageException("There already exists a file named '" + name + "' in directory " + this); } - return new Directory(dir); + return NodeFactory.internalCreateDirectoryNode(dir); } - boolean successful = dir.mkdir(); + boolean successful = FileOperations.getMonitoredInstanceForCurrentThread().mkdir(dir); if (successful == false) { throw new EnvironmentFailureException("Couldn't create directory " + dir.getAbsolutePath() + " for some unknown reason."); } - return new Directory(dir); + return NodeFactory.internalCreateDirectoryNode(dir); } public final IFile addKeyValuePair(final String key, final String value) @@ -113,8 +127,8 @@ final class Directory extends AbstractNode implements IDirectory throw new IllegalArgumentException("Value for key '" + key + "' not specified."); } java.io.File file = new java.io.File(nodeFile, key); - FileUtilities.writeToFile(file, value); - return new File(file); + FileOperations.getMonitoredInstanceForCurrentThread().writeToFile(file, value); + return NodeFactory.internalCreateFileNode(file); } public final INode addFile(final java.io.File file, final String name, final boolean move) @@ -136,21 +150,22 @@ final class Directory extends AbstractNode implements IDirectory { try { - if (file.isDirectory()) + if (FileOperations.getMonitoredInstanceForCurrentThread().isDirectory(file)) { - FileUtils.copyDirectory(file, newFile); + FileOperations.getMonitoredInstanceForCurrentThread().copyDirectory(file, + newFile); } else { - FileUtils.copyFile(file, newFile); + FileOperations.getMonitoredInstanceForCurrentThread().copyFile(file, newFile); } - } catch (IOException ex) + } catch (WrappedIOException ex) { throw EnvironmentFailureException.fromTemplate(ex, - "Couldn't not copy file '%s' to directory '%s'.", file, nodeFile + "Can not copy file '%s' to directory '%s'.", file, nodeFile .getAbsolutePath()); } } - return NodeFactory.createNode(newFile); + return NodeFactory.internalCreateNode(newFile); } public final ILink tryAddLink(final String name, final INode node) @@ -158,11 +173,10 @@ final class Directory extends AbstractNode implements IDirectory assert node != null : "Node can not be null."; assert name != null : "Name can not be null."; final java.io.File file = getNodeFile(node); - final boolean ok = - LinkMakerProvider.getLinkMaker().copyImmutably(file, nodeFile, name); + final boolean ok = LinkMakerProvider.getLinkMaker().copyImmutably(file, nodeFile, name); if (ok) { - final Link link = (Link) NodeFactory.createLinkNode(name, file); + final IFileBasedLink link = (IFileBasedLink) NodeFactory.createLinkNode(name, file); link.setParent(this); return link; } @@ -173,7 +187,9 @@ final class Directory extends AbstractNode implements IDirectory { return new Iterator<INode>() { - private java.io.File[] files = FileUtilities.listFiles(nodeFile); + private List<java.io.File> files = + FileOperations.getMonitoredInstanceForCurrentThread() + .listFilesAndDirectories(nodeFile, false); private int index; @@ -188,12 +204,13 @@ final class Directory extends AbstractNode implements IDirectory public INode next() { - return index >= files.length ? null : NodeFactory.createNode(files[index++]); + return index >= files.size() ? null : NodeFactory.internalCreateNode(files + .get(index++)); } public boolean hasNext() { - return index < files.length; + return index < files.size(); } }; } @@ -204,11 +221,12 @@ final class Directory extends AbstractNode implements IDirectory // ...but might not exist try { - FileUtils.copyDirectoryToDirectory(nodeFile, directory); - } catch (IOException ex) + FileOperations.getMonitoredInstanceForCurrentThread().copyDirectoryToDirectory( + nodeFile, directory); + } catch (WrappedIOException ex) { throw EnvironmentFailureException.fromTemplate(ex, - "Couldn't copy directory '%s' to directory '%s'.", nodeFile.getAbsolutePath(), + "Can not copy directory '%s' to directory '%s'.", nodeFile.getAbsolutePath(), directory.getAbsolutePath()); } } @@ -217,26 +235,50 @@ final class Directory extends AbstractNode implements IDirectory { assert node != null : "Node could not be null"; final java.io.File file = getNodeFile(node); - if (file.isDirectory()) + if (FileOperations.getMonitoredInstanceForCurrentThread().isDirectory(file)) { - if (FileUtilities.deleteRecursively(file) == false) + try { - throw EnvironmentFailureException.fromTemplate("Couldn't remove directory '%s'.", + FileOperations.getMonitoredInstanceForCurrentThread().deleteRecursively(file); + } catch (WrappedIOException ex) + { + throw EnvironmentFailureException.fromTemplate("Can not remove directory '%s'.", file.getAbsolutePath()); } - } else if (file.isFile()) + } else if (FileOperations.getMonitoredInstanceForCurrentThread().isFile(file)) { - if (file.delete() == false) + if (FileOperations.getMonitoredInstanceForCurrentThread().delete(file) == false) { - throw EnvironmentFailureException.fromTemplate("Couldn't remove file '%s'.", file + throw EnvironmentFailureException.fromTemplate("Can not remove file '%s'.", file .getAbsolutePath()); } } } - @Override - public final boolean isValid() + public List<IFile> listFiles(String[] extensionsOrNull, boolean recursive) { - return super.isValid() && FileUtilities.checkDirectoryFullyAccessible(nodeFile, "") == null; + final List<java.io.File> files = + FileOperations.getMonitoredInstanceForCurrentThread().listFiles(nodeFile, + extensionsOrNull, recursive); + final List<IFile> nodes = new ArrayList<IFile>(files.size()); + for (java.io.File f : files) + { + nodes.add(NodeFactory.internalCreateFileNode(f)); + } + return Collections.unmodifiableList(nodes); } + + public List<IDirectory> listDirectories(boolean recursive) + { + final List<java.io.File> files = + FileOperations.getMonitoredInstanceForCurrentThread().listDirectories(nodeFile, + recursive); + final List<IDirectory> nodes = new ArrayList<IDirectory>(files.size()); + for (java.io.File f : files) + { + nodes.add(NodeFactory.internalCreateDirectoryNode(f)); + } + return Collections.unmodifiableList(nodes); + } + } diff --git a/bds/source/java/ch/systemsx/cisd/bds/storage/filesystem/File.java b/bds/source/java/ch/systemsx/cisd/bds/storage/filesystem/File.java index ef9251442cf83d7895092b467c796f996f058cb9..8ad39a633ac854d70a2c3739f61485fde3d3397d 100644 --- a/bds/source/java/ch/systemsx/cisd/bds/storage/filesystem/File.java +++ b/bds/source/java/ch/systemsx/cisd/bds/storage/filesystem/File.java @@ -16,30 +16,38 @@ package ch.systemsx.cisd.bds.storage.filesystem; -import java.io.FileInputStream; -import java.io.FileNotFoundException; -import java.io.IOException; import java.io.InputStream; import java.util.List; -import org.apache.commons.io.FileUtils; -import org.apache.commons.io.IOUtils; - +import ch.systemsx.cisd.bds.storage.IDirectory; import ch.systemsx.cisd.bds.storage.IFile; +import ch.systemsx.cisd.bds.storage.IFileBasedFile; import ch.systemsx.cisd.common.exceptions.EnvironmentFailureException; -import ch.systemsx.cisd.common.utilities.FileUtilities; +import ch.systemsx.cisd.common.exceptions.WrappedIOException; +import ch.systemsx.cisd.common.filesystem.FileOperations; /** * An <code>IFile</code> implementation. * * @author Franz-Josef Elmer */ -final class File extends AbstractNode implements IFile +final class File extends AbstractNode implements IFileBasedFile { File(final java.io.File file) { super(file); - assert file.isFile() : "Not a file " + file.getAbsolutePath(); + assert FileOperations.getMonitoredInstanceForCurrentThread().isFile(file) : "Not a file " + + file.getAbsolutePath(); + } + + public IDirectory tryAsDirectory() + { + return null; + } + + public IFile tryAsFile() + { + return this; } // @@ -48,17 +56,14 @@ final class File extends AbstractNode implements IFile public final byte[] getBinaryContent() { - final InputStream inputStream = getInputStream(); try { - return IOUtils.toByteArray(inputStream); - } catch (final IOException ex) - { - throw new EnvironmentFailureException("Couldn't get data from file " - + nodeFile.getAbsolutePath(), ex); - } finally + return FileOperations.getMonitoredInstanceForCurrentThread().getContentAsByteArray( + nodeFile); + } catch (WrappedIOException ex) { - IOUtils.closeQuietly(inputStream); + throw new EnvironmentFailureException("Can not load data from file " + + nodeFile.getAbsolutePath(), ex.getCause()); } } @@ -66,27 +71,29 @@ final class File extends AbstractNode implements IFile { try { - return new FileInputStream(nodeFile); - } catch (final FileNotFoundException ex) + return FileOperations.getMonitoredInstanceForCurrentThread().getInputStream(nodeFile); + } catch (WrappedIOException ex) { - throw new EnvironmentFailureException("Couldn't open input stream for file " - + nodeFile.getAbsolutePath()); + throw new EnvironmentFailureException("Can not open input stream for file " + + nodeFile.getAbsolutePath(), ex.getCause()); } } public final String getStringContent() { - return FileUtilities.loadToString(nodeFile); + return FileOperations.getMonitoredInstanceForCurrentThread().getContentAsString(nodeFile); } public final String getExactStringContent() { - return FileUtilities.loadExactToString(nodeFile); + return FileOperations.getMonitoredInstanceForCurrentThread().getExactContentAsString( + nodeFile); } public final List<String> getStringContentList() { - return FileUtilities.loadToStringList(nodeFile); + return FileOperations.getMonitoredInstanceForCurrentThread().getContentAsStringList( + nodeFile); } public final void extractTo(final java.io.File directory) throws EnvironmentFailureException @@ -94,11 +101,12 @@ final class File extends AbstractNode implements IFile assert directory != null && directory.isDirectory(); try { - FileUtils.copyFileToDirectory(nodeFile, directory); - } catch (final IOException ex) + FileOperations.getMonitoredInstanceForCurrentThread().copyFileToDirectory(nodeFile, + directory); + } catch (WrappedIOException ex) { - throw EnvironmentFailureException.fromTemplate(ex, - "Couldn't not copy file '%s' to directory '%s'.", nodeFile.getAbsolutePath(), + throw EnvironmentFailureException.fromTemplate(ex.getCause(), + "Can not copy file '%s' to directory '%s'.", nodeFile.getAbsolutePath(), directory.getAbsolutePath()); } } diff --git a/bds/source/java/ch/systemsx/cisd/bds/storage/filesystem/FileStorage.java b/bds/source/java/ch/systemsx/cisd/bds/storage/filesystem/FileStorage.java index c67f85fbd6aeded3b6600bab4cbdafea74ca031b..5731b4a9654e3b937029bf8866bc3e8d2f77a822 100644 --- a/bds/source/java/ch/systemsx/cisd/bds/storage/filesystem/FileStorage.java +++ b/bds/source/java/ch/systemsx/cisd/bds/storage/filesystem/FileStorage.java @@ -29,7 +29,7 @@ import ch.systemsx.cisd.bds.storage.IStorage; */ public class FileStorage implements IStorage { - private final Directory root; + private final IDirectory root; private boolean mounted; @@ -41,7 +41,7 @@ public class FileStorage implements IStorage */ public FileStorage(File folder) { - root = new Directory(folder); + root = NodeFactory.createDirectoryNode(folder); } public IDirectory getRoot() diff --git a/bds/source/java/ch/systemsx/cisd/bds/storage/filesystem/Link.java b/bds/source/java/ch/systemsx/cisd/bds/storage/filesystem/Link.java index b632c04ae7b946915b0338d1c7992c420eae62a8..cea952266948e94a598f7c41730cba44099e0222 100644 --- a/bds/source/java/ch/systemsx/cisd/bds/storage/filesystem/Link.java +++ b/bds/source/java/ch/systemsx/cisd/bds/storage/filesystem/Link.java @@ -18,9 +18,12 @@ package ch.systemsx.cisd.bds.storage.filesystem; import java.io.File; +import com.sun.corba.se.impl.orbutil.ObjectUtility; + 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.IFileBasedLink; +import ch.systemsx.cisd.bds.storage.IFileBasedNode; import ch.systemsx.cisd.bds.storage.INode; /** @@ -28,15 +31,15 @@ import ch.systemsx.cisd.bds.storage.INode; * * @author Franz-Josef Elmer */ -final class Link implements ILink +final class Link implements IFileBasedLink { private final String name; - private final INode reference; + private final IFileBasedNode reference; private IDirectory parent; - Link(final String name, final INode reference) + Link(final String name, final IFileBasedNode reference) { assert name != null : "A name must be specified."; assert reference != null : "Reference can not be null."; @@ -48,11 +51,21 @@ final class Link implements ILink } /** Sets the parent of this {@link INode}. */ - final void setParent(final IDirectory parentOrNull) + public final void setParent(final IDirectory parentOrNull) { parent = parentOrNull; } + public IDirectory tryAsDirectory() + { + return (reference instanceof IDirectory) ? (IDirectory) reference : null; + } + + public IFile tryAsFile() + { + return (reference instanceof IFile) ? (IFile) reference : null; + } + // // ILink // @@ -62,7 +75,12 @@ final class Link implements ILink return name; } - public final IDirectory tryToGetParent() + public String getPath() + { + return parent.getPath() + "/" + getPath(); + } + + public final IDirectory tryGetParent() { return parent; } @@ -95,4 +113,36 @@ final class Link implements ILink } return true; } + + public File getNodeFile() + { + return reference.getNodeFile(); + } + + // + // Object + // + + @Override + public final String toString() + { + return getPath(); + } + + @Override + public boolean equals(Object obj) + { + if (obj instanceof IFileBasedLink == false) + { + return false; + } + return ObjectUtility.equals(getPath(), ((IFileBasedLink) obj).getPath()); + } + + @Override + public int hashCode() + { + return getPath().hashCode(); + } + } diff --git a/bds/source/java/ch/systemsx/cisd/bds/storage/filesystem/NodeFactory.java b/bds/source/java/ch/systemsx/cisd/bds/storage/filesystem/NodeFactory.java index 62ec78acd4d6f30a60aba15679026290ce6529bf..77b7c9a85b8488fa87b9ac6b46660cf6e2340550 100644 --- a/bds/source/java/ch/systemsx/cisd/bds/storage/filesystem/NodeFactory.java +++ b/bds/source/java/ch/systemsx/cisd/bds/storage/filesystem/NodeFactory.java @@ -16,13 +16,15 @@ package ch.systemsx.cisd.bds.storage.filesystem; -import java.io.IOException; - import ch.systemsx.cisd.bds.storage.IDirectory; import ch.systemsx.cisd.bds.storage.IFile; +import ch.systemsx.cisd.bds.storage.IFileBasedDirectory; +import ch.systemsx.cisd.bds.storage.IFileBasedFile; +import ch.systemsx.cisd.bds.storage.IFileBasedNode; import ch.systemsx.cisd.bds.storage.ILink; import ch.systemsx.cisd.bds.storage.INode; import ch.systemsx.cisd.common.exceptions.EnvironmentFailureException; +import ch.systemsx.cisd.common.filesystem.FileOperations; /** * A <code>INode</code> factory class. @@ -37,40 +39,13 @@ public final class NodeFactory { /** - * A <code>INode</code> factory method for given <var>file</var>. - * <p> - * IMPORTANT NOTE: we compare the absolute path against the canonical one to found out whether - * it is a link or not. This only works for <i>symbolic</i> links and not for <i>hard</i> - * links. - * </p> + * A <code>INode</code> factory method for given <var>file</var>. It does not support creating + * links, because only symbolic links could be recognized. */ public static INode createNode(final java.io.File file) throws EnvironmentFailureException { - assert file != null : "Unspecified node"; - final String absolutePath = file.getAbsolutePath(); - final String canonicalPath = getCanonicalPath(file); - if (absolutePath.equals(canonicalPath) == false) - { - return createLinkNode(file); - } - if (file.isDirectory()) - { - return createDirectoryNode(file); - } - return createFileNode(file); - } - - private final static String getCanonicalPath(final java.io.File file) - { - assert file != null : "Unspecified node"; - try - { - return file.getCanonicalPath(); - } catch (IOException ex) - { - throw new EnvironmentFailureException("Couldn't get canonical path of file '" - + file.getAbsolutePath() + "'", ex); - } + assert file != null : "Given node can not be null"; + return internalCreateNode(file); } /** @@ -79,28 +54,30 @@ public final class NodeFactory */ public final static ILink createLinkNode(final String name, final java.io.File file) { - assert file != null : "Given file can not be null."; - assert name != null : "Given name can not be null."; - return new Link(name, createNode(file)); + assert file != null : "Given file can not be null"; + assert name != null : "Given name can not be null"; + return new Link(name, internalCreateNode(file)); } /** - * Creates a new <code>ILink</code>. + * Creates a new <code>ILink</code> assuming that the given file is a symbolic link. * <p> - * IMPORTANT NOTE: we compare the absolute path against the canonical one to found out whether - * it is a link or not. This only works for <i>symbolic</i> links and not for <i>hard</i> - * links. + * IMPORTANT NOTE: we compare the absolute path against the canonical one to find out whether it + * is a link or not. This only works for <i>symbolic</i> links and not for <i>hard</i> links. * </p> */ - public final static ILink createLinkNode(final java.io.File file) + public final static ILink createSymbolicLinkNode(final java.io.File file) throws EnvironmentFailureException { - final String canonicalPath = getCanonicalPath(file); final String absolutePath = file.getAbsolutePath(); - assert absolutePath.equals(canonicalPath) == false : String.format( - "Given file must be a link [absolute=%s,canonical=%s].", absolutePath, - canonicalPath); - return new Link(file.getName(), createNode(new java.io.File(canonicalPath))); + final String canonicalPath = + FileOperations.getMonitoredInstanceForCurrentThread().getCanonicalPath(file); + if (absolutePath.equals(canonicalPath)) + { + throw new IllegalArgumentException(String.format( + "Given file must be a link [path=%s].", absolutePath)); + } + return new Link(file.getName(), internalCreateNode(new java.io.File(canonicalPath))); } /** @@ -108,8 +85,13 @@ public final class NodeFactory */ public final static IFile createFileNode(final java.io.File file) { - assert file != null && file.isFile() : "Given file must be a file"; - return new File(file); + assert file != null : "Given file must not be null"; + if (FileOperations.getMonitoredInstanceForCurrentThread().isFile(file) == false) + { + throw new IllegalArgumentException("File '" + file.getAbsolutePath() + + "' is not a file."); + } + return internalCreateFileNode(file); } /** @@ -117,7 +99,31 @@ public final class NodeFactory */ public final static IDirectory createDirectoryNode(final java.io.File file) { - assert file != null && file.isDirectory() : "Given file must be a directory"; + assert file != null : "Given file must not be null"; + if (FileOperations.getMonitoredInstanceForCurrentThread().isDirectory(file) == false) + { + throw new IllegalArgumentException("File '" + file.getAbsolutePath() + + "' is not a directory."); + } + return internalCreateDirectoryNode(file); + } + + static IFileBasedNode internalCreateNode(final java.io.File file) + { + if (FileOperations.getMonitoredInstanceForCurrentThread().isDirectory(file)) + { + return internalCreateDirectoryNode(file); + } + return internalCreateFileNode(file); + } + + static IFileBasedFile internalCreateFileNode(final java.io.File file) + { + return new File(file); + } + + static IFileBasedDirectory internalCreateDirectoryNode(final java.io.File file) + { return new Directory(file); } diff --git a/bds/sourceTest/java/ch/systemsx/cisd/bds/DataStructureTestV1_0.java b/bds/sourceTest/java/ch/systemsx/cisd/bds/DataStructureTestV1_0.java index fe4105b41202a637abb8c4b4e232d5f062b4480e..df8689fd8fd23588bd0d227ea779ac34cb217ee1 100644 --- a/bds/sourceTest/java/ch/systemsx/cisd/bds/DataStructureTestV1_0.java +++ b/bds/sourceTest/java/ch/systemsx/cisd/bds/DataStructureTestV1_0.java @@ -74,7 +74,7 @@ public final class DataStructureTestV1_0 extends AbstractFileSystemTestCase dataStructure.create(); final IDirectory dataFolder = dataStructure.getOriginalData(); assertEquals(DataStructureV1_0.DIR_ORIGINAL, dataFolder.getName()); - assertEquals(DataStructureV1_0.DIR_DATA, dataFolder.tryToGetParent().getName()); + assertEquals(DataStructureV1_0.DIR_DATA, dataFolder.tryGetParent().getName()); } @Test @@ -110,7 +110,8 @@ public final class DataStructureTestV1_0 extends AbstractFileSystemTestCase dataStructure.setExperimentIdentifier(id); final IDirectory root = storage.getRoot(); final IDirectory metaData = Utilities.getSubDirectory(root, DataStructureV1_0.DIR_METADATA); - final IDirectory idDir = Utilities.getSubDirectory(metaData, ExperimentIdentifier.EXPERIMENT_IDENTIFIER); + final IDirectory idDir = + Utilities.getSubDirectory(metaData, ExperimentIdentifier.EXPERIMENT_IDENTIFIER); assertEquals("i\n", Utilities.getString(idDir, ExperimentIdentifier.INSTANCE_CODE)); assertEquals("g\n", Utilities.getString(idDir, ExperimentIdentifier.GROUP_CODE)); assertEquals("p\n", Utilities.getString(idDir, ExperimentIdentifier.PROJECT_CODE)); @@ -126,7 +127,8 @@ public final class DataStructureTestV1_0 extends AbstractFileSystemTestCase dataStructure.setExperimentIdentifier(id); final IDirectory root = storage.getRoot(); final IDirectory metaData = Utilities.getSubDirectory(root, DataStructureV1_0.DIR_METADATA); - final IDirectory idDir = Utilities.getSubDirectory(metaData, ExperimentIdentifier.EXPERIMENT_IDENTIFIER); + final IDirectory idDir = + Utilities.getSubDirectory(metaData, ExperimentIdentifier.EXPERIMENT_IDENTIFIER); assertEquals("i\n", Utilities.getString(idDir, ExperimentIdentifier.INSTANCE_CODE)); assertEquals("g\n", Utilities.getString(idDir, ExperimentIdentifier.GROUP_CODE)); assertEquals("p\n", Utilities.getString(idDir, ExperimentIdentifier.PROJECT_CODE)); @@ -205,7 +207,12 @@ public final class DataStructureTestV1_0 extends AbstractFileSystemTestCase } } - @Test + // + // Note: validation has currently been switched off. We want to make the feature confgurable, + // though. At that point, these tests are supposed to work again. + // + + @Test(groups = "broken") public void testCloseIfNoFormat() { dataStructure.create(); @@ -220,7 +227,7 @@ public final class DataStructureTestV1_0 extends AbstractFileSystemTestCase } } - @Test + @Test(groups = "broken") public void testCloseIfNoExperimentID() { dataStructure.create(); @@ -236,7 +243,7 @@ public final class DataStructureTestV1_0 extends AbstractFileSystemTestCase } } - @Test + @Test(groups = "broken") public void testCloseIfNoExperimentRegistrator() { dataStructure.create(); @@ -255,7 +262,7 @@ public final class DataStructureTestV1_0 extends AbstractFileSystemTestCase } } - @Test + @Test(groups = "broken") public void testCloseIfNoExperimentRegistrationDate() { dataStructure.create(); @@ -273,7 +280,7 @@ public final class DataStructureTestV1_0 extends AbstractFileSystemTestCase } } - @Test + @Test(groups = "broken") public void testCloseIfNoMeasurementEntity() { dataStructure.create(); @@ -299,7 +306,8 @@ public final class DataStructureTestV1_0 extends AbstractFileSystemTestCase dataStructure.create(); dataStructure.getOriginalData().addKeyValuePair("answer", "42"); dataStructure.setFormat(UnknownFormatV1_0.UNKNOWN_1_0); - final ExperimentIdentifier experimentIdentifier = new ExperimentIdentifier("i", "g", "p", "e"); + final ExperimentIdentifier experimentIdentifier = + new ExperimentIdentifier("i", "g", "p", "e"); dataStructure.setExperimentIdentifier(experimentIdentifier); final ExperimentRegistrationTimestamp experimentRegistratorDate = new ExperimentRegistrationTimestamp(new Date(4711L * 4711000L)); diff --git a/bds/sourceTest/java/ch/systemsx/cisd/bds/hcs/HCSImageFormattedDataTest.java b/bds/sourceTest/java/ch/systemsx/cisd/bds/hcs/HCSImageFormattedDataTest.java index 964bc702eec4de33aa16542f7a1e047deb7f3cd2..b417a0e2a4af76fe8c09a75020b028fd472ab8ba 100644 --- a/bds/sourceTest/java/ch/systemsx/cisd/bds/hcs/HCSImageFormattedDataTest.java +++ b/bds/sourceTest/java/ch/systemsx/cisd/bds/hcs/HCSImageFormattedDataTest.java @@ -53,6 +53,10 @@ import ch.systemsx.cisd.common.utilities.AbstractFileSystemTestCase; public class HCSImageFormattedDataTest extends AbstractFileSystemTestCase { + private static final int NUMBER_OF_CHANNELS = 1; + + private static final Geometry GEOMETRY = new Geometry(2, 2); + private static final String IMAGE_ROOT_DIRECTORY_NAME = "CP001-1"; private static final String ORIGINAL_TIFF = "original.tiff"; @@ -78,6 +82,17 @@ public class HCSImageFormattedDataTest extends AbstractFileSystemTestCase private File imageRootDirectory; private final void prepareAndCreateFormattedData() + { + prepareAndCreateFormattedData(standardNode, originalNode); + } + + private final void prepareAndCreateFormattedDataWithoutOriginal() + { + prepareAndCreateFormattedData(standardNode, null); + } + + private final void prepareAndCreateFormattedData(final IDirectory standardDirNode, + final IDirectory originalNodeOrNull) { directory = context.mock(IDirectory.class); formatParameters = context.mock(IFormatParameters.class); @@ -90,6 +105,8 @@ public class HCSImageFormattedDataTest extends AbstractFileSystemTestCase one(formatParameters).containsParameter(formatParameterName); will(returnValue(true)); } + addParameterCheckExpectations(this, GEOMETRY, GEOMETRY, NUMBER_OF_CHANNELS); + prepareGetDataDirectories(this, standardDirNode, originalNodeOrNull); } }); formattedData = @@ -97,7 +114,24 @@ public class HCSImageFormattedDataTest extends AbstractFileSystemTestCase null, formatParameters); } - private final void prepareStandardNode() + private void prepareGetDataDirectories(Expectations exp, IDirectory standardDirNode, + IDirectory originalNodeOrNull) + { + exp.one(directory).tryGetNode(DataStructureV1_0.DIR_STANDARD); + exp.will(Expectations.returnValue(standardDirNode)); + + exp.one(formatParameters).getValue(HCSImageFormatV1_0.CONTAINS_ORIGINAL_DATA); + boolean containsOriginalData = originalNodeOrNull != null; + exp.will(Expectations.returnValue(Utilities.Boolean.fromBoolean(containsOriginalData))); + + if (containsOriginalData) + { + exp.one(directory).tryGetNode(DataStructureV1_0.DIR_ORIGINAL); + exp.will(Expectations.returnValue(originalNodeOrNull)); + } + } + + private final void createStandardNode() { final File standardDirectory = new File(workingDirectory, DataStructureV1_0.DIR_STANDARD); standardDirectory.mkdir(); @@ -107,25 +141,25 @@ public class HCSImageFormattedDataTest extends AbstractFileSystemTestCase standardLeafDirectory = row1.makeDirectory(HCSImageFormattedData.COLUMN + "2"); } - private final void prepareOriginalNode() + private final void createOriginalNode() { final File originalDirectory = new File(workingDirectory, DataStructureV1_0.DIR_ORIGINAL); originalDirectory.mkdir(); originalNode = NodeFactory.createDirectoryNode(originalDirectory); } - private final void addParameterCheckExpectations(final Expectations exp) + private final void addParameterCheckExpectations(final Expectations exp, + Geometry plateGeometry, Geometry wellGeometry, int numberOfChannels) { - final Geometry geometry = new Geometry(2, 2); exp.one(formatParameters).getValue(HCSImageFormatV1_0.NUMBER_OF_CHANNELS); - exp.will(Expectations.returnValue(new Integer(1))); + exp.will(Expectations.returnValue(new Integer(numberOfChannels))); exp.one(formatParameters).getValue(PlateGeometry.PLATE_GEOMETRY); - exp.will(Expectations.returnValue(geometry)); + exp.will(Expectations.returnValue(plateGeometry)); exp.one(formatParameters).getValue(WellGeometry.WELL_GEOMETRY); - exp.will(Expectations.returnValue(geometry)); + exp.will(Expectations.returnValue(wellGeometry)); } - private final void prepareImageRootDirectory() throws IOException + private final void createImageRootDirectory() throws IOException { imageRootDirectory = new File(workingDirectory, IMAGE_ROOT_DIRECTORY_NAME); imageRootDirectory.mkdir(); @@ -143,9 +177,8 @@ public class HCSImageFormattedDataTest extends AbstractFileSystemTestCase { super.setUp(); context = new Mockery(); - prepareAndCreateFormattedData(); - prepareStandardNode(); - prepareOriginalNode(); + createStandardNode(); + createOriginalNode(); } @AfterMethod @@ -159,6 +192,7 @@ public class HCSImageFormattedDataTest extends AbstractFileSystemTestCase @Test public final void testCreateWellFileName() { + prepareAndCreateFormattedDataWithoutOriginal(); boolean fail = true; try { @@ -177,6 +211,7 @@ public class HCSImageFormattedDataTest extends AbstractFileSystemTestCase @Test public final void testGetFormat() { + prepareAndCreateFormattedDataWithoutOriginal(); assertEquals(HCSImageFormatV1_0.HCS_IMAGE_1_0, formattedData.getFormat()); context.assertIsSatisfied(); } @@ -184,23 +219,10 @@ public class HCSImageFormattedDataTest extends AbstractFileSystemTestCase @Test public final void testAddStandardNodeWithOriginalData() throws IOException { - prepareImageRootDirectory(); - final int channelIndex = 1; - context.checking(new Expectations() - { - { - addParameterCheckExpectations(this); - - exactly(2).of(directory).tryGetNode(DataStructureV1_0.DIR_STANDARD); - will(returnValue(standardNode)); - - one(directory).tryGetNode(DataStructureV1_0.DIR_ORIGINAL); - will(returnValue(originalNode)); + createImageRootDirectory(); + prepareAndCreateFormattedData(); - one(formatParameters).getValue(HCSImageFormatV1_0.CONTAINS_ORIGINAL_DATA); - will(returnValue(Utilities.Boolean.TRUE)); - } - }); + final int channelIndex = 1; final NodePath nodePath = formattedData.addStandardNode(imageRootDirectory, ORIGINAL_TIFF, channelIndex, PLATE_LOCATION, WELL_LOCATION); @@ -222,20 +244,10 @@ public class HCSImageFormattedDataTest extends AbstractFileSystemTestCase @Test public final void testAddStandardNodeWithoutOriginalData() throws IOException { - prepareImageRootDirectory(); - final int channelIndex = 1; - context.checking(new Expectations() - { - { - addParameterCheckExpectations(this); + createImageRootDirectory(); + prepareAndCreateFormattedDataWithoutOriginal(); - exactly(2).of(directory).tryGetNode(DataStructureV1_0.DIR_STANDARD); - will(returnValue(standardNode)); - - one(formatParameters).getValue(HCSImageFormatV1_0.CONTAINS_ORIGINAL_DATA); - will(returnValue(Utilities.Boolean.FALSE)); - } - }); + final int channelIndex = 1; final NodePath nodePath = formattedData.addStandardNode(imageRootDirectory, ORIGINAL_TIFF, channelIndex, PLATE_LOCATION, WELL_LOCATION); @@ -257,16 +269,9 @@ public class HCSImageFormattedDataTest extends AbstractFileSystemTestCase @Test public final void testTryGetStandardNodeAtWithNoFile() { - final int channelIndex = 1; - context.checking(new Expectations() - { - { - addParameterCheckExpectations(this); + prepareAndCreateFormattedDataWithoutOriginal(); - one(directory).tryGetNode(DataStructureV1_0.DIR_STANDARD); - will(returnValue(standardNode)); - } - }); + final int channelIndex = 1; final INode node = formattedData.tryGetStandardNodeAt(channelIndex, PLATE_LOCATION, WELL_LOCATION); assertNull(node); @@ -276,19 +281,12 @@ public class HCSImageFormattedDataTest extends AbstractFileSystemTestCase @Test public final void testTryGetStandardNodeAtWithFile() throws IOException { + prepareAndCreateFormattedDataWithoutOriginal(); + final File file = new File(workingDirectory, "row2_column1.tiff"); FileUtils.writeStringToFile(file, "This is my original file..."); standardLeafDirectory.addFile(file, null, true); final int channelIndex = 1; - context.checking(new Expectations() - { - { - addParameterCheckExpectations(this); - - one(directory).tryGetNode(DataStructureV1_0.DIR_STANDARD); - will(returnValue(standardNode)); - } - }); final INode node = formattedData.tryGetStandardNodeAt(channelIndex, PLATE_LOCATION, WELL_LOCATION); assertNotNull(node); @@ -298,13 +296,7 @@ public class HCSImageFormattedDataTest extends AbstractFileSystemTestCase @Test public final void testTryGetStandardNodeAtWithWrongChannelIndex() { - context.checking(new Expectations() - { - { - one(formatParameters).getValue(HCSImageFormatV1_0.NUMBER_OF_CHANNELS); - will(returnValue(new Integer(1))); - } - }); + prepareAndCreateFormattedDataWithoutOriginal(); try { formattedData.tryGetStandardNodeAt(2, null, null); @@ -319,16 +311,7 @@ public class HCSImageFormattedDataTest extends AbstractFileSystemTestCase @Test public final void testTryGetStandardNodeAtWithWrongPlateLocation() { - context.checking(new Expectations() - { - { - one(formatParameters).getValue(HCSImageFormatV1_0.NUMBER_OF_CHANNELS); - will(returnValue(new Integer(1))); - - one(formatParameters).getValue(PlateGeometry.PLATE_GEOMETRY); - will(returnValue(new Geometry(2, 2))); - } - }); + prepareAndCreateFormattedDataWithoutOriginal(); try { final Location location = new Location(2, 3); @@ -344,12 +327,7 @@ public class HCSImageFormattedDataTest extends AbstractFileSystemTestCase @Test public final void testTryGetStandardNodeAtWithWrongWellLocation() { - context.checking(new Expectations() - { - { - addParameterCheckExpectations(this); - } - }); + prepareAndCreateFormattedDataWithoutOriginal(); try { formattedData.tryGetStandardNodeAt(1, new Location(2, 2), new Location(3, 2)); diff --git a/bds/sourceTest/java/ch/systemsx/cisd/bds/storage/filesystem/DirectoryTest.java b/bds/sourceTest/java/ch/systemsx/cisd/bds/storage/filesystem/DirectoryTest.java index d3d85b5c9105354ee037f5dbc2be7dd75c1d3301..4334e97f6c3196a9c66df4fed7c711db0b28502a 100644 --- a/bds/sourceTest/java/ch/systemsx/cisd/bds/storage/filesystem/DirectoryTest.java +++ b/bds/sourceTest/java/ch/systemsx/cisd/bds/storage/filesystem/DirectoryTest.java @@ -52,7 +52,7 @@ public final class DirectoryTest extends AbstractFileSystemTestCase FileUtilities.writeToFile(new File(subDir, "p2"), "property 2"); File dest = new File(workingDirectory, "destination"); dest.mkdir(); - Directory directory = new Directory(dest); + final IDirectory directory = NodeFactory.createDirectoryNode(dest); INode copiedDir = directory.addFile(dir, null, move); assertEquals("dir", copiedDir.getName()); assertTrue(copiedDir instanceof IDirectory); @@ -81,14 +81,14 @@ public final class DirectoryTest extends AbstractFileSystemTestCase @Test public void testGetName() { - Directory directory = new Directory(workingDirectory); + final IDirectory directory = NodeFactory.createDirectoryNode(workingDirectory); assertEquals(workingDirectory.getName(), directory.getName()); } @Test public void testMakeDirectory() { - Directory directory = new Directory(workingDirectory); + final IDirectory directory = NodeFactory.createDirectoryNode(workingDirectory); IDirectory subdirectory = directory.makeDirectory("sub-directory"); assertEquals("sub-directory", subdirectory.getName()); @@ -100,7 +100,7 @@ public final class DirectoryTest extends AbstractFileSystemTestCase @Test public void testMakeDirectoryTwice() { - Directory directory = new Directory(workingDirectory); + final IDirectory directory = NodeFactory.createDirectoryNode(workingDirectory); directory.makeDirectory("sub-directory"); IDirectory subdirectory = directory.makeDirectory("sub-directory"); @@ -113,7 +113,7 @@ public final class DirectoryTest extends AbstractFileSystemTestCase @Test public void testMakeDirectoryButThereIsAlreadyAFileWithSameName() { - Directory directory = new Directory(workingDirectory); + final IDirectory directory = NodeFactory.createDirectoryNode(workingDirectory); directory.addKeyValuePair("sub-directory", "value"); try { @@ -128,7 +128,8 @@ public final class DirectoryTest extends AbstractFileSystemTestCase @Test public void testAddKeyValuePair() { - IFile stringFile = new Directory(workingDirectory).addKeyValuePair("answer", "42"); + IFile stringFile = + NodeFactory.createDirectoryNode(workingDirectory).addKeyValuePair("answer", "42"); assertEquals("42\n", FileUtilities.loadToString(new File(workingDirectory, "answer"))); assertEquals("42\n", stringFile.getStringContent()); } @@ -138,7 +139,7 @@ public final class DirectoryTest extends AbstractFileSystemTestCase { File dir = new File(workingDirectory, "dir"); dir.mkdirs(); - Directory directory = new Directory(dir); + final IDirectory directory = NodeFactory.createDirectoryNode(dir); directory.addKeyValuePair("p1", "property 1"); IDirectory subdir = directory.makeDirectory("subdir"); subdir.addKeyValuePair("p2", "property 2"); @@ -161,7 +162,7 @@ public final class DirectoryTest extends AbstractFileSystemTestCase { File dir = new File(workingDirectory, "dir"); dir.mkdirs(); - IDirectory directory = new Directory(dir); + final IDirectory directory = NodeFactory.createDirectoryNode(dir); directory.addKeyValuePair("p1", "property 1"); IDirectory subdir = directory.makeDirectory("subdir"); subdir.addKeyValuePair("p2", "property 2"); diff --git a/bds/sourceTest/java/ch/systemsx/cisd/bds/storage/filesystem/FileTest.java b/bds/sourceTest/java/ch/systemsx/cisd/bds/storage/filesystem/FileTest.java index c948f34ab3b7609524d38593d8b4fd3bcc32b77e..58795b728594abe6bbebc38811f000c50e5f62fa 100644 --- a/bds/sourceTest/java/ch/systemsx/cisd/bds/storage/filesystem/FileTest.java +++ b/bds/sourceTest/java/ch/systemsx/cisd/bds/storage/filesystem/FileTest.java @@ -40,9 +40,9 @@ public final class FileTest extends AbstractFileSystemTestCase @Test public void testGetValueAndGetName() { - java.io.File file = new java.io.File(workingDirectory, "test.txt"); + final java.io.File file = new java.io.File(workingDirectory, "test.txt"); FileUtilities.writeToFile(file, "Hello\nworld!\n"); - File stringFile = new File(file); + final IFile stringFile = NodeFactory.createFileNode(file); assertEquals("test.txt", stringFile.getName()); assertEquals("Hello\nworld!\n", stringFile.getStringContent()); @@ -52,9 +52,9 @@ public final class FileTest extends AbstractFileSystemTestCase @Test public void testExtractTo() { - java.io.File file = new java.io.File(workingDirectory, "test.txt"); + final java.io.File file = new java.io.File(workingDirectory, "test.txt"); FileUtilities.writeToFile(file, "Hello\nworld!\n"); - File stringFile = new File(file); + final IFile stringFile = NodeFactory.createFileNode(file); java.io.File subdir = new java.io.File(workingDirectory, "subdir"); subdir.mkdir(); @@ -66,9 +66,9 @@ public final class FileTest extends AbstractFileSystemTestCase @Test public void testMoveTo() { - java.io.File dir = new java.io.File(workingDirectory, "dir"); + final java.io.File dir = new java.io.File(workingDirectory, "dir"); dir.mkdirs(); - IDirectory directory = new Directory(dir); + final IDirectory directory = NodeFactory.createDirectoryNode(dir); IFile file = directory.addKeyValuePair("p1", "property 1"); file.moveTo(workingDirectory); @@ -81,7 +81,7 @@ public final class FileTest extends AbstractFileSystemTestCase @Test public void testGetInputStream() throws Exception { - java.io.File file = new java.io.File(workingDirectory, "test"); + final java.io.File file = new java.io.File(workingDirectory, "test"); FileOutputStream fileOutputStream = null; try { diff --git a/bds/sourceTest/java/ch/systemsx/cisd/bds/storage/filesystem/NodeFactoryTest.java b/bds/sourceTest/java/ch/systemsx/cisd/bds/storage/filesystem/NodeFactoryTest.java index e5bed9cffe95ab91d900b4c03108264cb2e462e8..ec0bfff55179a20e0e6567bc50026d95713cfc03 100644 --- a/bds/sourceTest/java/ch/systemsx/cisd/bds/storage/filesystem/NodeFactoryTest.java +++ b/bds/sourceTest/java/ch/systemsx/cisd/bds/storage/filesystem/NodeFactoryTest.java @@ -19,11 +19,14 @@ package ch.systemsx.cisd.bds.storage.filesystem; import static org.testng.AssertJUnit.assertEquals; import static org.testng.AssertJUnit.assertTrue; +import org.testng.annotations.AfterTest; +import org.testng.annotations.BeforeTest; import org.testng.annotations.Test; 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.common.TimingParameters; import ch.systemsx.cisd.common.utilities.AbstractFileSystemTestCase; import ch.systemsx.cisd.common.utilities.FileUtilities; @@ -34,6 +37,18 @@ import ch.systemsx.cisd.common.utilities.FileUtilities; */ public class NodeFactoryTest extends AbstractFileSystemTestCase { + @BeforeTest + public void beforeTest() + { + TimingParameters.setDefault(TimingParameters.createNoRetries(500L)); + } + + @AfterTest + public void afterTest() + { + TimingParameters.setDefault(TimingParameters.getStandardParameters()); + } + @Test public void testCreateFileNode() { diff --git a/common/source/java/ch/systemsx/cisd/common/filesystem/FileOperations.java b/common/source/java/ch/systemsx/cisd/common/filesystem/FileOperations.java index 4a1b31da285d0c2f32316683adc28fc82eacb6a1..16341d67ab229cca3ee0446a1949943a5de4854e 100644 --- a/common/source/java/ch/systemsx/cisd/common/filesystem/FileOperations.java +++ b/common/source/java/ch/systemsx/cisd/common/filesystem/FileOperations.java @@ -453,6 +453,11 @@ public class FileOperations implements IFileOperations return FileUtilities.loadToString(file); } + public String getExactContentAsString(File file) throws WrappedIOException + { + return FileUtilities.loadExactToString(file); + } + public List<String> getContentAsStringList(File file) throws WrappedIOException { return FileUtilities.loadToStringList(file); diff --git a/common/source/java/ch/systemsx/cisd/common/filesystem/IFileOperations.java b/common/source/java/ch/systemsx/cisd/common/filesystem/IFileOperations.java index 717e6cca23e2fa0f33fc3b8a67c1bdfde759b301..7a8695fc0672c9a407609f17b3b34f25736d944a 100644 --- a/common/source/java/ch/systemsx/cisd/common/filesystem/IFileOperations.java +++ b/common/source/java/ch/systemsx/cisd/common/filesystem/IFileOperations.java @@ -348,6 +348,13 @@ public interface IFileOperations extends IFileRemover */ public String getContentAsString(File file) throws WrappedIOException; + /** + * Returns the content of <var>file</var> as a String. Doesn't append new line at the end. + * + * @throws WrappedIOException if an IO error occurs during reading the file + */ + public String getExactContentAsString(File file) throws WrappedIOException; + /** * Returns the content of <var>file</var> as a list of Strings. *