You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@manifoldcf.apache.org by kw...@apache.org on 2013/12/24 11:43:17 UTC

svn commit: r1553263 - /manifoldcf/trunk/connectors/filesystem/connector/src/main/java/org/apache/manifoldcf/agents/output/filesystem/FileOutputConnector.java

Author: kwright
Date: Tue Dec 24 10:43:17 2013
New Revision: 1553263

URL: http://svn.apache.org/r1553263
Log:
File system output connector logic to avoid collisions.  Part of CONNECTORS-814.

Modified:
    manifoldcf/trunk/connectors/filesystem/connector/src/main/java/org/apache/manifoldcf/agents/output/filesystem/FileOutputConnector.java

Modified: manifoldcf/trunk/connectors/filesystem/connector/src/main/java/org/apache/manifoldcf/agents/output/filesystem/FileOutputConnector.java
URL: http://svn.apache.org/viewvc/manifoldcf/trunk/connectors/filesystem/connector/src/main/java/org/apache/manifoldcf/agents/output/filesystem/FileOutputConnector.java?rev=1553263&r1=1553262&r2=1553263&view=diff
==============================================================================
--- manifoldcf/trunk/connectors/filesystem/connector/src/main/java/org/apache/manifoldcf/agents/output/filesystem/FileOutputConnector.java (original)
+++ manifoldcf/trunk/connectors/filesystem/connector/src/main/java/org/apache/manifoldcf/agents/output/filesystem/FileOutputConnector.java Tue Dec 24 10:43:17 2013
@@ -180,28 +180,78 @@ public class FileOutputConnector extends
       if (specs.getRootPath() != null) {
         path.append(specs.getRootPath());
       }
-      path.append("/");
-      path.append(documentURItoFilePath(documentURI));
-
-      File file = new File(path.toString());
-
-      //System.out.println("File is '"+file+"'");
-
-      /*
-       * make directory
-       */
-      if (!file.getParentFile().exists()) {
-        file.getParentFile().mkdirs();
-      }
-
-      /*
-       * delete old file
-       */
-      if (file.exists()) {
-        file.delete();
+      
+      // If the path does not yet exist at the root level, it is dangerous to create it.
+      File currentPath = new File(path.toString());
+      if (!currentPath.exists())
+        throw new ManifoldCFException("Root path does not yet exist: '"+currentPath+"'");
+      if (!currentPath.isDirectory())
+        throw new ManifoldCFException("Root path is not a directory: '"+currentPath+"'");
+      
+      String filePath = documentURItoFilePath(documentURI);
+      
+      // Build path one level at a time.  This is needed because there may be a collision at
+      // every level.
+      int index = 0;
+      while (true)
+      {
+        int currentIndex = filePath.indexOf("/",index);
+        if (currentIndex == -1)
+          break;
+        String dirName = filePath.substring(index,currentIndex);
+        File newPath = new File(currentPath, dirName);
+        index = currentIndex + 1;
+        int suffix = 1;
+        while (true)
+        {
+          if (newPath.exists() && newPath.isDirectory())
+            break;
+          // Try to create it.  If we fail, check if it now exists as a file.
+          if (newPath.mkdir())
+            break;
+          // Hmm, didn't create.  If it is a file, we suffered a collision, so try again with ".N" as a suffix.
+          if (newPath.exists())
+          {
+            if (newPath.isDirectory())
+              break;
+            newPath = new File(currentPath, dirName + "." + suffix);
+            suffix++;
+          }
+          else
+            throw new ManifoldCFException("Could not create directory '"+newPath+"'.  Permission issue?");
+        }
+        // Directory successfully created!
+        currentPath = newPath;
+        // Go on to the next one.
+      }
+      
+      // Path successfully created.  Now create file.
+      FileOutputStream output = null;
+      String fileName = filePath.substring(index);
+      File outputPath = new File(currentPath, fileName);
+      int fileSuffix = 1;
+      while (true)
+      {
+        try
+        {
+          output = new FileOutputStream(outputPath);
+          break;
+        }
+        catch (FileNotFoundException e)
+        {
+          // Figure out why it could not be created.
+          if (outputPath.exists() && !outputPath.isFile())
+          {
+            // try a new file
+            outputPath = new File(currentPath, fileName + "." + fileSuffix);
+            fileSuffix++;
+            continue;
+          }
+          // Probably some other error
+          throw new ManifoldCFException("Could not create file '"+outputPath+"': "+e.getMessage(),e);
+        }
       }
 
-      FileOutputStream output = new FileOutputStream(file);
       try {
         /*
          * lock file
@@ -209,7 +259,7 @@ public class FileOutputConnector extends
         FileChannel channel = output.getChannel();
         FileLock lock = channel.tryLock();
         if (lock == null)
-          throw new ServiceInterruption("Could not lock file: '"+file+"'",null,1000L,-1L,10,false);
+          throw new ServiceInterruption("Could not lock file: '"+outputPath+"'",null,1000L,-1L,10,false);
 
         try {
 
@@ -217,7 +267,7 @@ public class FileOutputConnector extends
            * write file
            */
           InputStream input = document.getBinaryStream();
-          byte buf[] = new byte[1024];
+          byte buf[] = new byte[65536];
           int len;
           while((len = input.read(buf)) != -1) {
             output.write(buf, 0, len);
@@ -244,12 +294,12 @@ public class FileOutputConnector extends
     } catch (URISyntaxException e) {
       handleURISyntaxException(e);
       return DOCUMENTSTATUS_REJECTED;
-    } catch (SecurityException e) {
-      handleSecurityException(e);
-      return DOCUMENTSTATUS_REJECTED;
     } catch (FileNotFoundException e) {
       handleFileNotFoundException(e);
       return DOCUMENTSTATUS_REJECTED;
+    } catch (SecurityException e) {
+      handleSecurityException(e);
+      return DOCUMENTSTATUS_REJECTED;
     } catch (IOException e) {
       handleIOException(e);
       return DOCUMENTSTATUS_REJECTED;