diff --git a/modules/plugin/jdbc/jdbc-oracle/src/main/java/org/geotools/data/oracle/OracleFilterToSQL.java b/modules/plugin/jdbc/jdbc-oracle/src/main/java/org/geotools/data/oracle/OracleFilterToSQL.java
index e434138..9dff5c0 100644
--- a/modules/plugin/jdbc/jdbc-oracle/src/main/java/org/geotools/data/oracle/OracleFilterToSQL.java
+++ b/modules/plugin/jdbc/jdbc-oracle/src/main/java/org/geotools/data/oracle/OracleFilterToSQL.java
@@ -308,7 +308,8 @@ public class OracleFilterToSQL extends PreparedFilterToSQL {
     protected void doSDODistance(BinarySpatialOperator filter,
             Expression e1, Expression e2, Object extraData) throws IOException {
         double distance = ((DistanceBufferOperator) filter).getDistance();
-        String unit = ((DistanceBufferOperator) filter).getDistanceUnits();
+        String unit = getSDOUnitFromOGCUnit(((DistanceBufferOperator) filter).getDistanceUnits());
+
         String within = filter instanceof DWithin ? "TRUE" : "FALSE"; 
         
         out.write("SDO_WITHIN_DISTANCE(");
@@ -322,5 +323,28 @@ public class OracleFilterToSQL extends PreparedFilterToSQL {
         else
             out.write(",'distance=" + distance + "') = '" + within + "' ");
     }
-   
+
+    /**
+     * The mapping between OGC filter units and Oracle Units.
+     * The full list of Oracle Units can be obtained by issuing
+     *  "select * from MDSYS.SDO_DIST_UNITS WHERE SDO_UNIT IS NOT NULL order by SDO_UNIT;"
+     */
+    private static final Map<String, String> UNITS_MAP = new HashMap<String, String>() {
+        {
+            put("metre", "m");
+            put("meters", "m");
+            put("kilometers", "km");
+            put("mi", "Mile");
+            put("miles", "Mile");
+            put("NM", "naut_mile");
+            put("feet", "foot");
+            put("ft", "foot");
+            put("in", "inch");
+        }
+    };
+
+    private static String getSDOUnitFromOGCUnit(String ogcUnit) {
+        Object sdoUnit = UNITS_MAP.get(ogcUnit);
+        return sdoUnit != null ? sdoUnit.toString() : ogcUnit;
+    }
 }
diff --git a/modules/plugin/jdbc/jdbc-oracle/src/test/java/org/geotools/data/oracle/OracleSpatialFiltersTest.java b/modules/plugin/jdbc/jdbc-oracle/src/test/java/org/geotools/data/oracle/OracleSpatialFiltersTest.java
index 797b4ae..8c677e9 100644
--- a/modules/plugin/jdbc/jdbc-oracle/src/test/java/org/geotools/data/oracle/OracleSpatialFiltersTest.java
+++ b/modules/plugin/jdbc/jdbc-oracle/src/test/java/org/geotools/data/oracle/OracleSpatialFiltersTest.java
@@ -16,12 +16,24 @@
  */
 package org.geotools.data.oracle;
 
+import org.geotools.data.Query;
+import org.geotools.data.simple.SimpleFeatureCollection;
 import org.geotools.factory.CommonFactoryFinder;
 import org.geotools.feature.FeatureCollection;
 import org.geotools.jdbc.JDBCDataStoreAPITestSetup;
 import org.geotools.jdbc.JDBCSpatialFiltersTest;
 import org.opengis.filter.FilterFactory;
+import org.opengis.filter.FilterFactory2;
+import org.opengis.filter.expression.Literal;
+import org.opengis.filter.expression.PropertyName;
 import org.opengis.filter.spatial.BBOX;
+import org.opengis.filter.spatial.DWithin;
+
+import com.vividsolutions.jts.geom.Coordinate;
+import com.vividsolutions.jts.geom.Geometry;
+import com.vividsolutions.jts.geom.GeometryCollection;
+import com.vividsolutions.jts.geom.GeometryFactory;
+import com.vividsolutions.jts.geom.Point;
 
 /**
  * 
@@ -44,4 +56,45 @@ public class OracleSpatialFiltersTest extends JDBCSpatialFiltersTest {
         FeatureCollection features = dataStore.getFeatureSource(tname("road")).getFeatures(bbox);
         checkSingleResult(features, "r2");
     }
+
+    // As reported in GEOS-4384 (http://jira.codehaus.org/browse/GEOS-4384)
+    public void testSDODWithinOGCUnits() throws Exception {
+        // express the same distance in different ways and check results
+        validateOGCUnitUsage(10, "kilometers");
+        validateOGCUnitUsage(10, "km");
+        validateOGCUnitUsage(10, "kilometer");
+        // this one does not work... not sure why 
+        // validateOGCUnitUsage(10000 * 1000, "mm");
+        validateOGCUnitUsage(10000, "m");
+        validateOGCUnitUsage(10000, "metre");
+        validateOGCUnitUsage(10000, "meters");
+        validateOGCUnitUsage(10000 / 0.0254, "in");
+        validateOGCUnitUsage(10000 / 0.3048, "feet");
+        validateOGCUnitUsage(10000 / 0.3048, "foot");
+        validateOGCUnitUsage(10000 / 0.3048, "ft");
+        validateOGCUnitUsage(10000 / 1609.344, "mi");
+        validateOGCUnitUsage(10000 / 1609.344, "mile");
+        validateOGCUnitUsage(10000 / 1609.344, "miles");
+        validateOGCUnitUsage(10000 / 1852, "NM");
+      }
+
+    private void validateOGCUnitUsage(double distance, String unit) throws Exception {
+        Coordinate coordinate = new Coordinate(3.031, 2.754);
+        GeometryFactory factory = new GeometryFactory();
+        Point point = factory.createPoint(coordinate);
+        Geometry[] geometries = {point};
+        GeometryCollection geometry = new GeometryCollection(geometries, factory );
+
+        FilterFactory2 ff = CommonFactoryFinder.getFilterFactory2(null);
+
+        PropertyName geomName = ff.property(aname("geom"));
+        Literal lit = ff.literal(geometry);
+        
+        DWithin dwithinGeomFilter  = ((FilterFactory2) ff).dwithin(geomName, lit, distance, unit);
+        Query query = new Query(tname("road"), dwithinGeomFilter);
+        SimpleFeatureCollection features = dataStore.getFeatureSource(tname("road")).getFeatures(query);
+        assertEquals(1, features.size());
+        checkSingleResult(features, "r2");
+    }
+
 }
diff --git a/modules/plugin/jdbc/jdbc-postgis/src/main/java/org/geotools/data/postgis/FilterToSqlHelper.java b/modules/plugin/jdbc/jdbc-postgis/src/main/java/org/geotools/data/postgis/FilterToSqlHelper.java
index c9a232f..d970860 100644
--- a/modules/plugin/jdbc/jdbc-postgis/src/main/java/org/geotools/data/postgis/FilterToSqlHelper.java
+++ b/modules/plugin/jdbc/jdbc-postgis/src/main/java/org/geotools/data/postgis/FilterToSqlHelper.java
@@ -24,7 +24,9 @@ import java.sql.Date;
 import java.sql.Time;
 import java.sql.Timestamp;
 import java.util.ArrayList;
+import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
 
 import org.geotools.data.jdbc.FilterToSQL;
 import org.geotools.factory.CommonFactoryFinder;
@@ -90,6 +92,24 @@ class FilterToSqlHelper {
     
     protected static final String IO_ERROR = "io problem writing filter";
     
+    /**
+     * Conversion factor from common units to meter
+     */
+    private static final Map<String, Double> UNITS_MAP = new HashMap<String, Double>() {
+        {
+            put("kilometers", 1000.0);
+            put("kilometer", 1000.0);
+            put("mm", 0.001);
+            put("millimeter", 0.001);
+            put("mi", 1609.344);
+            put("miles", 1609.344);
+            put("NM", 1852d);
+            put("feet", 0.3048);
+            put("ft", 0.3048);
+            put("in", 0.0254);
+        }
+    };
+    
     private static final Envelope WORLD = new Envelope(-180, 180, -90, 90);
     
     FilterToSQL delegate;
@@ -193,7 +213,7 @@ class FilterToSqlHelper {
             out.write(",");
             geometry.accept(delegate, extraData);
             out.write(",");
-            out.write(Double.toString(filter.getDistance()));
+            out.write(toMeters(filter.getDistance(), filter.getDistanceUnits()));
             out.write(")");
         }
         if ((filter instanceof DWithin && swapped)
@@ -207,6 +227,19 @@ class FilterToSqlHelper {
         }
     }
 
+    private String toMeters(double distance, String unit) {
+        // only geography uses metric units
+        if(isCurrentGeography()) {
+            Double conversion = UNITS_MAP.get(unit);
+            if(conversion != null) {
+                return String.valueOf(distance * conversion);
+            }
+        }
+        
+        // in case unknown unit or not geography, use as-is
+        return String.valueOf(distance);
+    }
+
     void visitComparisonSpatialOperator(BinarySpatialOperator filter,
             PropertyName property, Literal geometry, boolean swapped, Object extraData)
             throws IOException {
diff --git a/modules/plugin/jdbc/jdbc-postgis/src/test/java/org/geotools/data/postgis/PostgisGeographyTest.java b/modules/plugin/jdbc/jdbc-postgis/src/test/java/org/geotools/data/postgis/PostgisGeographyTest.java
index f9c9f59..0b32e2a 100644
--- a/modules/plugin/jdbc/jdbc-postgis/src/test/java/org/geotools/data/postgis/PostgisGeographyTest.java
+++ b/modules/plugin/jdbc/jdbc-postgis/src/test/java/org/geotools/data/postgis/PostgisGeographyTest.java
@@ -16,10 +16,26 @@
  */
 package org.geotools.data.postgis;
 
+import org.geotools.data.Query;
+import org.geotools.data.simple.SimpleFeatureCollection;
+import org.geotools.factory.CommonFactoryFinder;
+import org.geotools.feature.FeatureCollection;
+import org.geotools.feature.FeatureIterator;
 import org.geotools.jdbc.JDBCDataStore;
 import org.geotools.jdbc.JDBCGeographyTest;
 import org.geotools.jdbc.JDBCGeographyTestSetup;
+import org.opengis.feature.simple.SimpleFeature;
 import org.opengis.feature.simple.SimpleFeatureType;
+import org.opengis.filter.FilterFactory2;
+import org.opengis.filter.expression.Literal;
+import org.opengis.filter.expression.PropertyName;
+import org.opengis.filter.spatial.DWithin;
+
+import com.vividsolutions.jts.geom.Coordinate;
+import com.vividsolutions.jts.geom.Geometry;
+import com.vividsolutions.jts.geom.GeometryCollection;
+import com.vividsolutions.jts.geom.GeometryFactory;
+import com.vividsolutions.jts.geom.Point;
 
 /**
  * 
@@ -45,4 +61,53 @@ public class PostgisGeographyTest extends JDBCGeographyTest {
         SimpleFeatureType ft = dataStore.getFeatureSource(tname("geopoint")).getSchema();
         assertEquals("geography", ft.getGeometryDescriptor().getUserData().get(JDBCDataStore.JDBC_NATIVE_TYPENAME));
     }
+    
+    // As reported in GEOS-4384 (http://jira.codehaus.org/browse/GEOS-4384)
+    public void testDWithinOGCUnits() throws Exception {
+        validateOGCUnitUsage(10000, "m");
+        validateOGCUnitUsage(10000, "metre");
+        validateOGCUnitUsage(10000, "meters");
+        validateOGCUnitUsage(10000 * 1000, "mm");
+        validateOGCUnitUsage(10, "kilometers");
+        validateOGCUnitUsage(10, "km");
+        validateOGCUnitUsage(10, "kilometer");
+        validateOGCUnitUsage(10000 / 0.0254, "in");
+        validateOGCUnitUsage(10000 / 0.3048, "feet");
+        validateOGCUnitUsage(10000 / 0.3048, "foot");
+        validateOGCUnitUsage(10000 / 0.3048, "ft");
+        validateOGCUnitUsage(10000 / 1609.344, "mi");
+        validateOGCUnitUsage(10000 / 1609.344, "mile");
+        validateOGCUnitUsage(10000 / 1609.344, "miles");
+        validateOGCUnitUsage(10000 / 1852, "NM");
+      }
+
+    private void validateOGCUnitUsage(double distance, String unit) throws Exception {
+        Coordinate coordinate = new Coordinate(-110, 30);
+        GeometryFactory factory = new GeometryFactory();
+        Point point = factory.createPoint(coordinate);
+        Geometry[] geometries = {point};
+        GeometryCollection geometry = new GeometryCollection(geometries, factory );
+
+        FilterFactory2 ff = CommonFactoryFinder.getFilterFactory2(null);
+
+        PropertyName geomName = ff.property(aname("geo"));
+        Literal lit = ff.literal(geometry);
+        
+        DWithin dwithinGeomFilter  = ((FilterFactory2) ff).dwithin(geomName, lit, distance, unit);
+        Query query = new Query(tname("geopoint"), dwithinGeomFilter);
+        SimpleFeatureCollection features = dataStore.getFeatureSource(tname("geopoint")).getFeatures(query);
+        assertEquals(1, features.size());
+        checkSingleResult(features, "Town");
+    }
+    
+    protected void checkSingleResult(FeatureCollection features, String name) {
+        assertEquals(1, features.size());
+        FeatureIterator fr = features.features();
+        assertTrue(fr.hasNext());
+        SimpleFeature f = (SimpleFeature) fr.next();
+        assertNotNull(f);
+        assertEquals(name, f.getAttribute(aname("name")));
+        assertFalse(fr.hasNext());
+        fr.close();
+    }
 }
