diff --git a/datastore_server/source/java/ch/systemsx/cisd/etlserver/plugins/SimpleShufflingShareFinder.java b/datastore_server/source/java/ch/systemsx/cisd/etlserver/plugins/SimpleShufflingShareFinder.java
index 041895c028ccdec1b3b4790c6e98b60a55c9665a..194237ee416965fa3fb736e3a6a589bc2b6b2aee 100644
--- a/datastore_server/source/java/ch/systemsx/cisd/etlserver/plugins/SimpleShufflingShareFinder.java
+++ b/datastore_server/source/java/ch/systemsx/cisd/etlserver/plugins/SimpleShufflingShareFinder.java
@@ -24,6 +24,7 @@ import org.apache.commons.io.FileUtils;
 import ch.rinn.restrictions.Private;
 import ch.systemsx.cisd.common.utilities.PropertyUtils;
 import ch.systemsx.cisd.openbis.dss.generic.shared.AbstractShareFinder;
+import ch.systemsx.cisd.openbis.dss.generic.shared.ISpeedChecker;
 import ch.systemsx.cisd.openbis.dss.generic.shared.utils.Share;
 import ch.systemsx.cisd.openbis.generic.shared.dto.SimpleDataSetInformationDTO;
 
diff --git a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/shared/AbstractShareFinder.java b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/shared/AbstractShareFinder.java
index 2605ab176106b7c4aa31facaa95c3ac872702144..d3aa2f187b0e1ad194ff1632a4e6bd24ebd3cf4d 100644
--- a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/shared/AbstractShareFinder.java
+++ b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/shared/AbstractShareFinder.java
@@ -29,44 +29,6 @@ import ch.systemsx.cisd.openbis.generic.shared.dto.SimpleDataSetInformationDTO;
  */
 public abstract class AbstractShareFinder implements IShareFinder
 {
-    /**
-     * Returns <code>true</code> if speed of specified share and speed hint of specified data set
-     * are allowed. 
-     *
-     * @author Franz-Josef Elmer
-     */
-    public static interface ISpeedChecker
-    {
-        boolean check(SimpleDataSetInformationDTO dataSet, Share share);
-    }
-    
-    private enum SpeedChecker implements ISpeedChecker
-    {
-        MATCHING_CHECKER()
-        {
-            public boolean check(SimpleDataSetInformationDTO dataSet, Share share)
-            {
-                return Math.abs(dataSet.getSpeedHint()) == share.getSpeed();
-            }
-        },
-        RESPECTUNG_SPEED_HINT_CHECKER()
-        {
-            public boolean check(SimpleDataSetInformationDTO dataSet, Share share)
-            {
-                int speedHint = dataSet.getSpeedHint();
-                int speed = share.getSpeed();
-                return speedHint < 0 ? speed < Math.abs(speedHint) : speed > speedHint;
-            }
-        },
-        IGNORING_SPEED_HINT_CHECKER()
-        {
-            public boolean check(SimpleDataSetInformationDTO dataSet, Share share)
-            {
-                return true;
-            }
-        }
-    }
-
     /**
      * Tries to find a share fulfilling speed hint contract.
      */
diff --git a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/shared/ISpeedChecker.java b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/shared/ISpeedChecker.java
new file mode 100644
index 0000000000000000000000000000000000000000..0a4f50fa20b56754b1cda93d520067a592e54ee3
--- /dev/null
+++ b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/shared/ISpeedChecker.java
@@ -0,0 +1,15 @@
+package ch.systemsx.cisd.openbis.dss.generic.shared;
+
+import ch.systemsx.cisd.openbis.dss.generic.shared.utils.Share;
+import ch.systemsx.cisd.openbis.generic.shared.dto.SimpleDataSetInformationDTO;
+
+/**
+ * Returns <code>true</code> if speed of specified share and speed hint of specified data set
+ * are allowed. 
+ *
+ * @author Franz-Josef Elmer
+ */
+public interface ISpeedChecker
+{
+    public boolean check(SimpleDataSetInformationDTO dataSet, Share share);
+}
\ No newline at end of file
diff --git a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/shared/SpeedChecker.java b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/shared/SpeedChecker.java
new file mode 100644
index 0000000000000000000000000000000000000000..de231c579180c0ae87ba48a93cca1edd7a95b841
--- /dev/null
+++ b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/shared/SpeedChecker.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright 2011 ETH Zuerich, CISD
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package ch.systemsx.cisd.openbis.dss.generic.shared;
+
+import ch.systemsx.cisd.openbis.dss.generic.shared.utils.Share;
+import ch.systemsx.cisd.openbis.generic.shared.dto.SimpleDataSetInformationDTO;
+
+/**
+ * Enumeration of {@link ISpeedChecker} ordered in accordance to strictness.
+ * 
+ *
+ * @author Franz-Josef Elmer
+ */
+public enum SpeedChecker implements ISpeedChecker
+{
+    MATCHING_CHECKER()
+    {
+        public boolean check(SimpleDataSetInformationDTO dataSet, Share share)
+        {
+            return Math.abs(dataSet.getSpeedHint()) == share.getSpeed();
+        }
+    },
+    RESPECTUNG_SPEED_HINT_CHECKER()
+    {
+        public boolean check(SimpleDataSetInformationDTO dataSet, Share share)
+        {
+            int speedHint = dataSet.getSpeedHint();
+            int speed = share.getSpeed();
+            return speedHint < 0 ? speed < Math.abs(speedHint) : speed > speedHint;
+        }
+    },
+    IGNORING_SPEED_HINT_CHECKER()
+    {
+        public boolean check(SimpleDataSetInformationDTO dataSet, Share share)
+        {
+            return true;
+        }
+    }
+}
\ No newline at end of file
diff --git a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/shared/SpeedOptimizedShareFinder.java b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/shared/SpeedOptimizedShareFinder.java
new file mode 100644
index 0000000000000000000000000000000000000000..ae6db7f3e865296e3b019ca3ab5e9cc6e3f228e1
--- /dev/null
+++ b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/shared/SpeedOptimizedShareFinder.java
@@ -0,0 +1,81 @@
+/*
+ * Copyright 2011 ETH Zuerich, CISD
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package ch.systemsx.cisd.openbis.dss.generic.shared;
+
+import java.util.List;
+import java.util.Properties;
+
+import ch.systemsx.cisd.openbis.dss.generic.shared.utils.Share;
+import ch.systemsx.cisd.openbis.generic.shared.dto.SimpleDataSetInformationDTO;
+
+/**
+ * A share finder which first searches for the extension share with most free space which matches
+ * speed. If nothing found it does the same also for all extension shares but speed needs not to
+ * match but speed hint needs to be respected. If this isn't working {@link SimpleShareFinder} is
+ * used ignoring speed hint.
+ * 
+ * @author Franz-Josef Elmer
+ */
+public class SpeedOptimizedShareFinder implements IShareFinder
+{
+    private final SimpleShareFinder simpleFinder;
+
+    public SpeedOptimizedShareFinder(Properties properties)
+    {
+        simpleFinder = new SimpleShareFinder(properties);
+    }
+
+    public Share tryToFindShare(SimpleDataSetInformationDTO dataSet, List<Share> shares)
+    {
+        Share share = tryToFindeExtensionShare(dataSet, shares, SpeedChecker.MATCHING_CHECKER);
+        if (share != null)
+        {
+            return share;
+        }
+        share =
+                tryToFindeExtensionShare(dataSet, shares,
+                        SpeedChecker.RESPECTUNG_SPEED_HINT_CHECKER);
+        if (share != null)
+        {
+            return share;
+        }
+        return simpleFinder.tryToFindShare(dataSet, shares,
+                SpeedChecker.IGNORING_SPEED_HINT_CHECKER);
+    }
+
+    private Share tryToFindeExtensionShare(SimpleDataSetInformationDTO dataSet, List<Share> shares,
+            ISpeedChecker speedChecker)
+    {
+        Share result = null;
+        long maxFreeSpace = dataSet.getDataSetSize();
+        for (Share share : shares)
+        {
+            if (share.isIncoming() || speedChecker.check(dataSet, share) == false)
+            {
+                continue;
+            }
+            long freeSpace = share.calculateFreeSpace();
+            if (freeSpace > maxFreeSpace)
+            {
+                maxFreeSpace = freeSpace;
+                result = share;
+            }
+        }
+        return result;
+    }
+    
+}
diff --git a/datastore_server/sourceTest/java/ch/systemsx/cisd/etlserver/plugins/SimpleShufflingShareFinderTest.java b/datastore_server/sourceTest/java/ch/systemsx/cisd/etlserver/plugins/SimpleShufflingShareFinderTest.java
index 19212c2a0e6c752fb32b857255328524b0655998..f681f1e8f9644413a760973aa76fcf508a6d4d40 100644
--- a/datastore_server/sourceTest/java/ch/systemsx/cisd/etlserver/plugins/SimpleShufflingShareFinderTest.java
+++ b/datastore_server/sourceTest/java/ch/systemsx/cisd/etlserver/plugins/SimpleShufflingShareFinderTest.java
@@ -36,7 +36,7 @@ import ch.rinn.restrictions.Friend;
 import ch.systemsx.cisd.base.exceptions.CheckedExceptionTunnel;
 import ch.systemsx.cisd.common.filesystem.HostAwareFile;
 import ch.systemsx.cisd.common.filesystem.IFreeSpaceProvider;
-import ch.systemsx.cisd.openbis.dss.generic.shared.AbstractShareFinder;
+import ch.systemsx.cisd.openbis.dss.generic.shared.ISpeedChecker;
 import ch.systemsx.cisd.openbis.dss.generic.shared.utils.Share;
 import ch.systemsx.cisd.openbis.generic.shared.dto.SimpleDataSetInformationDTO;
 
@@ -50,7 +50,7 @@ public class SimpleShufflingShareFinderTest extends AssertJUnit
 {
     private static final String DATA_SET_CODE = "ds-1";
 
-    private static final class MockSpeedChecker implements AbstractShareFinder.ISpeedChecker
+    private static final class MockSpeedChecker implements ISpeedChecker
     {
         private final boolean[] checkingResults;
         
diff --git a/datastore_server/sourceTest/java/ch/systemsx/cisd/openbis/dss/generic/shared/SimpleShareFinderTest.java b/datastore_server/sourceTest/java/ch/systemsx/cisd/openbis/dss/generic/shared/SimpleShareFinderTest.java
index a6db43a8641bc898524b064fa042de606b169b90..10cdebf9b1cb1fc60240f95efcefac19759a45d2 100644
--- a/datastore_server/sourceTest/java/ch/systemsx/cisd/openbis/dss/generic/shared/SimpleShareFinderTest.java
+++ b/datastore_server/sourceTest/java/ch/systemsx/cisd/openbis/dss/generic/shared/SimpleShareFinderTest.java
@@ -40,7 +40,7 @@ import ch.systemsx.cisd.openbis.generic.shared.dto.SimpleDataSetInformationDTO;
  */
 public class SimpleShareFinderTest extends AssertJUnit
 {
-    private static final class MockSpeedChecker implements AbstractShareFinder.ISpeedChecker
+    private static final class MockSpeedChecker implements ISpeedChecker
     {
         private final boolean[] checkingResults;
         
diff --git a/datastore_server/sourceTest/java/ch/systemsx/cisd/openbis/dss/generic/shared/SpeedOptimizedShareFinderTest.java b/datastore_server/sourceTest/java/ch/systemsx/cisd/openbis/dss/generic/shared/SpeedOptimizedShareFinderTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..babf246483a30d857068ae0139762692b14e67fe
--- /dev/null
+++ b/datastore_server/sourceTest/java/ch/systemsx/cisd/openbis/dss/generic/shared/SpeedOptimizedShareFinderTest.java
@@ -0,0 +1,142 @@
+/*
+ * Copyright 2011 ETH Zuerich, CISD
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package ch.systemsx.cisd.openbis.dss.generic.shared;
+
+import static org.apache.commons.io.FileUtils.ONE_MB;
+
+import java.io.File;
+import java.io.IOException;
+import java.lang.reflect.Method;
+import java.util.Arrays;
+import java.util.Properties;
+
+import org.apache.commons.io.FileUtils;
+import org.jmock.Expectations;
+import org.jmock.Mockery;
+import org.testng.AssertJUnit;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+import ch.systemsx.cisd.base.exceptions.CheckedExceptionTunnel;
+import ch.systemsx.cisd.common.filesystem.HostAwareFile;
+import ch.systemsx.cisd.common.filesystem.IFreeSpaceProvider;
+import ch.systemsx.cisd.openbis.dss.generic.shared.utils.Share;
+import ch.systemsx.cisd.openbis.generic.shared.dto.SimpleDataSetInformationDTO;
+
+/**
+ * 
+ *
+ * @author Franz-Josef Elmer
+ */
+public class SpeedOptimizedShareFinderTest extends AssertJUnit
+{
+    private static final String DATA_SET_CODE = "ds-1";
+    
+    private SpeedOptimizedShareFinder finder;
+    
+    private Mockery context;
+    private IFreeSpaceProvider freeSpaceProvider;
+    private SimpleDataSetInformationDTO dataSet;
+    
+    @BeforeMethod
+    public void setUp()
+    {
+        context = new Mockery();
+        freeSpaceProvider = context.mock(IFreeSpaceProvider.class);
+        dataSet = new SimpleDataSetInformationDTO();
+        dataSet.setDataSetCode(DATA_SET_CODE);
+        dataSet.setDataSetSize(FileUtils.ONE_MB);
+        finder = new SpeedOptimizedShareFinder(new Properties());
+    }
+    
+    @AfterMethod
+    public void tearDown(Method method)
+    {
+        try
+        {
+            context.assertIsSatisfied();
+        } catch (Throwable t)
+        {
+            // assert expectations were met, including the name of the failed method
+            throw new Error(method.getName() + "() : ", t);
+        }
+    }
+    
+    @Test
+    public void testFindMatchingExtensionShare()
+    {
+        dataSet.setSpeedHint(-50);
+        Share s1 = share(false, 50, 10 * ONE_MB);
+        Share s2 = share(true, 50, 0);
+        Share s3 = share(false, 40, 0);
+        Share s4 = share(false, 50, 11 * ONE_MB);
+        
+        Share foundShare = finder.tryToFindShare(dataSet, Arrays.asList(s1, s2, s3, s4));
+        assertSame(s4.getShare(), foundShare.getShare());
+    }
+    
+    @Test
+    public void testFindExtensionShareRespectingSpeedHint()
+    {
+        dataSet.setSpeedHint(-50);
+        Share s1 = share(false, 49, 10 * ONE_MB);
+        Share s2 = share(true, 50, 0);
+        Share s3 = share(false, 40, 11 * ONE_MB);
+        
+        Share foundShare = finder.tryToFindShare(dataSet, Arrays.asList(s1, s2, s3));
+        assertSame(s3.getShare(), foundShare.getShare());
+    }
+    
+    @Test
+    public void testFindShareIgnoringSpeedHint()
+    {
+        dataSet.setSpeedHint(-50);
+        dataSet.setDataSetShareId("20");
+        Share s1 = share(false, 51, 10 * ONE_MB);
+        Share s2 = share(true, 50, 20 * ONE_MB);
+        Share s3 = share(false, 60, 11 * ONE_MB);
+        Share s4 = share(true, 50, 15 * ONE_MB);
+        
+        Share foundShare = finder.tryToFindShare(dataSet, Arrays.asList(s1, s2, s3, s4));
+        assertSame(s3.getShare(), foundShare.getShare());
+    }
+    
+    private Share share(boolean incoming, int speed, final long freeSpace)
+    {
+        final File file = new File(Integer.toString(speed) + "/" + incoming + "/" + freeSpace);
+        if (freeSpace > 0)
+        {
+            context.checking(new Expectations()
+                {
+                    {
+                        try
+                        {
+                            one(freeSpaceProvider).freeSpaceKb(new HostAwareFile(file));
+                            will(returnValue(freeSpace / FileUtils.ONE_KB));
+                        } catch (IOException ex)
+                        {
+                            throw CheckedExceptionTunnel.wrapIfNecessary(ex);
+                        }
+                    }
+                });
+        }
+        Share share = new Share(file, speed, freeSpaceProvider);
+        share.setIncoming(incoming);
+        return share;
+    }
+}