diff --git a/source/java/org/alfresco/repo/bulkimport/AnalysedDirectory.java b/source/java/org/alfresco/repo/bulkimport/AnalysedDirectory.java index a0b190e38e..ea6145cba1 100644 --- a/source/java/org/alfresco/repo/bulkimport/AnalysedDirectory.java +++ b/source/java/org/alfresco/repo/bulkimport/AnalysedDirectory.java @@ -1,4 +1,4 @@ -/* +/* * #%L * Alfresco Repository * %% @@ -15,20 +15,18 @@ * (at your option) any later version. * * Alfresco is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with Alfresco. If not, see . - * #L% - */ + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ package org.alfresco.repo.bulkimport; -import java.io.File; -import java.util.ArrayList; -import java.util.Arrays; +import java.nio.file.Path; import java.util.Collection; import java.util.Collections; import java.util.HashMap; @@ -42,23 +40,23 @@ import java.util.Map; */ public class AnalysedDirectory { - private List originalListing = null; - private Map importableItems = null; - private Map importableDirectories = null; + private List originalPaths = null; + private Map importableItems = null; + private Map importableDirectories = null; - public AnalysedDirectory(File[] files) + public AnalysedDirectory(List paths) { - originalListing = Arrays.asList(files); + originalPaths = paths; // Sort the files/directories so that the *.metadata.properties.xml found later, see ALF-17965 for details. - Collections.sort(originalListing); - importableItems = new HashMap(); - importableDirectories = new HashMap(); + Collections.sort(originalPaths); + importableItems = new HashMap(); + importableDirectories = new HashMap(); } - public List getOriginalListing() - { - return originalListing; - } + public List getOriginalPaths() + { + return originalPaths; + } public Collection getImportableItems() { @@ -83,7 +81,7 @@ public class AnalysedDirectory } } - public ImportableItem findImportableItem(File contentFile) + public ImportableItem findImportableItem(Path contentFile) { ImportableItem result = null; result = importableItems.get(contentFile); diff --git a/source/java/org/alfresco/repo/bulkimport/DirectoryAnalyser.java b/source/java/org/alfresco/repo/bulkimport/DirectoryAnalyser.java index b4f251ab59..d44b5afc62 100644 --- a/source/java/org/alfresco/repo/bulkimport/DirectoryAnalyser.java +++ b/source/java/org/alfresco/repo/bulkimport/DirectoryAnalyser.java @@ -1,4 +1,4 @@ -/* +/* * #%L * Alfresco Repository * %% @@ -15,18 +15,19 @@ * (at your option) any later version. * * Alfresco is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with Alfresco. If not, see . - * #L% - */ + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ package org.alfresco.repo.bulkimport; -import java.io.FileFilter; +import java.nio.file.DirectoryStream; +import java.nio.file.Path; /** @@ -52,6 +53,6 @@ public interface DirectoryAnalyser * @param directory The directory to analyse (note: must be a directory) (must not be null). * @return An AnalysedDirectory object (will not be null). */ - public AnalysedDirectory analyseDirectory(ImportableItem directory, FileFilter filter); + public AnalysedDirectory analyseDirectory(ImportableItem directory, DirectoryStream.Filter filter); } diff --git a/source/java/org/alfresco/repo/bulkimport/ImportableItem.java b/source/java/org/alfresco/repo/bulkimport/ImportableItem.java index a019d5941d..6523966243 100644 --- a/source/java/org/alfresco/repo/bulkimport/ImportableItem.java +++ b/source/java/org/alfresco/repo/bulkimport/ImportableItem.java @@ -1,4 +1,4 @@ -/* +/* * #%L * Alfresco Repository * %% @@ -15,17 +15,21 @@ * (at your option) any later version. * * Alfresco is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with Alfresco. If not, see . - * #L% - */ + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ package org.alfresco.repo.bulkimport; -import java.io.File; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.LinkOption; +import java.nio.file.Path; +import java.nio.file.attribute.BasicFileAttributes; import java.util.Collections; import java.util.Date; import java.util.Set; @@ -68,45 +72,45 @@ public final class ImportableItem } public void setNodeRef(NodeRef nodeRef) - { - this.nodeRef = nodeRef; - } + { + this.nodeRef = nodeRef; + } public NodeRef getNodeRef() - { - return nodeRef; - } - + { + return nodeRef; + } + public void clearParent() { - numChildren--; - if(numChildren <= 0) - { - numChildren = 0; - parent = null; - } + numChildren--; + if (numChildren <= 0) + { + numChildren = 0; + parent = null; + } } public void setParent(ImportableItem parent) - { - if(parent == null) - { - throw new IllegalArgumentException("Parent cannot be null"); - } - this.parent = parent; - } + { + if (parent == null) + { + throw new IllegalArgumentException("Parent cannot be null"); + } + this.parent = parent; + } public ImportableItem getParent() - { - return parent; - } + { + return parent; + } - /** + /** * @return True if this ImportableItem has version entries. */ public boolean hasVersionEntries() { - return(versionEntries != null && versionEntries.size() > 0); + return (versionEntries != null && versionEntries.size() > 0); } public Set getVersionEntries() @@ -138,49 +142,57 @@ public final class ImportableItem public class ContentAndMetadata { - private File contentFile = null; + private Path contentFile = null; private boolean contentFileExists = false; private boolean contentFileIsReadable = false; private FileType contentFileType = null; private long contentFileSize = -1; private Date contentFileCreated = null; private Date contentFileModified = null; - private File metadataFile = null; + private Path metadataFile = null; private long metadataFileSize = -1; - public final File getContentFile() + public final Path getContentFile() { - return(contentFile); + return contentFile; } - public final void setContentFile(final File contentFile) + public final void setContentFile(final Path contentFile) { this.contentFile = contentFile; if (contentFile != null) { // stat the file, to find out a few key details - contentFileExists = contentFile.exists(); + contentFileExists = Files.exists(contentFile, LinkOption.NOFOLLOW_LINKS); if (contentFileExists) { - contentFileIsReadable = contentFile.canRead(); - contentFileSize = contentFile.length(); - contentFileModified = new Date(contentFile.lastModified()); - contentFileCreated = contentFileModified; //TODO: determine proper file creation time (awaiting JDK 1.7 NIO2 library) - - if (contentFile.isFile()) + try { - contentFileType = FileType.FILE; + BasicFileAttributes attrs = Files.readAttributes(contentFile, BasicFileAttributes.class); + + contentFileIsReadable = Files.isReadable(contentFile); + contentFileSize = attrs.size(); + contentFileModified = new Date(attrs.lastModifiedTime().toMillis()); + contentFileCreated = new Date(attrs.creationTime().toMillis()); + + if (Files.isRegularFile(contentFile, LinkOption.NOFOLLOW_LINKS)) + { + contentFileType = FileType.FILE; + } + else if (Files.isDirectory(contentFile, LinkOption.NOFOLLOW_LINKS)) + { + contentFileType = FileType.DIRECTORY; + } + else + { + contentFileType = FileType.OTHER; + } } - else if (contentFile.isDirectory()) + catch (IOException e) { - contentFileType = FileType.DIRECTORY; - } - else - { - contentFileType = FileType.OTHER; } } } @@ -241,17 +253,23 @@ public final class ImportableItem return(metadataFile != null); } - public final File getMetadataFile() + public final Path getMetadataFile() { - return(metadataFile); + return metadataFile; } - public final void setMetadataFile(final File metadataFile) + public final void setMetadataFile(final Path metadataFile) { - if (metadataFile != null && metadataFile.exists()) + if (metadataFile != null && Files.exists(metadataFile)) { - this.metadataFile = metadataFile; - this.metadataFileSize = metadataFile.length(); + this.metadataFile = metadataFile; + try + { + this.metadataFileSize = Files.size(metadataFile); + } + catch (IOException e) + { + } } } diff --git a/source/java/org/alfresco/repo/bulkimport/impl/AbstractFilesystemTracker.java b/source/java/org/alfresco/repo/bulkimport/impl/AbstractFilesystemTracker.java index e766a02f5f..02b4ae5e03 100644 --- a/source/java/org/alfresco/repo/bulkimport/impl/AbstractFilesystemTracker.java +++ b/source/java/org/alfresco/repo/bulkimport/impl/AbstractFilesystemTracker.java @@ -1,4 +1,4 @@ -/* +/* * #%L * Alfresco Repository * %% @@ -15,18 +15,20 @@ * (at your option) any later version. * * Alfresco is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with Alfresco. If not, see . - * #L% - */ + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ package org.alfresco.repo.bulkimport.impl; -import java.io.File; -import java.io.FileFilter; +import java.io.IOException; +import java.nio.file.DirectoryStream; +import java.nio.file.Files; +import java.nio.file.Path; import org.alfresco.repo.bulkimport.AnalysedDirectory; import org.alfresco.repo.bulkimport.DirectoryAnalyser; @@ -64,31 +66,31 @@ public abstract class AbstractFilesystemTracker implements FilesystemTracker protected final AnalysedDirectory getImportableDirectoriesInDirectory(ImportableItem directory, final int count) { - FileFilter filter = null; + DirectoryStream.Filter filter = null; - if(count != -1) + if (count != -1) { - filter = new FileFilter() - { - private int i = count; - - @Override - public boolean accept(File file) - { - return file.isDirectory() && i-- > 0; - } - }; + filter = new DirectoryStream.Filter() + { + private int i = count; + + @Override + public boolean accept(Path entry) throws IOException + { + return Files.isDirectory(entry) && i-- > 0; + } + }; } else { - filter = new FileFilter() - { - @Override - public boolean accept(File file) - { - return file.isDirectory(); - } - }; + filter = new DirectoryStream.Filter() + { + @Override + public boolean accept(Path entry) throws IOException + { + return Files.isDirectory(entry); + } + }; } AnalysedDirectory analysedDirectory = directoryAnalyser.analyseDirectory(directory, filter); diff --git a/source/java/org/alfresco/repo/bulkimport/impl/AbstractNodeImporter.java b/source/java/org/alfresco/repo/bulkimport/impl/AbstractNodeImporter.java index 28ca2d9d1b..8ad21457f8 100644 --- a/source/java/org/alfresco/repo/bulkimport/impl/AbstractNodeImporter.java +++ b/source/java/org/alfresco/repo/bulkimport/impl/AbstractNodeImporter.java @@ -1,4 +1,4 @@ -/* +/* * #%L * Alfresco Repository * %% @@ -15,18 +15,18 @@ * (at your option) any later version. * * Alfresco is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with Alfresco. If not, see . - * #L% - */ + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ package org.alfresco.repo.bulkimport.impl; -import java.io.File; import java.io.Serializable; +import java.nio.file.Path; import java.util.Date; import java.util.HashMap; import java.util.Map; @@ -160,11 +160,11 @@ public abstract class AbstractNodeImporter implements NodeImporter importableItem != null && importableItem.getHeadRevision() != null) { - File metadataFile = importableItem.getHeadRevision().getMetadataFile(); + Path metadataFile = importableItem.getHeadRevision().getMetadataFile(); if (metadataFile != null) { - final String metadataFileName = metadataFile.getName(); + final String metadataFileName = metadataFile.getFileName().toString(); result = metadataFileName.substring(0, metadataFileName.length() - (MetadataLoader.METADATA_SUFFIX.length() + metadataLoader.getMetadataFileExtension().length())); @@ -175,7 +175,7 @@ public abstract class AbstractNodeImporter implements NodeImporter if (result == null && importableItem != null) { - result = importableItem.getHeadRevision().getContentFile().getName(); + result = importableItem.getHeadRevision().getContentFile().getFileName().toString(); } return(result); @@ -341,12 +341,12 @@ public abstract class AbstractNodeImporter implements NodeImporter return(result); } - protected String getFileName(File file) + protected String getFileName(Path file) { return FileUtils.getFileName(file); } - protected final void importImportableItemMetadata(NodeRef nodeRef, File parentFile, MetadataLoader.Metadata metadata) + protected final void importImportableItemMetadata(NodeRef nodeRef, Path parentFile, MetadataLoader.Metadata metadata) { // Attach aspects if (metadata.getAspects() != null) @@ -405,9 +405,9 @@ public abstract class AbstractNodeImporter implements NodeImporter // Load "standard" metadata from the filesystem if (contentAndMetadata != null && contentAndMetadata.contentFileExists()) { - final String filename = contentAndMetadata.getContentFile().getName().trim().replaceFirst(DirectoryAnalyser.VERSION_SUFFIX_REGEX, ""); // Strip off the version suffix (if any) - final Date modified = new Date(contentAndMetadata.getContentFile().lastModified()); - final Date created = modified; //TODO: determine proper file creation time (awaiting JDK 1.7 NIO2 library) + final String filename = contentAndMetadata.getContentFile().getFileName().toString().trim().replaceFirst(DirectoryAnalyser.VERSION_SUFFIX_REGEX, ""); // Strip off the version suffix (if any) + final Date modified = contentAndMetadata.getContentFileModifiedDate(); + final Date created = contentAndMetadata.getContentFileCreatedDate(); result.setType(ImportableItem.FileType.FILE.equals(contentAndMetadata.getContentFileType()) ? ContentModel.TYPE_CONTENT : ContentModel.TYPE_FOLDER); result.addProperty(ContentModel.PROP_NAME, filename); diff --git a/source/java/org/alfresco/repo/bulkimport/impl/DirectoryAnalyserImpl.java b/source/java/org/alfresco/repo/bulkimport/impl/DirectoryAnalyserImpl.java index a1136a86da..25f975114d 100644 --- a/source/java/org/alfresco/repo/bulkimport/impl/DirectoryAnalyserImpl.java +++ b/source/java/org/alfresco/repo/bulkimport/impl/DirectoryAnalyserImpl.java @@ -1,4 +1,4 @@ -/* +/* * #%L * Alfresco Repository * %% @@ -15,20 +15,23 @@ * (at your option) any later version. * * Alfresco is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with Alfresco. If not, see . - * #L% - */ + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ package org.alfresco.repo.bulkimport.impl; -import java.io.File; -import java.io.FileFilter; +import java.io.IOException; import java.io.Serializable; +import java.nio.file.DirectoryStream; +import java.nio.file.Files; +import java.nio.file.LinkOption; +import java.nio.file.Path; import java.util.ArrayList; import java.util.Date; import java.util.Iterator; @@ -37,7 +40,6 @@ import java.util.Map; import java.util.regex.Matcher; import java.util.regex.Pattern; -import org.alfresco.error.AlfrescoRuntimeException; import org.alfresco.repo.bulkimport.AnalysedDirectory; import org.alfresco.repo.bulkimport.DirectoryAnalyser; import org.alfresco.repo.bulkimport.ImportFilter; @@ -141,21 +143,12 @@ public class DirectoryAnalyserImpl implements DirectoryAnalyser } /** - * @see org.alfresco.repo.bulkimport.DirectoryAnalyser#analyseDirectory(ImportableItem, FileFilter) + * @see org.alfresco.repo.bulkimport.DirectoryAnalyser#analyseDirectory(org.alfresco.repo.bulkimport.ImportableItem, java.nio.file.DirectoryStream.Filter) */ - public AnalysedDirectory analyseDirectory(ImportableItem directory, FileFilter filter) + public AnalysedDirectory analyseDirectory(ImportableItem directory, DirectoryStream.Filter filter) { - File directoryFile = directory.getHeadRevision().getContentFile(); - AnalysedDirectory result = null; - - if(filter == null) - { - result = new AnalysedDirectory(directoryFile.listFiles()); - } - else - { - result = new AnalysedDirectory(directoryFile.listFiles(filter)); - } + Path directoryFile = directory.getHeadRevision().getContentFile(); + AnalysedDirectory result = new AnalysedDirectory(listFiles(directoryFile, filter)); if (log.isDebugEnabled()) { @@ -163,18 +156,18 @@ public class DirectoryAnalyserImpl implements DirectoryAnalyser } // Build up the list of ImportableItems from the directory listing - for (File file : result.getOriginalListing()) + for (Path file : result.getOriginalPaths()) { // MNT-9763 bulkimport fails when there is a very large LastModified timestamp. String isoDate = null; try { - isoDate = ISO8601DateFormat.format(new Date(file.lastModified())); + isoDate = ISO8601DateFormat.format(new Date(Files.getLastModifiedTime(file, LinkOption.NOFOLLOW_LINKS).toMillis())); ISO8601DateFormat.parse(isoDate); } - catch (PlatformRuntimeException e) + catch (PlatformRuntimeException | IOException e) { - log.warn("Failed to convert date " + isoDate + " to string for " + file.getName(), e); + log.warn("Failed to convert date " + isoDate + " to string for " + file.getFileName(), e); importStatus.incrementNumberOfUnreadableEntries(); continue; } @@ -184,11 +177,11 @@ public class DirectoryAnalyserImpl implements DirectoryAnalyser log.trace("Scanning file " + FileUtils.getFileName(file) + "..."); } - if (file.canRead()) + if (Files.isReadable(file)) { try { - nameChecker.evaluate(file.getName()); + nameChecker.evaluate(file.getFileName().toString()); } catch (ConstraintException e) { @@ -269,6 +262,23 @@ public class DirectoryAnalyserImpl implements DirectoryAnalyser return result; } + + private List listFiles(Path sourceDirectory, DirectoryStream.Filter filter) + { + List files = new ArrayList(); + try (DirectoryStream paths = (filter != null) ? Files.newDirectoryStream(sourceDirectory, filter) : Files.newDirectoryStream(sourceDirectory)) + { + for (Iterator it = paths.iterator(); it.hasNext();) + { + files.add(it.next()); + } + } + catch (IOException e) + { + log.error(e.getMessage()); + } + return files; + } private boolean isMetadataValid(ImportableItem importableItem) { @@ -315,29 +325,30 @@ public class DirectoryAnalyserImpl implements DirectoryAnalyser return true; } - private boolean isVersionFile(File file) + private boolean isVersionFile(Path file) { - Matcher matcher = VERSION_SUFFIX_PATTERN.matcher(file.getName()); + Matcher matcher = VERSION_SUFFIX_PATTERN.matcher(file.getFileName().toString()); return matcher.matches(); } - private boolean isMetadataFile(File file) + private boolean isMetadataFile(Path file) { boolean result = false; if (metadataLoader != null) { - result = file.getName().endsWith(MetadataLoader.METADATA_SUFFIX + metadataLoader.getMetadataFileExtension()); + String name = file.getFileName().toString(); + result = name.endsWith(MetadataLoader.METADATA_SUFFIX + metadataLoader.getMetadataFileExtension()); } return(result); } - private void addVersionFile(ImportableItem parent, AnalysedDirectory analysedDirectory, File versionFile) + private void addVersionFile(ImportableItem parent, AnalysedDirectory analysedDirectory, Path versionFile) { - File parentContentFile = getParentOfVersionFile(versionFile); + Path parentContentFile = getParentOfVersionFile(versionFile); boolean isContentVersion = false; if (isMetadataFile(parentContentFile)) @@ -365,9 +376,9 @@ public class DirectoryAnalyserImpl implements DirectoryAnalyser } - private void addMetadataFile(ImportableItem parent, AnalysedDirectory analysedDirectory, File metadataFile) + private void addMetadataFile(ImportableItem parent, AnalysedDirectory analysedDirectory, Path metadataFile) { - File parentContentfile = getParentOfMetadatafile(metadataFile); + Path parentContentfile = getParentOfMetadatafile(metadataFile); ImportableItem importableItem = findOrCreateImportableItem(parent, analysedDirectory, parentContentfile); @@ -375,7 +386,7 @@ public class DirectoryAnalyserImpl implements DirectoryAnalyser } - private boolean addParentFile(ImportableItem parent, AnalysedDirectory analysedDirectory, File contentFile) + private boolean addParentFile(ImportableItem parent, AnalysedDirectory analysedDirectory, Path contentFile) { ImportableItem importableItem = findOrCreateImportableItem(parent, analysedDirectory, contentFile); @@ -384,7 +395,7 @@ public class DirectoryAnalyserImpl implements DirectoryAnalyser return(importableItem.getHeadRevision().getContentFileType() == FileType.DIRECTORY); } - private ImportableItem findOrCreateImportableItem(ImportableItem parent, AnalysedDirectory analysedDirectory, File contentFile) + private ImportableItem findOrCreateImportableItem(ImportableItem parent, AnalysedDirectory analysedDirectory, Path contentFile) { ImportableItem result = findImportableItem(analysedDirectory, contentFile); @@ -404,7 +415,7 @@ public class DirectoryAnalyserImpl implements DirectoryAnalyser } - private ImportableItem findImportableItem(AnalysedDirectory analysedDirectory, File contentFile) + private ImportableItem findImportableItem(AnalysedDirectory analysedDirectory, Path contentFile) { ImportableItem result = null; @@ -454,7 +465,7 @@ public class DirectoryAnalyserImpl implements DirectoryAnalyser } - private int getVersionNumber(File versionFile) + private int getVersionNumber(Path versionFile) { int result = -1; @@ -463,7 +474,7 @@ public class DirectoryAnalyserImpl implements DirectoryAnalyser throw new IllegalStateException(FileUtils.getFileName(versionFile) + " is not a version file."); } - Matcher matcher = VERSION_SUFFIX_PATTERN.matcher(versionFile.getName()); + Matcher matcher = VERSION_SUFFIX_PATTERN.matcher(versionFile.getFileName().toString()); String versionStr = null; if (matcher.matches()) @@ -481,36 +492,36 @@ public class DirectoryAnalyserImpl implements DirectoryAnalyser } - private File getParentOfVersionFile(File versionFile) + private Path getParentOfVersionFile(Path versionFile) { - File result = null; + Path result = null; if (!isVersionFile(versionFile)) { throw new IllegalStateException(FileUtils.getFileName(versionFile) + " is not a version file."); } - String parentFilename = versionFile.getName().replaceFirst(VERSION_SUFFIX_REGEX, ""); + String parentFilename = versionFile.getFileName().toString().replaceFirst(VERSION_SUFFIX_REGEX, ""); - result = new File(versionFile.getParent(), parentFilename); + result = versionFile.getParent().resolve(parentFilename); return(result); } - private File getParentOfMetadatafile(File metadataFile) + private Path getParentOfMetadatafile(Path metadataFile) { - File result = null; + Path result = null; if (!isMetadataFile(metadataFile)) { throw new IllegalStateException(FileUtils.getFileName(metadataFile) + " is not a metadata file."); } - String name = metadataFile.getName(); + String name = metadataFile.getFileName().toString(); String contentName = name.substring(0, name.length() - (MetadataLoader.METADATA_SUFFIX + metadataLoader.getMetadataFileExtension()).length()); - result = new File(metadataFile.getParent(), contentName); + result = metadataFile.getParent().resolve(contentName); return(result); } diff --git a/source/java/org/alfresco/repo/bulkimport/impl/FileUtils.java b/source/java/org/alfresco/repo/bulkimport/impl/FileUtils.java index da833c92f9..ec6f1b52c4 100644 --- a/source/java/org/alfresco/repo/bulkimport/impl/FileUtils.java +++ b/source/java/org/alfresco/repo/bulkimport/impl/FileUtils.java @@ -1,4 +1,4 @@ -/* +/* * #%L * Alfresco Repository * %% @@ -15,18 +15,20 @@ * (at your option) any later version. * * Alfresco is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with Alfresco. If not, see . - * #L% - */ + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ package org.alfresco.repo.bulkimport.impl; import java.io.File; import java.io.IOException; +import java.nio.file.LinkOption; +import java.nio.file.Path; /** * @@ -54,4 +56,23 @@ public class FileUtils return(result); } + + public static String getFileName(final Path path) + { + String result = null; + + if (path != null) + { + try + { + result = path.toRealPath(LinkOption.NOFOLLOW_LINKS).toString(); + } + catch (final IOException ioe) + { + result = path.toString(); + } + } + + return result; + } } diff --git a/source/java/org/alfresco/repo/bulkimport/impl/StreamingNodeImporterFactory.java b/source/java/org/alfresco/repo/bulkimport/impl/StreamingNodeImporterFactory.java index 0210cf1e64..49ca7173d6 100644 --- a/source/java/org/alfresco/repo/bulkimport/impl/StreamingNodeImporterFactory.java +++ b/source/java/org/alfresco/repo/bulkimport/impl/StreamingNodeImporterFactory.java @@ -1,4 +1,4 @@ -/* +/* * #%L * Alfresco Repository * %% @@ -15,23 +15,26 @@ * (at your option) any later version. * * Alfresco is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with Alfresco. If not, see . - * #L% - */ + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ package org.alfresco.repo.bulkimport.impl; import java.io.File; +import java.io.IOException; +import java.nio.file.Files; import org.alfresco.error.AlfrescoRuntimeException; import org.alfresco.repo.bulkimport.ImportableItem; import org.alfresco.repo.bulkimport.MetadataLoader; import org.alfresco.repo.bulkimport.NodeImporter; import org.alfresco.repo.bulkimport.impl.BulkImportStatusImpl.NodeState; +import org.alfresco.service.cmr.repository.ContentIOException; import org.alfresco.service.cmr.repository.ContentWriter; import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.util.Triple; @@ -85,7 +88,17 @@ public class StreamingNodeImporterFactory extends AbstractNodeImporterFactory } ContentWriter writer = fileFolderService.getWriter(nodeRef); - writer.putContent(contentAndMetadata.getContentFile()); + try + { + writer.putContent(Files.newInputStream(contentAndMetadata.getContentFile())); + } + catch (IOException e) + { + throw new ContentIOException("Failed to copy content from file: \n" + + " writer: " + writer + "\n" + + " file: " + contentAndMetadata.getContentFile(), + e); + } } else { diff --git a/source/java/org/alfresco/repo/bulkimport/impl/StripingFilesystemTracker.java b/source/java/org/alfresco/repo/bulkimport/impl/StripingFilesystemTracker.java index 1fa8e33f40..44f1252128 100644 --- a/source/java/org/alfresco/repo/bulkimport/impl/StripingFilesystemTracker.java +++ b/source/java/org/alfresco/repo/bulkimport/impl/StripingFilesystemTracker.java @@ -1,4 +1,4 @@ -/* +/* * #%L * Alfresco Repository * %% @@ -15,14 +15,14 @@ * (at your option) any later version. * * Alfresco is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with Alfresco. If not, see . - * #L% - */ + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ package org.alfresco.repo.bulkimport.impl; import java.io.File; @@ -62,7 +62,7 @@ public class StripingFilesystemTracker extends AbstractFilesystemTracker // not really an importable item but the interface requires it to be in this form rootFolder = new ImportableItem(); - rootFolder.getHeadRevision().setContentFile(sourceFolder); + rootFolder.getHeadRevision().setContentFile(sourceFolder.toPath()); rootFolder.setNodeRef(target); addDirectoryToProcess(rootFolder, currentLevel); diff --git a/source/java/org/alfresco/repo/bulkimport/importfilters/FileNameRegexImportFilter.java b/source/java/org/alfresco/repo/bulkimport/importfilters/FileNameRegexImportFilter.java index 0e7b58690a..8943d1d6a4 100644 --- a/source/java/org/alfresco/repo/bulkimport/importfilters/FileNameRegexImportFilter.java +++ b/source/java/org/alfresco/repo/bulkimport/importfilters/FileNameRegexImportFilter.java @@ -1,4 +1,4 @@ -/* +/* * #%L * Alfresco Repository * %% @@ -15,14 +15,14 @@ * (at your option) any later version. * * Alfresco is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with Alfresco. If not, see . - * #L% - */ + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ package org.alfresco.repo.bulkimport.importfilters; @@ -58,7 +58,7 @@ public class FileNameRegexImportFilter implements ImportFilter */ public boolean shouldFilter(final ImportableItem importableItem) { - return(pattern.matcher(importableItem.getHeadRevision().getContentFile().getName()).matches()); + return pattern.matcher(importableItem.getHeadRevision().getContentFile().getFileName().toString()).matches(); } } diff --git a/source/java/org/alfresco/repo/bulkimport/importfilters/HiddenFileFilter.java b/source/java/org/alfresco/repo/bulkimport/importfilters/HiddenFileFilter.java index 9d9f68556d..b312cb07bc 100644 --- a/source/java/org/alfresco/repo/bulkimport/importfilters/HiddenFileFilter.java +++ b/source/java/org/alfresco/repo/bulkimport/importfilters/HiddenFileFilter.java @@ -1,4 +1,4 @@ -/* +/* * #%L * Alfresco Repository * %% @@ -15,17 +15,21 @@ * (at your option) any later version. * * Alfresco is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with Alfresco. If not, see . - * #L% - */ + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ package org.alfresco.repo.bulkimport.importfilters; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; + import org.alfresco.repo.bulkimport.ImportFilter; import org.alfresco.repo.bulkimport.ImportableItem; @@ -49,7 +53,14 @@ public class HiddenFileFilter implements ImportFilter if (importableItem.getHeadRevision().contentFileExists()) { - result = importableItem.getHeadRevision().getContentFile().isHidden(); + Path file = importableItem.getHeadRevision().getContentFile(); + try + { + result = Files.isHidden(file); + } + catch (IOException e) + { + } } return(result); diff --git a/source/java/org/alfresco/repo/bulkimport/metadataloaders/AbstractMapBasedMetadataLoader.java b/source/java/org/alfresco/repo/bulkimport/metadataloaders/AbstractMapBasedMetadataLoader.java index 6f6a100257..b29dd439d7 100644 --- a/source/java/org/alfresco/repo/bulkimport/metadataloaders/AbstractMapBasedMetadataLoader.java +++ b/source/java/org/alfresco/repo/bulkimport/metadataloaders/AbstractMapBasedMetadataLoader.java @@ -1,4 +1,4 @@ -/* +/* * #%L * Alfresco Repository * %% @@ -15,18 +15,19 @@ * (at your option) any later version. * * Alfresco is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with Alfresco. If not, see . - * #L% - */ + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ package org.alfresco.repo.bulkimport.metadataloaders; -import java.io.File; import java.io.Serializable; +import java.nio.file.Files; +import java.nio.file.Path; import java.util.ArrayList; import java.util.Arrays; import java.util.Map; @@ -98,7 +99,7 @@ abstract class AbstractMapBasedMetadataLoader implements MetadataLoader * @param metadataFile The file to load the properties from (must not be null). * @return A new Properties object loaded from that file. */ - abstract protected Map loadMetadataFromFile(final File metadataFile); + abstract protected Map loadMetadataFromFile(final Path metadataFile); @Override @@ -106,9 +107,9 @@ abstract class AbstractMapBasedMetadataLoader implements MetadataLoader { if (contentAndMetadata.metadataFileExists()) { - final File metadataFile = contentAndMetadata.getMetadataFile(); + final Path metadataFile = contentAndMetadata.getMetadataFile(); - if (metadataFile.canRead()) + if (Files.isReadable(metadataFile)) { Map metadataProperties = loadMetadataFromFile(metadataFile); diff --git a/source/java/org/alfresco/repo/bulkimport/metadataloaders/PropertiesFileMetadataLoader.java b/source/java/org/alfresco/repo/bulkimport/metadataloaders/PropertiesFileMetadataLoader.java index fdc934e282..5c3e444b78 100644 --- a/source/java/org/alfresco/repo/bulkimport/metadataloaders/PropertiesFileMetadataLoader.java +++ b/source/java/org/alfresco/repo/bulkimport/metadataloaders/PropertiesFileMetadataLoader.java @@ -1,4 +1,4 @@ -/* +/* * #%L * Alfresco Repository * %% @@ -15,21 +15,21 @@ * (at your option) any later version. * * Alfresco is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with Alfresco. If not, see . - * #L% - */ + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ package org.alfresco.repo.bulkimport.metadataloaders; import java.io.BufferedInputStream; -import java.io.File; -import java.io.FileInputStream; import java.io.IOException; import java.io.Serializable; +import java.nio.file.Files; +import java.nio.file.Path; import java.util.HashMap; import java.util.Map; import java.util.Properties; @@ -110,14 +110,14 @@ extends AbstractMapBasedMetadataLoader * @see org.alfresco.repo.bulkimport.metadataloaders.AbstractMapBasedMetadataLoader#loadMetadataFromFile(java.io.File) */ @Override - protected Map loadMetadataFromFile(File metadataFile) + protected Map loadMetadataFromFile(Path metadataFile) { Map result = null; try { Properties props = new Properties(); - props.load(new BufferedInputStream(new FileInputStream(metadataFile))); + props.load(new BufferedInputStream(Files.newInputStream(metadataFile))); result = new HashMap((Map)props); } catch (final IOException ioe) diff --git a/source/java/org/alfresco/repo/bulkimport/metadataloaders/XmlPropertiesFileMetadataLoader.java b/source/java/org/alfresco/repo/bulkimport/metadataloaders/XmlPropertiesFileMetadataLoader.java index 1ba5763b08..5028d9adf0 100644 --- a/source/java/org/alfresco/repo/bulkimport/metadataloaders/XmlPropertiesFileMetadataLoader.java +++ b/source/java/org/alfresco/repo/bulkimport/metadataloaders/XmlPropertiesFileMetadataLoader.java @@ -1,4 +1,4 @@ -/* +/* * #%L * Alfresco Repository * %% @@ -15,23 +15,23 @@ * (at your option) any later version. * * Alfresco is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with Alfresco. If not, see . - * #L% - */ + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ package org.alfresco.repo.bulkimport.metadataloaders; import java.io.BufferedInputStream; -import java.io.File; -import java.io.FileInputStream; import java.io.IOException; import java.io.Serializable; +import java.nio.file.Files; +import java.nio.file.Path; import java.util.HashMap; import java.util.Map; import java.util.Properties; @@ -112,14 +112,14 @@ public final class XmlPropertiesFileMetadataLoader extends AbstractMapBasedMetad * @see AbstractMapBasedMetadataLoader#loadMetadataFromFile(java.io.File) */ @Override - protected Map loadMetadataFromFile(File metadataFile) + protected Map loadMetadataFromFile(Path metadataFile) { Map result = null; try { Properties props = new Properties(); - props.loadFromXML(new BufferedInputStream(new FileInputStream(metadataFile))); + props.loadFromXML(new BufferedInputStream(Files.newInputStream(metadataFile))); result = new HashMap((Map)props); } catch (final IOException ioe) diff --git a/source/test-java/org/alfresco/repo/bulkimport/impl/BulkImportTest.java b/source/test-java/org/alfresco/repo/bulkimport/impl/BulkImportTest.java index 5451bbd91a..3695af97ca 100644 --- a/source/test-java/org/alfresco/repo/bulkimport/impl/BulkImportTest.java +++ b/source/test-java/org/alfresco/repo/bulkimport/impl/BulkImportTest.java @@ -1,4 +1,4 @@ -/* +/* * #%L * Alfresco Repository * %% @@ -15,14 +15,14 @@ * (at your option) any later version. * * Alfresco is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with Alfresco. If not, see . - * #L% - */ + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ package org.alfresco.repo.bulkimport.impl; import static org.junit.Assert.assertEquals; @@ -30,10 +30,18 @@ import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; +import java.io.File; +import java.io.IOException; +import java.io.OutputStream; import java.io.Serializable; +import java.nio.file.FileAlreadyExistsException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.StandardOpenOption; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.zip.GZIPInputStream; import javax.transaction.NotSupportedException; import javax.transaction.SystemException; @@ -54,7 +62,6 @@ import org.alfresco.service.cmr.rule.Rule; import org.alfresco.service.cmr.rule.RuleType; import org.alfresco.service.cmr.version.Version; import org.alfresco.service.cmr.version.VersionHistory; -import org.alfresco.test_category.BaseSpringTestsCategory; import org.alfresco.test_category.OwnJVMTestsCategory; import org.junit.Before; import org.junit.BeforeClass; @@ -607,5 +614,73 @@ public class BulkImportTest extends AbstractBulkImportTests assertEquals("This is version 1 of fileWithVersions.txt.", contentReader.getContentString()); } + + /** + * MNT-15367: Unable to bulk import filenames with Portuguese characters in a Linux environment + * + * @throws Throwable + */ + @Test + public void testImportFilesWithSpecialCharacters() throws Throwable + { + NodeRef folderNode = topLevelFolder.getNodeRef(); + NodeImporter nodeImporter = null; + + File source = ResourceUtils.getFile("classpath:bulkimport4"); + + String fileName = new String("135 CarbonÔÇô13 NMR spectroscopy_DS_NS_final_cau.txt".getBytes("ISO-8859-1"), "UTF-8"); + Path dest = source.toPath().resolve("encoding"); + try + { + dest = Files.createDirectory(dest); + } + catch (FileAlreadyExistsException ex) + { + } + Path destFile = dest.resolve(fileName); + + unpack(source.toPath(), destFile); + + txn = transactionService.getUserTransaction(); + txn.begin(); + + nodeImporter = streamingNodeImporterFactory.getNodeImporter(ResourceUtils.getFile("classpath:bulkimport4/encoding")); + + BulkImportParameters bulkImportParameters = new BulkImportParameters(); + bulkImportParameters.setTarget(folderNode); + bulkImportParameters.setReplaceExisting(true); + bulkImportParameters.setDisableRulesService(true); + bulkImportParameters.setBatchSize(40); + bulkImporter.bulkImport(bulkImportParameters, nodeImporter); + + assertEquals("", 1, bulkImporter.getStatus().getNumberOfContentNodesCreated()); + + checkFiles(folderNode, null, 0, 1, + new ExpectedFile[] { new ExpectedFile(fileName, MimetypeMap.MIMETYPE_TEXT_PLAIN)}, + null); + + Files.deleteIfExists(destFile); + Files.deleteIfExists(dest); + } + + private void unpack(Path source, Path destFile) + { + Path archive = source.resolve("testbulk.gz"); + + try (GZIPInputStream gzis = new GZIPInputStream(Files.newInputStream(archive)); + OutputStream out = Files.newOutputStream(destFile, StandardOpenOption.CREATE)) + { + byte[] buffer = new byte[1024]; + int len; + while ((len = gzis.read(buffer)) > 0) + { + out.write(buffer, 0, len); + } + } + catch (IOException ex) + { + ex.printStackTrace(); + } + } } diff --git a/source/test-resources/bulkimport4/testbulk.gz b/source/test-resources/bulkimport4/testbulk.gz new file mode 100644 index 0000000000..051c4539b1 Binary files /dev/null and b/source/test-resources/bulkimport4/testbulk.gz differ