Index: src/protocol/jdbc/org/apache/jmeter/protocol/jdbc/AbstractJdbcTestElement.java
===================================================================
--- src/protocol/jdbc/org/apache/jmeter/protocol/jdbc/AbstractJdbcTestElement.java	(revision 0)
+++ src/protocol/jdbc/org/apache/jmeter/protocol/jdbc/AbstractJdbcTestElement.java	(revision 0)
@@ -0,0 +1,568 @@
+package org.apache.jmeter.protocol.jdbc;
+
+import java.io.IOException;
+import java.io.UnsupportedEncodingException;
+import java.lang.reflect.Field;
+import java.sql.CallableStatement;
+import java.sql.Connection;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.ResultSetMetaData;
+import java.sql.SQLException;
+import java.sql.Statement;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.commons.lang.text.StrBuilder;
+import org.apache.jmeter.samplers.SampleResult;
+import org.apache.jmeter.save.CSVSaveService;
+import org.apache.jmeter.testelement.AbstractTestElement;
+import org.apache.jmeter.threads.JMeterVariables;
+import org.apache.jmeter.util.JMeterUtils;
+import org.apache.jorphan.logging.LoggingManager;
+import org.apache.log.Logger;
+
+public abstract class AbstractJdbcTestElement extends AbstractTestElement {
+    private static final long serialVersionUID = 235L;
+
+    private static final Logger log = LoggingManager.getLoggerForClass();
+
+    private static final String COMMA = ","; // $NON-NLS-1$
+    private static final char COMMA_CHAR = ',';
+
+    private static final String UNDERSCORE = "_"; // $NON-NLS-1$
+
+    // This value is used for both the connection (perConnCache) and statement (preparedStatementMap) caches.
+    // TODO - do they have to be the same size?
+    private static final int MAX_ENTRIES =
+        JMeterUtils.getPropDefault("jdbcsampler.cachesize",200); // $NON-NLS-1$
+
+    // String used to indicate a null value
+    private static final String NULL_MARKER =
+        JMeterUtils.getPropDefault("jdbcsampler.nullmarker","]NULL["); // $NON-NLS-1$
+
+    private static final String INOUT = "INOUT"; // $NON-NLS-1$
+
+    private static final String OUT = "OUT"; // $NON-NLS-1$
+
+    // TODO - should the encoding be configurable?
+    protected static final String ENCODING = "UTF-8"; // $NON-NLS-1$
+
+    // key: name (lowercase) from java.sql.Types; entry: corresponding int value
+    private static final Map<String, Integer> mapJdbcNameToInt;
+    // read-only after class init
+
+    static {
+        // based on e291. Getting the Name of a JDBC Type from javaalmanac.com
+        // http://javaalmanac.com/egs/java.sql/JdbcInt2Str.html
+        mapJdbcNameToInt = new HashMap<String, Integer>();
+
+        //Get all fields in java.sql.Types and store the corresponding int values
+        Field[] fields = java.sql.Types.class.getFields();
+        for (int i=0; i<fields.length; i++) {
+            try {
+                String name = fields[i].getName();
+                Integer value = (Integer)fields[i].get(null);
+                mapJdbcNameToInt.put(name.toLowerCase(java.util.Locale.ENGLISH),value);
+            } catch (IllegalAccessException e) {
+                throw new RuntimeException(e); // should not happen
+            }
+        }
+    }
+
+    // Query types (used to communicate with GUI)
+    // N.B. These must not be changed, as they are used in the JMX files
+    static final String SELECT   = "Select Statement"; // $NON-NLS-1$
+    static final String UPDATE   = "Update Statement"; // $NON-NLS-1$
+    static final String CALLABLE = "Callable Statement"; // $NON-NLS-1$
+    static final String PREPARED_SELECT = "Prepared Select Statement"; // $NON-NLS-1$
+    static final String PREPARED_UPDATE = "Prepared Update Statement"; // $NON-NLS-1$
+    static final String COMMIT   = "Commit"; // $NON-NLS-1$
+    static final String ROLLBACK = "Rollback"; // $NON-NLS-1$
+    static final String AUTOCOMMIT_FALSE = "AutoCommit(false)"; // $NON-NLS-1$
+    static final String AUTOCOMMIT_TRUE  = "AutoCommit(true)"; // $NON-NLS-1$
+
+    private String query = ""; // $NON-NLS-1$
+
+    private String dataSource = ""; // $NON-NLS-1$
+
+    private boolean collectDiagnostics = false;
+
+    private String queryType = SELECT;
+    private String queryArguments = ""; // $NON-NLS-1$
+    private String queryArgumentsTypes = ""; // $NON-NLS-1$
+    private String variableNames = ""; // $NON-NLS-1$
+    private String resultVariable = "";
+
+    /**
+     *  Cache of PreparedStatements stored in a per-connection basis. Each entry of this
+     *  cache is another Map mapping the statement string to the actual PreparedStatement.
+     *  The cache has a fixed size of MAX_ENTRIES and it will throw away all PreparedStatements
+     *  from the least recently used connections.
+     */
+    private static final Map<Connection, Map<String, PreparedStatement>> perConnCache =
+        new LinkedHashMap<Connection, Map<String, PreparedStatement>>(MAX_ENTRIES){
+        private static final long serialVersionUID = 1L;
+        @Override
+        protected boolean removeEldestEntry(Map.Entry<Connection, Map<String, PreparedStatement>> arg0) {
+            if (size() > MAX_ENTRIES) {
+                final  Map<String, PreparedStatement> value = arg0.getValue();
+                closeAllStatements(value.values());
+                return true;
+            }
+            return false;
+        }
+    };
+
+    /**
+     * Creates a JDBCSampler.
+     */
+    protected AbstractJdbcTestElement() {
+    }
+    
+    /**
+     * Execute the test element.
+     * 
+     * @param res a {@link SampleResult} in case the test should sample; <code>null</code> if only execution is requested
+     * @throws UnsupportedOperationException if the user provided incorrect query type 
+     */
+    protected byte[] execute(Connection conn) throws SQLException, UnsupportedEncodingException, IOException, UnsupportedOperationException {
+        log.debug("executing jdbc");
+        Statement stmt = null;
+        
+        try {
+            // Based on query return value, get results
+            String _queryType = getQueryType();
+            if (SELECT.equals(_queryType)) {
+                stmt = conn.createStatement();
+                ResultSet rs = null;
+                try {
+                    rs = stmt.executeQuery(getQuery());
+                    return getStringFromResultSet(rs).getBytes(ENCODING);
+                } finally {
+                    close(rs);
+                }
+            } else if (CALLABLE.equals(_queryType)) {
+                CallableStatement cstmt = getCallableStatement(conn);
+                int out[]=setArguments(cstmt);
+                // A CallableStatement can return more than 1 ResultSets
+                // plus a number of update counts.
+                boolean hasResultSet = cstmt.execute();
+                String sb = resultSetsToString(cstmt,hasResultSet, out);
+                return sb.getBytes(ENCODING);
+            } else if (UPDATE.equals(_queryType)) {
+                stmt = conn.createStatement();
+                stmt.executeUpdate(getQuery());
+                int updateCount = stmt.getUpdateCount();
+                String results = updateCount + " updates";
+                return results.getBytes(ENCODING);
+            } else if (PREPARED_SELECT.equals(_queryType)) {
+                PreparedStatement pstmt = getPreparedStatement(conn);
+                setArguments(pstmt);
+                boolean hasResultSet = pstmt.execute();
+                String sb = resultSetsToString(pstmt,hasResultSet,null);
+                return sb.getBytes(ENCODING);
+            } else if (PREPARED_UPDATE.equals(_queryType)) {
+                PreparedStatement pstmt = getPreparedStatement(conn);
+                setArguments(pstmt);
+                pstmt.executeUpdate();
+                String sb = resultSetsToString(pstmt,false,null);
+                return sb.getBytes(ENCODING);
+            } else if (ROLLBACK.equals(_queryType)){
+                conn.rollback();
+                return ROLLBACK.getBytes(ENCODING);
+            } else if (COMMIT.equals(_queryType)){
+                conn.commit();
+                return COMMIT.getBytes(ENCODING);
+            } else if (AUTOCOMMIT_FALSE.equals(_queryType)){
+                conn.setAutoCommit(false);
+                return AUTOCOMMIT_FALSE.getBytes(ENCODING);
+            } else if (AUTOCOMMIT_TRUE.equals(_queryType)){
+                conn.setAutoCommit(true);
+                return AUTOCOMMIT_TRUE.getBytes(ENCODING);
+            } else { // User provided incorrect query type
+                throw new UnsupportedOperationException("Unexpected query type: "+_queryType);
+            }
+        } finally {
+            close(stmt);
+        }
+    }
+
+    private String resultSetsToString(PreparedStatement pstmt, boolean result, int[] out) throws SQLException, UnsupportedEncodingException {
+        StrBuilder sb = new StrBuilder();
+        int updateCount = 0;
+        if (!result) {
+            updateCount = pstmt.getUpdateCount();
+        }
+        do {
+            if (result) {
+                ResultSet rs = null;
+                try {
+                    rs = pstmt.getResultSet();
+                    sb.append(getStringFromResultSet(rs)).append("\n"); // $NON-NLS-1$
+                } finally {
+                    close(rs);
+                }
+            } else {
+                sb.append(updateCount).append(" updates.\n");
+            }
+            result = pstmt.getMoreResults();
+            if (!result) {
+                updateCount = pstmt.getUpdateCount();
+            }
+        } while (result || (updateCount != -1));
+        if (out!=null && pstmt instanceof CallableStatement){
+            CallableStatement cs = (CallableStatement) pstmt;
+            sb.append("Output variables by position:\n");
+            for(int i=0; i < out.length; i++){
+                if (out[i]!=java.sql.Types.NULL){
+                    sb.append("[");
+                    sb.append(i+1);
+                    sb.append("] ");
+                    sb.append(cs.getObject(i+1));
+                    sb.append("\n");
+                }
+            }
+        }
+        return sb.toString();
+    }
+
+
+    private int[] setArguments(PreparedStatement pstmt) throws SQLException, IOException {
+        if (getQueryArguments().trim().length()==0) {
+            return new int[]{};
+        }
+        String[] arguments = CSVSaveService.csvSplitString(getQueryArguments(), COMMA_CHAR);
+        String[] argumentsTypes = getQueryArgumentsTypes().split(COMMA);
+        if (arguments.length != argumentsTypes.length) {
+            throw new SQLException("number of arguments ("+arguments.length+") and number of types ("+argumentsTypes.length+") are not equal");
+        }
+        int[] outputs= new int[arguments.length];
+        for (int i = 0; i < arguments.length; i++) {
+            String argument = arguments[i];
+            String argumentType = argumentsTypes[i];
+            String[] arg = argumentType.split(" ");
+            String inputOutput="";
+            if (arg.length > 1) {
+                argumentType = arg[1];
+                inputOutput=arg[0];
+            }
+            int targetSqlType = getJdbcType(argumentType);
+            try {
+                if (!OUT.equalsIgnoreCase(inputOutput)){
+                    if (argument.equals(NULL_MARKER)){
+                        pstmt.setNull(i+1, targetSqlType);
+                    } else {
+                        pstmt.setObject(i+1, argument, targetSqlType);
+                    }
+                }
+                if (OUT.equalsIgnoreCase(inputOutput)||INOUT.equalsIgnoreCase(inputOutput)) {
+                    CallableStatement cs = (CallableStatement) pstmt;
+                    cs.registerOutParameter(i+1, targetSqlType);
+                    outputs[i]=targetSqlType;
+                } else {
+                    outputs[i]=java.sql.Types.NULL; // can't have an output parameter type null
+                }
+            } catch (NullPointerException e) { // thrown by Derby JDBC (at least) if there are no "?" markers in statement
+                throw new SQLException("Could not set argument no: "+(i+1)+" - missing parameter marker?");
+            }
+        }
+        return outputs;
+    }
+
+
+    private static int getJdbcType(String jdbcType) throws SQLException {
+        Integer entry = mapJdbcNameToInt.get(jdbcType.toLowerCase(java.util.Locale.ENGLISH));
+        if (entry == null) {
+            try {
+                entry = Integer.decode(jdbcType);
+            } catch (NumberFormatException e) {
+                throw new SQLException("Invalid data type: "+jdbcType);
+            }
+        }
+        return (entry).intValue();
+    }
+
+
+    private CallableStatement getCallableStatement(Connection conn) throws SQLException {
+        return (CallableStatement) getPreparedStatement(conn,true);
+
+    }
+    private PreparedStatement getPreparedStatement(Connection conn) throws SQLException {
+        return getPreparedStatement(conn,false);
+    }
+
+    private PreparedStatement getPreparedStatement(Connection conn, boolean callable) throws SQLException {
+        Map<String, PreparedStatement> preparedStatementMap = perConnCache.get(conn);
+        if (null == preparedStatementMap ) {
+            // MRU PreparedStatements cache.
+            preparedStatementMap = new LinkedHashMap<String, PreparedStatement>(MAX_ENTRIES) {
+                private static final long serialVersionUID = 240L;
+
+                @Override
+                protected boolean removeEldestEntry(Map.Entry<String, PreparedStatement> arg0) {
+                    final int theSize = size();
+                    if (theSize > MAX_ENTRIES) {
+                        Object value = arg0.getValue();
+                        if (value instanceof PreparedStatement) {
+                            PreparedStatement pstmt = (PreparedStatement) value;
+                            close(pstmt);
+                        }
+                        return true;
+                    }
+                    return false;
+                }
+            };
+            perConnCache.put(conn, preparedStatementMap);
+        }
+        PreparedStatement pstmt = preparedStatementMap.get(getQuery());
+        if (null == pstmt) {
+            if (callable) {
+                pstmt = conn.prepareCall(getQuery());
+            } else {
+                pstmt = conn.prepareStatement(getQuery());
+            }
+            preparedStatementMap.put(getQuery(), pstmt);
+        }
+        pstmt.clearParameters();
+        return pstmt;
+    }
+
+    private static void closeAllStatements(Collection<PreparedStatement> collection) {
+        for (PreparedStatement pstmt : collection) {
+            close(pstmt);
+        }
+    }
+
+    /**
+     * Gets a Data object from a ResultSet.
+     *
+     * @param rs
+     *            ResultSet passed in from a database query
+     * @return a Data object
+     * @throws java.sql.SQLException
+     * @throws UnsupportedEncodingException
+     */
+    private String getStringFromResultSet(ResultSet rs) throws SQLException, UnsupportedEncodingException {
+        ResultSetMetaData meta = rs.getMetaData();
+
+        StrBuilder sb = new StrBuilder();
+
+        int numColumns = meta.getColumnCount();
+        for (int i = 1; i <= numColumns; i++) {
+            sb.append(meta.getColumnName(i));
+            if (i==numColumns){
+                sb.append('\n');
+            } else {
+                sb.append('\t');
+            }
+        }
+        
+
+        JMeterVariables jmvars = getThreadContext().getVariables();
+        String varnames[] = getVariableNames().split(COMMA);
+        String resultVariable = getResultVariable().trim();
+        List<Map<String, Object> > results = null;
+        if(resultVariable.length() > 0) {
+            results = new ArrayList<Map<String,Object> >();
+            jmvars.putObject(resultVariable, results);
+        }
+        int j = 0;
+        while (rs.next()) {
+            Map<String, Object> row = null;
+            j++;
+            for (int i = 1; i <= numColumns; i++) {
+                Object o = rs.getObject(i);
+                if(results != null) {
+                    if(row == null) {
+                        row = new HashMap<String, Object>(numColumns);
+                        results.add(row);
+                    }
+                    row.put(meta.getColumnName(i), o);
+                }
+                if (o instanceof byte[]) {
+                    o = new String((byte[]) o, ENCODING);
+                }
+                sb.append(o);
+                if (i==numColumns){
+                    sb.append('\n');
+                } else {
+                    sb.append('\t');
+                }
+                if (i <= varnames.length) { // i starts at 1
+                    String name = varnames[i - 1].trim();
+                    if (name.length()>0){ // Save the value in the variable if present
+                        jmvars.put(name+UNDERSCORE+j, o == null ? null : o.toString());
+                    }
+                }
+            }
+        }
+        // Remove any additional values from previous sample
+        for(int i=0; i < varnames.length; i++){
+            String name = varnames[i].trim();
+            if (name.length()>0 && jmvars != null){
+                final String varCount = name+"_#"; // $NON-NLS-1$
+                // Get the previous count
+                String prevCount = jmvars.get(varCount);
+                if (prevCount != null){
+                    int prev = Integer.parseInt(prevCount);
+                    for (int n=j+1; n <= prev; n++ ){
+                        jmvars.remove(name+UNDERSCORE+n);
+                    }
+                }
+                jmvars.put(varCount, Integer.toString(j)); // save the current count
+            }
+        }
+
+        return sb.toString();
+    }
+
+    public static void close(Connection c) {
+        try {
+            if (c != null) {
+                c.close();
+            }
+        } catch (SQLException e) {
+            log.warn("Error closing Connection", e);
+        }
+    }
+
+    public static void close(Statement s) {
+        try {
+            if (s != null) {
+                s.close();
+            }
+        } catch (SQLException e) {
+            log.warn("Error closing Statement " + s.toString(), e);
+        }
+    }
+
+    public static void close(ResultSet rs) {
+        try {
+            if (rs != null) {
+                rs.close();
+            }
+        } catch (SQLException e) {
+            log.warn("Error closing ResultSet", e);
+        }
+    }
+
+    public String getQuery() {
+        return query;
+    }
+
+    @Override
+    public String toString() {
+        StrBuilder sb = new StrBuilder(80);
+        sb.append("["); // $NON-NLS-1$
+        sb.append(getQueryType());
+        sb.append("] "); // $NON-NLS-1$
+        sb.append(getQuery());
+        sb.append("\n");
+        sb.append(getQueryArguments());
+        sb.append("\n");
+        sb.append(getQueryArgumentsTypes());
+        return sb.toString();
+    }
+
+    /**
+     * @param query
+     *            The query to set.
+     */
+    public void setQuery(String query) {
+        this.query = query;
+    }
+
+    /**
+     * @return Returns the dataSource.
+     */
+    public String getDataSource() {
+        return dataSource;
+    }
+
+    /**
+     * @param dataSource
+     *            The dataSource to set.
+     */
+    public void setDataSource(String dataSource) {
+        this.dataSource = dataSource;
+    }
+
+    /**
+     * @return the collectDiagnostics
+     */
+    public boolean getCollectDiagnostics() {
+        return collectDiagnostics;
+    }
+
+    /**
+     * @param collectDiagnostics
+     *            the collectDiagnostics to set
+     */
+    public void setCollectDiagnostics(boolean collectDiagnostics) {
+        this.collectDiagnostics = collectDiagnostics;
+    }
+
+    /**
+     * @return Returns the queryType.
+     */
+    public String getQueryType() {
+        return queryType;
+    }
+
+    /**
+     * @param queryType The queryType to set.
+     */
+    public void setQueryType(String queryType) {
+        this.queryType = queryType;
+    }
+
+    public String getQueryArguments() {
+        return queryArguments;
+    }
+
+    public void setQueryArguments(String queryArguments) {
+        this.queryArguments = queryArguments;
+    }
+
+    public String getQueryArgumentsTypes() {
+        return queryArgumentsTypes;
+    }
+
+    public void setQueryArgumentsTypes(String queryArgumentsType) {
+        this.queryArgumentsTypes = queryArgumentsType;
+    }
+
+    /**
+     * @return the variableNames
+     */
+    public String getVariableNames() {
+        return variableNames;
+    }
+
+    /**
+     * @param variableNames the variableNames to set
+     */
+    public void setVariableNames(String variableNames) {
+        this.variableNames = variableNames;
+    }
+
+    /**
+     * @return the resultVariable
+     */
+    public String getResultVariable() {
+        return resultVariable ;
+    }
+
+    /**
+     * @param resultVariable the variable name in which results will be stored
+     */
+    public void setResultVariable(String resultVariable) {
+        this.resultVariable = resultVariable;
+    }
+    
+}
Index: src/protocol/jdbc/org/apache/jmeter/protocol/jdbc/JDBCBeanInfoSupport.java
===================================================================
--- src/protocol/jdbc/org/apache/jmeter/protocol/jdbc/JDBCBeanInfoSupport.java	(revision 0)
+++ src/protocol/jdbc/org/apache/jmeter/protocol/jdbc/JDBCBeanInfoSupport.java	(revision 0)
@@ -0,0 +1,100 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ *
+ */
+
+/*
+ * Created on May 16, 2004
+ *
+ */
+package org.apache.jmeter.protocol.jdbc;
+
+import java.beans.PropertyDescriptor;
+
+import org.apache.jmeter.testbeans.BeanInfoSupport;
+import org.apache.jmeter.testbeans.gui.TextAreaEditor;
+
+public abstract class JDBCBeanInfoSupport extends BeanInfoSupport {
+
+    /**
+     *
+     */
+    public JDBCBeanInfoSupport(Class<?> beanClass) {
+        super(beanClass);
+
+        createPropertyGroup("varName", // $NON-NLS-1$
+                new String[]{"dataSource" }); // $NON-NLS-1$
+
+        createPropertyGroup("diagnostics", // $NON-NLS-1$
+                new String[] { "collectDiagnostics" }); // $NON-NLS-1$
+
+        createPropertyGroup("sql", // $NON-NLS-1$
+                new String[] {
+                "queryType", // $NON-NLS-1$
+                "query", // $NON-NLS-1$
+                "queryArguments", // $NON-NLS-1$
+                "queryArgumentsTypes", // $NON-NLS-1$
+                "variableNames", // $NON-NLS-1$
+                "resultVariable", // $NON-NLS-1$
+                });
+
+        PropertyDescriptor p = property("collectDiagnostics"); // $NON-NLS-1$
+        p.setValue(NOT_UNDEFINED, Boolean.TRUE);
+        p.setValue(DEFAULT, Boolean.FALSE);
+
+        p = property("dataSource"); // $NON-NLS-1$
+        p.setValue(NOT_UNDEFINED, Boolean.TRUE);
+        p.setValue(DEFAULT, "");
+
+        p = property("queryArguments"); // $NON-NLS-1$
+        p.setValue(NOT_UNDEFINED, Boolean.TRUE);
+        p.setValue(DEFAULT, "");
+
+        p = property("queryArgumentsTypes"); // $NON-NLS-1$
+        p.setValue(NOT_UNDEFINED, Boolean.TRUE);
+        p.setValue(DEFAULT, "");
+
+        p = property("variableNames"); // $NON-NLS-1$
+        p.setValue(NOT_UNDEFINED, Boolean.TRUE);
+        p.setValue(DEFAULT, "");
+
+        p = property("resultVariable"); // $NON-NLS-1$
+        p.setValue(NOT_UNDEFINED, Boolean.TRUE);
+        p.setValue(DEFAULT, "");
+
+        p = property("queryType"); // $NON-NLS-1$
+        p.setValue(NOT_UNDEFINED, Boolean.TRUE);
+        p.setValue(DEFAULT, AbstractJdbcTestElement.SELECT);
+        p.setValue(NOT_OTHER,Boolean.TRUE);
+        p.setValue(TAGS,new String[]{
+                AbstractJdbcTestElement.SELECT,
+                AbstractJdbcTestElement.UPDATE,
+                AbstractJdbcTestElement.CALLABLE,
+                AbstractJdbcTestElement.PREPARED_SELECT,
+                AbstractJdbcTestElement.PREPARED_UPDATE,
+                AbstractJdbcTestElement.COMMIT,
+                AbstractJdbcTestElement.ROLLBACK,
+                AbstractJdbcTestElement.AUTOCOMMIT_FALSE,
+                AbstractJdbcTestElement.AUTOCOMMIT_TRUE,
+                });
+
+        p = property("query"); // $NON-NLS-1$
+        p.setValue(NOT_UNDEFINED, Boolean.TRUE);
+        p.setValue(DEFAULT, "");
+        p.setPropertyEditorClass(TextAreaEditor.class);
+
+    }
+}
Index: src/protocol/jdbc/org/apache/jmeter/protocol/jdbc/JDBCBeanInfoSupportResources.properties
===================================================================
--- src/protocol/jdbc/org/apache/jmeter/protocol/jdbc/JDBCBeanInfoSupportResources.properties	(revision 0)
+++ src/protocol/jdbc/org/apache/jmeter/protocol/jdbc/JDBCBeanInfoSupportResources.properties	(revision 0)
@@ -0,0 +1,35 @@
+#   Licensed to the Apache Software Foundation (ASF) under one or more
+#   contributor license agreements.  See the NOTICE file distributed with
+#   this work for additional information regarding copyright ownership.
+#   The ASF licenses this file to You 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.
+
+displayName=JDBC Request
+varName.displayName=Variable Name Bound to Pool
+sql.displayName=SQL Query
+query.displayName=Query
+query.shortDescription=SQL Query to send to database
+queryType.displayName=Query Type
+queryType.shortDescription=Determines if the SQL statement should be run as a select statement or an update statement.
+dataSource.displayName=Variable Name
+dataSource.shortDescription=Name of the JMeter variable that the connection pool is bound to.
+queryArguments.displayName=Parameter values
+queryArguments.shortDescription=SQL parameter values (comma separated)
+queryArgumentsTypes.displayName=Parameter types
+queryArgumentsTypes.shortDescription=JDBC Type names from java.sql.Types. VARCHAR, INTEGER, etc. (comma separated)
+variableNames.displayName=Variable names
+variableNames.shortDescription=Output variable names for each column  (comma separated)
+resultVariable.displayName=Result variable name
+resultVariable.shortDescription=Name of the JMeter variable that stores the result set objects in a list of maps for looking up results by column name.
+diagnostics.displayName=Diagnostics
+collectDiagnostics.displayName=Collect diagnostic messages
+collectDiagnostics.shortDescription=Retrieve diagnostic messages like Warnings and other information from the database
Index: src/protocol/jdbc/org/apache/jmeter/protocol/jdbc/processor/AbstractJDBCProcessor.java
===================================================================
--- src/protocol/jdbc/org/apache/jmeter/protocol/jdbc/processor/AbstractJDBCProcessor.java	(revision 0)
+++ src/protocol/jdbc/org/apache/jmeter/protocol/jdbc/processor/AbstractJDBCProcessor.java	(revision 0)
@@ -0,0 +1,29 @@
+package org.apache.jmeter.protocol.jdbc.processor;
+
+import java.io.IOException;
+import java.sql.SQLException;
+
+import org.apache.jmeter.protocol.jdbc.AbstractJdbcTestElement;
+import org.apache.jmeter.protocol.jdbc.config.DataSourceElement;
+import org.apache.jorphan.logging.LoggingManager;
+import org.apache.log.Logger;
+
+public abstract class AbstractJDBCProcessor extends AbstractJdbcTestElement {
+    
+    private static final Logger log = LoggingManager.getLoggerForClass();
+
+    private static final long serialVersionUID = 232L;
+
+    protected void process() {
+        try {
+            execute(DataSourceElement.getConnection(getDataSource()));
+        } catch (SQLException ex) {
+            log.warn("SQL Problem in  "+ getName() + ": " + ex.toString());
+        } catch (IOException ex) {
+            log.warn("IO Problem in  "+ getName() + ": " + ex.toString());
+        } catch (UnsupportedOperationException ex) {
+            log.warn("Execution Problem in "+ getName() + ": " + ex.toString());
+        }
+    }
+
+}
Index: src/protocol/jdbc/org/apache/jmeter/protocol/jdbc/processor/JDBCPostProcessor.java
===================================================================
--- src/protocol/jdbc/org/apache/jmeter/protocol/jdbc/processor/JDBCPostProcessor.java	(revision 0)
+++ src/protocol/jdbc/org/apache/jmeter/protocol/jdbc/processor/JDBCPostProcessor.java	(revision 0)
@@ -0,0 +1,13 @@
+package org.apache.jmeter.protocol.jdbc.processor;
+
+import org.apache.jmeter.processor.PostProcessor;
+import org.apache.jmeter.testbeans.TestBean;
+
+public class JDBCPostProcessor extends AbstractJDBCProcessor implements TestBean, PostProcessor {
+
+    @Override
+    public void process() {
+        super.process();
+    }
+    
+}
Index: src/protocol/jdbc/org/apache/jmeter/protocol/jdbc/processor/JDBCPostProcessorBeanInfo.java
===================================================================
--- src/protocol/jdbc/org/apache/jmeter/protocol/jdbc/processor/JDBCPostProcessorBeanInfo.java	(revision 0)
+++ src/protocol/jdbc/org/apache/jmeter/protocol/jdbc/processor/JDBCPostProcessorBeanInfo.java	(revision 0)
@@ -0,0 +1,36 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ *
+ */
+
+/*
+ * Created on May 16, 2004
+ *
+ */
+package org.apache.jmeter.protocol.jdbc.processor;
+
+import org.apache.jmeter.protocol.jdbc.JDBCBeanInfoSupport;
+
+
+public class JDBCPostProcessorBeanInfo extends JDBCBeanInfoSupport {
+
+    /**
+     *
+     */
+    public JDBCPostProcessorBeanInfo() {
+        super(JDBCPostProcessor.class);
+    }
+}
Index: src/protocol/jdbc/org/apache/jmeter/protocol/jdbc/processor/JDBCPostProcessorResources.properties
===================================================================
--- src/protocol/jdbc/org/apache/jmeter/protocol/jdbc/processor/JDBCPostProcessorResources.properties	(revision 0)
+++ src/protocol/jdbc/org/apache/jmeter/protocol/jdbc/processor/JDBCPostProcessorResources.properties	(revision 0)
@@ -0,0 +1,16 @@
+#   Licensed to the Apache Software Foundation (ASF) under one or more
+#   contributor license agreements.  See the NOTICE file distributed with
+#   this work for additional information regarding copyright ownership.
+#   The ASF licenses this file to You 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.
+
+displayName=JDBC PostProcessor Request
\ No newline at end of file
Index: src/protocol/jdbc/org/apache/jmeter/protocol/jdbc/processor/JDBCPreProcessor.java
===================================================================
--- src/protocol/jdbc/org/apache/jmeter/protocol/jdbc/processor/JDBCPreProcessor.java	(revision 0)
+++ src/protocol/jdbc/org/apache/jmeter/protocol/jdbc/processor/JDBCPreProcessor.java	(revision 0)
@@ -0,0 +1,13 @@
+package org.apache.jmeter.protocol.jdbc.processor;
+
+import org.apache.jmeter.processor.PreProcessor;
+import org.apache.jmeter.testbeans.TestBean;
+
+public class JDBCPreProcessor extends AbstractJDBCProcessor implements TestBean, PreProcessor {
+
+    @Override
+    public void process() {
+        super.process();
+    }
+    
+}
Index: src/protocol/jdbc/org/apache/jmeter/protocol/jdbc/processor/JDBCPreProcessorBeanInfo.java
===================================================================
--- src/protocol/jdbc/org/apache/jmeter/protocol/jdbc/processor/JDBCPreProcessorBeanInfo.java	(revision 0)
+++ src/protocol/jdbc/org/apache/jmeter/protocol/jdbc/processor/JDBCPreProcessorBeanInfo.java	(revision 0)
@@ -0,0 +1,36 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ *
+ */
+
+/*
+ * Created on May 16, 2004
+ *
+ */
+package org.apache.jmeter.protocol.jdbc.processor;
+
+import org.apache.jmeter.protocol.jdbc.JDBCBeanInfoSupport;
+
+
+public class JDBCPreProcessorBeanInfo extends JDBCBeanInfoSupport {
+
+    /**
+     *
+     */
+    public JDBCPreProcessorBeanInfo() {
+        super(JDBCPreProcessor.class);
+    }
+}
Index: src/protocol/jdbc/org/apache/jmeter/protocol/jdbc/processor/JDBCPreProcessorResources.properties
===================================================================
--- src/protocol/jdbc/org/apache/jmeter/protocol/jdbc/processor/JDBCPreProcessorResources.properties	(revision 0)
+++ src/protocol/jdbc/org/apache/jmeter/protocol/jdbc/processor/JDBCPreProcessorResources.properties	(revision 0)
@@ -0,0 +1,16 @@
+#   Licensed to the Apache Software Foundation (ASF) under one or more
+#   contributor license agreements.  See the NOTICE file distributed with
+#   this work for additional information regarding copyright ownership.
+#   The ASF licenses this file to You 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.
+
+displayName=JDBC PreProcessor Request
\ No newline at end of file
Index: src/protocol/jdbc/org/apache/jmeter/protocol/jdbc/sampler/JDBCSampler.java
===================================================================
--- src/protocol/jdbc/org/apache/jmeter/protocol/jdbc/sampler/JDBCSampler.java	(revision 1197059)
+++ src/protocol/jdbc/org/apache/jmeter/protocol/jdbc/sampler/JDBCSampler.java	(working copy)
@@ -19,129 +19,29 @@
 package org.apache.jmeter.protocol.jdbc.sampler;
 
 import java.io.IOException;
-import java.io.UnsupportedEncodingException;
-import java.lang.reflect.Field;
-import java.sql.CallableStatement;
 import java.sql.Connection;
-import java.sql.PreparedStatement;
-import java.sql.ResultSet;
-import java.sql.ResultSetMetaData;
 import java.sql.SQLException;
-import java.sql.Statement;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.LinkedHashMap;
-import java.util.List;
-import java.util.Map;
 
-import org.apache.commons.lang.text.StrBuilder;
+import org.apache.jmeter.protocol.jdbc.AbstractJdbcTestElement;
 import org.apache.jmeter.protocol.jdbc.config.DataSourceElement;
-import org.apache.jmeter.samplers.AbstractSampler;
 import org.apache.jmeter.samplers.Entry;
 import org.apache.jmeter.samplers.SampleResult;
-import org.apache.jmeter.save.CSVSaveService;
+import org.apache.jmeter.samplers.Sampler;
 import org.apache.jmeter.testbeans.TestBean;
-import org.apache.jmeter.threads.JMeterVariables;
-import org.apache.jmeter.util.JMeterUtils;
 import org.apache.jorphan.logging.LoggingManager;
 import org.apache.log.Logger;
 
+import ch.infonic.jmeter.jdbc.JDBCSamplerDiagnosticListener;
+
 /**
  * A sampler which understands JDBC database requests.
  *
  */
-public class JDBCSampler extends AbstractSampler implements TestBean {
-    private static final long serialVersionUID = 233L;
-
+public class JDBCSampler extends AbstractJdbcTestElement implements Sampler, TestBean {
+    
     private static final Logger log = LoggingManager.getLoggerForClass();
 
-    private static final String COMMA = ","; // $NON-NLS-1$
-    private static final char COMMA_CHAR = ',';
-
-    private static final String UNDERSCORE = "_"; // $NON-NLS-1$
-
-    // This value is used for both the connection (perConnCache) and statement (preparedStatementMap) caches.
-    // TODO - do they have to be the same size?
-    private static final int MAX_ENTRIES =
-        JMeterUtils.getPropDefault("jdbcsampler.cachesize",200); // $NON-NLS-1$
-
-    // String used to indicate a null value
-    private static final String NULL_MARKER =
-        JMeterUtils.getPropDefault("jdbcsampler.nullmarker","]NULL["); // $NON-NLS-1$
-
-    private static final String INOUT = "INOUT"; // $NON-NLS-1$
-
-    private static final String OUT = "OUT"; // $NON-NLS-1$
-
-    // TODO - should the encoding be configurable?
-    private static final String ENCODING = "UTF-8"; // $NON-NLS-1$
-
-    // key: name (lowercase) from java.sql.Types; entry: corresponding int value
-    private static final Map<String, Integer> mapJdbcNameToInt;
-    // read-only after class init
-
-    static {
-        // based on e291. Getting the Name of a JDBC Type from javaalmanac.com
-        // http://javaalmanac.com/egs/java.sql/JdbcInt2Str.html
-        mapJdbcNameToInt = new HashMap<String, Integer>();
-
-        //Get all fields in java.sql.Types and store the corresponding int values
-        Field[] fields = java.sql.Types.class.getFields();
-        for (int i=0; i<fields.length; i++) {
-            try {
-                String name = fields[i].getName();
-                Integer value = (Integer)fields[i].get(null);
-                mapJdbcNameToInt.put(name.toLowerCase(java.util.Locale.ENGLISH),value);
-            } catch (IllegalAccessException e) {
-                throw new RuntimeException(e); // should not happen
-            }
-        }
-    }
-
-    // Query types (used to communicate with GUI)
-    // N.B. These must not be changed, as they are used in the JMX files
-    static final String SELECT   = "Select Statement"; // $NON-NLS-1$
-    static final String UPDATE   = "Update Statement"; // $NON-NLS-1$
-    static final String CALLABLE = "Callable Statement"; // $NON-NLS-1$
-    static final String PREPARED_SELECT = "Prepared Select Statement"; // $NON-NLS-1$
-    static final String PREPARED_UPDATE = "Prepared Update Statement"; // $NON-NLS-1$
-    static final String COMMIT   = "Commit"; // $NON-NLS-1$
-    static final String ROLLBACK = "Rollback"; // $NON-NLS-1$
-    static final String AUTOCOMMIT_FALSE = "AutoCommit(false)"; // $NON-NLS-1$
-    static final String AUTOCOMMIT_TRUE  = "AutoCommit(true)"; // $NON-NLS-1$
-
-    private String query = ""; // $NON-NLS-1$
-
-    private String dataSource = ""; // $NON-NLS-1$
-
-    private String queryType = SELECT;
-    private String queryArguments = ""; // $NON-NLS-1$
-    private String queryArgumentsTypes = ""; // $NON-NLS-1$
-    private String variableNames = ""; // $NON-NLS-1$
-    private String resultVariable = "";
-
     /**
-     *  Cache of PreparedStatements stored in a per-connection basis. Each entry of this
-     *  cache is another Map mapping the statement string to the actual PreparedStatement.
-     *  The cache has a fixed size of MAX_ENTRIES and it will throw away all PreparedStatements
-     *  from the least recently used connections.
-     */
-    private static final Map<Connection, Map<String, PreparedStatement>> perConnCache =
-        new LinkedHashMap<Connection, Map<String, PreparedStatement>>(MAX_ENTRIES){
-        private static final long serialVersionUID = 1L;
-        @Override
-        protected boolean removeEldestEntry(Map.Entry<Connection, Map<String, PreparedStatement>> arg0) {
-            if (size() > MAX_ENTRIES) {
-                final  Map<String, PreparedStatement> value = arg0.getValue();
-                closeAllStatements(value.values());
-                return true;
-            }
-            return false;
-        }
-    };
-
-    /**
      * Creates a JDBCSampler.
      */
     public JDBCSampler() {
@@ -165,7 +65,8 @@
 
         res.sampleStart();
         Connection conn = null;
-        Statement stmt = null;
+        JDBCSamplerDiagnosticListener diagnosticListener = getCollectDiagnostics() ? new JDBCSamplerDiagnosticListener()
+                : null;
 
         try {
 
@@ -175,68 +76,17 @@
                 res.latencyEnd(); // use latency to measure connection time
             }
             res.setResponseHeaders(conn.toString());
+            res.setResponseData(execute(conn));
 
-            // Based on query return value, get results
-            String _queryType = getQueryType();
-            if (SELECT.equals(_queryType)) {
-                stmt = conn.createStatement();
-                ResultSet rs = null;
-                try {
-                    rs = stmt.executeQuery(getQuery());
-                    res.setResponseData(getStringFromResultSet(rs).getBytes(ENCODING));
-                } finally {
-                    close(rs);
-                }
-            } else if (CALLABLE.equals(_queryType)) {
-                CallableStatement cstmt = getCallableStatement(conn);
-                int out[]=setArguments(cstmt);
-                // A CallableStatement can return more than 1 ResultSets
-                // plus a number of update counts.
-                boolean hasResultSet = cstmt.execute();
-                String sb = resultSetsToString(cstmt,hasResultSet, out);
-                res.setResponseData(sb.getBytes(ENCODING));
-            } else if (UPDATE.equals(_queryType)) {
-                stmt = conn.createStatement();
-                stmt.executeUpdate(getQuery());
-                int updateCount = stmt.getUpdateCount();
-                String results = updateCount + " updates";
-                res.setResponseData(results.getBytes(ENCODING));
-            } else if (PREPARED_SELECT.equals(_queryType)) {
-                PreparedStatement pstmt = getPreparedStatement(conn);
-                setArguments(pstmt);
-                boolean hasResultSet = pstmt.execute();
-                String sb = resultSetsToString(pstmt,hasResultSet,null);
-                res.setResponseData(sb.getBytes(ENCODING));
-            } else if (PREPARED_UPDATE.equals(_queryType)) {
-                PreparedStatement pstmt = getPreparedStatement(conn);
-                setArguments(pstmt);
-                pstmt.executeUpdate();
-                String sb = resultSetsToString(pstmt,false,null);
-                res.setResponseData(sb.getBytes(ENCODING));
-            } else if (ROLLBACK.equals(_queryType)){
-                conn.rollback();
-                res.setResponseData(ROLLBACK.getBytes(ENCODING));
-            } else if (COMMIT.equals(_queryType)){
-                conn.commit();
-                res.setResponseData(COMMIT.getBytes(ENCODING));
-            } else if (AUTOCOMMIT_FALSE.equals(_queryType)){
-                conn.setAutoCommit(false);
-                res.setResponseData(AUTOCOMMIT_FALSE.getBytes(ENCODING));
-            } else if (AUTOCOMMIT_TRUE.equals(_queryType)){
-                conn.setAutoCommit(true);
-                res.setResponseData(AUTOCOMMIT_TRUE.getBytes(ENCODING));
-            } else { // User provided incorrect query type
-                String results="Unexpected query type: "+_queryType;
-                res.setResponseMessage(results);
-                res.setSuccessful(false);
-            }
-
         } catch (SQLException ex) {
             final String errCode = Integer.toString(ex.getErrorCode());
             res.setResponseMessage(ex.toString());
             res.setResponseCode(ex.getSQLState()+ " " +errCode);
             res.setSuccessful(false);
-        } catch (UnsupportedEncodingException ex) {
+            if (diagnosticListener != null) {
+                res.setResponseData(diagnosticListener.getDiagnosticMessages(), ENCODING);
+            }
+        } catch (UnsupportedOperationException ex) {
             res.setResponseMessage(ex.toString());
             res.setResponseCode("000"); // TODO - is this correct?
             res.setSuccessful(false);
@@ -245,7 +95,9 @@
             res.setResponseCode("000"); // TODO - is this correct?
             res.setSuccessful(false);
         } finally {
-            close(stmt);
+            if (diagnosticListener != null) {
+                diagnosticListener.detach();
+            }
             close(conn);
         }
 
@@ -253,363 +105,4 @@
         res.sampleEnd();
         return res;
     }
-
-    private String resultSetsToString(PreparedStatement pstmt, boolean result, int[] out) throws SQLException, UnsupportedEncodingException {
-        StrBuilder sb = new StrBuilder();
-        int updateCount = 0;
-        if (!result) {
-            updateCount = pstmt.getUpdateCount();
-        }
-        do {
-            if (result) {
-                ResultSet rs = null;
-                try {
-                    rs = pstmt.getResultSet();
-                    sb.append(getStringFromResultSet(rs)).append("\n"); // $NON-NLS-1$
-                } finally {
-                    close(rs);
-                }
-            } else {
-                sb.append(updateCount).append(" updates.\n");
-            }
-            result = pstmt.getMoreResults();
-            if (!result) {
-                updateCount = pstmt.getUpdateCount();
-            }
-        } while (result || (updateCount != -1));
-        if (out!=null && pstmt instanceof CallableStatement){
-            CallableStatement cs = (CallableStatement) pstmt;
-            sb.append("Output variables by position:\n");
-            for(int i=0; i < out.length; i++){
-                if (out[i]!=java.sql.Types.NULL){
-                    sb.append("[");
-                    sb.append(i+1);
-                    sb.append("] ");
-                    sb.append(cs.getObject(i+1));
-                    sb.append("\n");
-                }
-            }
-        }
-        return sb.toString();
-    }
-
-
-    private int[] setArguments(PreparedStatement pstmt) throws SQLException, IOException {
-        if (getQueryArguments().trim().length()==0) {
-            return new int[]{};
-        }
-        String[] arguments = CSVSaveService.csvSplitString(getQueryArguments(), COMMA_CHAR);
-        String[] argumentsTypes = getQueryArgumentsTypes().split(COMMA);
-        if (arguments.length != argumentsTypes.length) {
-            throw new SQLException("number of arguments ("+arguments.length+") and number of types ("+argumentsTypes.length+") are not equal");
-        }
-        int[] outputs= new int[arguments.length];
-        for (int i = 0; i < arguments.length; i++) {
-            String argument = arguments[i];
-            String argumentType = argumentsTypes[i];
-            String[] arg = argumentType.split(" ");
-            String inputOutput="";
-            if (arg.length > 1) {
-                argumentType = arg[1];
-                inputOutput=arg[0];
-            }
-            int targetSqlType = getJdbcType(argumentType);
-            try {
-                if (!OUT.equalsIgnoreCase(inputOutput)){
-                    if (argument.equals(NULL_MARKER)){
-                        pstmt.setNull(i+1, targetSqlType);
-                    } else {
-                        pstmt.setObject(i+1, argument, targetSqlType);
-                    }
-                }
-                if (OUT.equalsIgnoreCase(inputOutput)||INOUT.equalsIgnoreCase(inputOutput)) {
-                    CallableStatement cs = (CallableStatement) pstmt;
-                    cs.registerOutParameter(i+1, targetSqlType);
-                    outputs[i]=targetSqlType;
-                } else {
-                    outputs[i]=java.sql.Types.NULL; // can't have an output parameter type null
-                }
-            } catch (NullPointerException e) { // thrown by Derby JDBC (at least) if there are no "?" markers in statement
-                throw new SQLException("Could not set argument no: "+(i+1)+" - missing parameter marker?");
-            }
-        }
-        return outputs;
-    }
-
-
-    private static int getJdbcType(String jdbcType) throws SQLException {
-        Integer entry = mapJdbcNameToInt.get(jdbcType.toLowerCase(java.util.Locale.ENGLISH));
-        if (entry == null) {
-            try {
-                entry = Integer.decode(jdbcType);
-            } catch (NumberFormatException e) {
-                throw new SQLException("Invalid data type: "+jdbcType);
-            }
-        }
-        return (entry).intValue();
-    }
-
-
-    private CallableStatement getCallableStatement(Connection conn) throws SQLException {
-        return (CallableStatement) getPreparedStatement(conn,true);
-
-    }
-    private PreparedStatement getPreparedStatement(Connection conn) throws SQLException {
-        return getPreparedStatement(conn,false);
-    }
-
-    private PreparedStatement getPreparedStatement(Connection conn, boolean callable) throws SQLException {
-        Map<String, PreparedStatement> preparedStatementMap = perConnCache.get(conn);
-        if (null == preparedStatementMap ) {
-            // MRU PreparedStatements cache.
-            preparedStatementMap = new LinkedHashMap<String, PreparedStatement>(MAX_ENTRIES) {
-                private static final long serialVersionUID = 240L;
-
-                @Override
-                protected boolean removeEldestEntry(Map.Entry<String, PreparedStatement> arg0) {
-                    final int theSize = size();
-                    if (theSize > MAX_ENTRIES) {
-                        Object value = arg0.getValue();
-                        if (value instanceof PreparedStatement) {
-                            PreparedStatement pstmt = (PreparedStatement) value;
-                            close(pstmt);
-                        }
-                        return true;
-                    }
-                    return false;
-                }
-            };
-            perConnCache.put(conn, preparedStatementMap);
-        }
-        PreparedStatement pstmt = preparedStatementMap.get(getQuery());
-        if (null == pstmt) {
-            if (callable) {
-                pstmt = conn.prepareCall(getQuery());
-            } else {
-                pstmt = conn.prepareStatement(getQuery());
-            }
-            preparedStatementMap.put(getQuery(), pstmt);
-        }
-        pstmt.clearParameters();
-        return pstmt;
-    }
-
-    private static void closeAllStatements(Collection<PreparedStatement> collection) {
-        for (PreparedStatement pstmt : collection) {
-            close(pstmt);
-        }
-    }
-
-    /**
-     * Gets a Data object from a ResultSet.
-     *
-     * @param rs
-     *            ResultSet passed in from a database query
-     * @return a Data object
-     * @throws java.sql.SQLException
-     * @throws UnsupportedEncodingException
-     */
-    private String getStringFromResultSet(ResultSet rs) throws SQLException, UnsupportedEncodingException {
-        ResultSetMetaData meta = rs.getMetaData();
-
-        StrBuilder sb = new StrBuilder();
-
-        int numColumns = meta.getColumnCount();
-        for (int i = 1; i <= numColumns; i++) {
-            sb.append(meta.getColumnName(i));
-            if (i==numColumns){
-                sb.append('\n');
-            } else {
-                sb.append('\t');
-            }
-        }
-        
-
-        JMeterVariables jmvars = getThreadContext().getVariables();
-        String varnames[] = getVariableNames().split(COMMA);
-        String resultVariable = getResultVariable().trim();
-        List<Map<String, Object> > results = null;
-        if(resultVariable.length() > 0) {
-            results = new ArrayList<Map<String,Object> >();
-            jmvars.putObject(resultVariable, results);
-        }
-        int j = 0;
-        while (rs.next()) {
-        	Map<String, Object> row = null;
-            j++;
-            for (int i = 1; i <= numColumns; i++) {
-                Object o = rs.getObject(i);
-                if(results != null) {
-                	if(row == null) {
-                		row = new HashMap<String, Object>(numColumns);
-                		results.add(row);
-                	}
-                	row.put(meta.getColumnName(i), o);
-                }
-                if (o instanceof byte[]) {
-                    o = new String((byte[]) o, ENCODING);
-                }
-                sb.append(o);
-                if (i==numColumns){
-                    sb.append('\n');
-                } else {
-                    sb.append('\t');
-                }
-                if (i <= varnames.length) { // i starts at 1
-                    String name = varnames[i - 1].trim();
-                    if (name.length()>0){ // Save the value in the variable if present
-                        jmvars.put(name+UNDERSCORE+j, o == null ? null : o.toString());
-                    }
-                }
-            }
-        }
-        // Remove any additional values from previous sample
-        for(int i=0; i < varnames.length; i++){
-            String name = varnames[i].trim();
-            if (name.length()>0 && jmvars != null){
-                final String varCount = name+"_#"; // $NON-NLS-1$
-                // Get the previous count
-                String prevCount = jmvars.get(varCount);
-                if (prevCount != null){
-                    int prev = Integer.parseInt(prevCount);
-                    for (int n=j+1; n <= prev; n++ ){
-                        jmvars.remove(name+UNDERSCORE+n);
-                    }
-                }
-                jmvars.put(varCount, Integer.toString(j)); // save the current count
-            }
-        }
-
-        return sb.toString();
-    }
-
-    public static void close(Connection c) {
-        try {
-            if (c != null) {
-                c.close();
-            }
-        } catch (SQLException e) {
-            log.warn("Error closing Connection", e);
-        }
-    }
-
-    public static void close(Statement s) {
-        try {
-            if (s != null) {
-                s.close();
-            }
-        } catch (SQLException e) {
-            log.warn("Error closing Statement " + s.toString(), e);
-        }
-    }
-
-    public static void close(ResultSet rs) {
-        try {
-            if (rs != null) {
-                rs.close();
-            }
-        } catch (SQLException e) {
-            log.warn("Error closing ResultSet", e);
-        }
-    }
-
-    public String getQuery() {
-        return query;
-    }
-
-    @Override
-    public String toString() {
-        StrBuilder sb = new StrBuilder(80);
-        sb.append("["); // $NON-NLS-1$
-        sb.append(getQueryType());
-        sb.append("] "); // $NON-NLS-1$
-        sb.append(getQuery());
-        sb.append("\n");
-        sb.append(getQueryArguments());
-        sb.append("\n");
-        sb.append(getQueryArgumentsTypes());
-        return sb.toString();
-    }
-
-    /**
-     * @param query
-     *            The query to set.
-     */
-    public void setQuery(String query) {
-        this.query = query;
-    }
-
-    /**
-     * @return Returns the dataSource.
-     */
-    public String getDataSource() {
-        return dataSource;
-    }
-
-    /**
-     * @param dataSource
-     *            The dataSource to set.
-     */
-    public void setDataSource(String dataSource) {
-        this.dataSource = dataSource;
-    }
-
-    /**
-     * @return Returns the queryType.
-     */
-    public String getQueryType() {
-        return queryType;
-    }
-
-    /**
-     * @param queryType The queryType to set.
-     */
-    public void setQueryType(String queryType) {
-        this.queryType = queryType;
-    }
-
-    public String getQueryArguments() {
-        return queryArguments;
-    }
-
-    public void setQueryArguments(String queryArguments) {
-        this.queryArguments = queryArguments;
-    }
-
-    public String getQueryArgumentsTypes() {
-        return queryArgumentsTypes;
-    }
-
-    public void setQueryArgumentsTypes(String queryArgumentsType) {
-        this.queryArgumentsTypes = queryArgumentsType;
-    }
-
-    /**
-     * @return the variableNames
-     */
-    public String getVariableNames() {
-        return variableNames;
-    }
-
-    /**
-     * @param variableNames the variableNames to set
-     */
-    public void setVariableNames(String variableNames) {
-        this.variableNames = variableNames;
-    }
-
-    /**
-     * @return the resultVariable
-     */
-	public String getResultVariable() {
-		return resultVariable ;
-	}
-
-    /**
-     * @param resultVariable the variable name in which results will be stored
-     */
-	public void setResultVariable(String resultVariable) {
-		this.resultVariable = resultVariable;
-	}
-    
 }
Index: src/protocol/jdbc/org/apache/jmeter/protocol/jdbc/sampler/JDBCSamplerBeanInfo.java
===================================================================
--- src/protocol/jdbc/org/apache/jmeter/protocol/jdbc/sampler/JDBCSamplerBeanInfo.java	(revision 1197059)
+++ src/protocol/jdbc/org/apache/jmeter/protocol/jdbc/sampler/JDBCSamplerBeanInfo.java	(working copy)
@@ -22,72 +22,15 @@
  */
 package org.apache.jmeter.protocol.jdbc.sampler;
 
-import java.beans.PropertyDescriptor;
+import org.apache.jmeter.protocol.jdbc.JDBCBeanInfoSupport;
 
-import org.apache.jmeter.testbeans.BeanInfoSupport;
-import org.apache.jmeter.testbeans.gui.TextAreaEditor;
 
-public class JDBCSamplerBeanInfo extends BeanInfoSupport {
+public class JDBCSamplerBeanInfo extends JDBCBeanInfoSupport {
 
     /**
      *
      */
     public JDBCSamplerBeanInfo() {
         super(JDBCSampler.class);
-
-        createPropertyGroup("varName", // $NON-NLS-1$
-                new String[]{"dataSource" }); // $NON-NLS-1$
-
-        createPropertyGroup("sql", // $NON-NLS-1$
-                new String[] {
-                "queryType", // $NON-NLS-1$
-                "query", // $NON-NLS-1$
-                "queryArguments", // $NON-NLS-1$
-                "queryArgumentsTypes", // $NON-NLS-1$
-                "variableNames", // $NON-NLS-1$
-                "resultVariable", // $NON-NLS-1$
-                });
-
-        PropertyDescriptor p = property("dataSource"); // $NON-NLS-1$
-        p.setValue(NOT_UNDEFINED, Boolean.TRUE);
-        p.setValue(DEFAULT, "");
-
-        p = property("queryArguments"); // $NON-NLS-1$
-        p.setValue(NOT_UNDEFINED, Boolean.TRUE);
-        p.setValue(DEFAULT, "");
-
-        p = property("queryArgumentsTypes"); // $NON-NLS-1$
-        p.setValue(NOT_UNDEFINED, Boolean.TRUE);
-        p.setValue(DEFAULT, "");
-
-        p = property("variableNames"); // $NON-NLS-1$
-        p.setValue(NOT_UNDEFINED, Boolean.TRUE);
-        p.setValue(DEFAULT, "");
-
-        p = property("resultVariable"); // $NON-NLS-1$
-        p.setValue(NOT_UNDEFINED, Boolean.TRUE);
-        p.setValue(DEFAULT, "");
-
-        p = property("queryType"); // $NON-NLS-1$
-        p.setValue(NOT_UNDEFINED, Boolean.TRUE);
-        p.setValue(DEFAULT, JDBCSampler.SELECT);
-        p.setValue(NOT_OTHER,Boolean.TRUE);
-        p.setValue(TAGS,new String[]{
-                JDBCSampler.SELECT,
-                JDBCSampler.UPDATE,
-                JDBCSampler.CALLABLE,
-                JDBCSampler.PREPARED_SELECT,
-                JDBCSampler.PREPARED_UPDATE,
-                JDBCSampler.COMMIT,
-                JDBCSampler.ROLLBACK,
-                JDBCSampler.AUTOCOMMIT_FALSE,
-                JDBCSampler.AUTOCOMMIT_TRUE,
-                });
-
-        p = property("query"); // $NON-NLS-1$
-        p.setValue(NOT_UNDEFINED, Boolean.TRUE);
-        p.setValue(DEFAULT, "");
-        p.setPropertyEditorClass(TextAreaEditor.class);
-
     }
 }
Index: src/protocol/jdbc/org/apache/jmeter/protocol/jdbc/sampler/JDBCSamplerResources.properties
===================================================================
--- src/protocol/jdbc/org/apache/jmeter/protocol/jdbc/sampler/JDBCSamplerResources.properties	(revision 1197059)
+++ src/protocol/jdbc/org/apache/jmeter/protocol/jdbc/sampler/JDBCSamplerResources.properties	(working copy)
@@ -14,20 +14,3 @@
 #   limitations under the License.
 
 displayName=JDBC Request
-varName.displayName=Variable Name Bound to Pool
-sql.displayName=SQL Query
-query.displayName=Query
-query.shortDescription=SQL Query to send to database
-queryType.displayName=Query Type
-queryType.shortDescription=Determines if the SQL statement should be run as a select statement or an update statement.
-dataSource.displayName=Variable Name
-dataSource.shortDescription=Name of the JMeter variable that the connection pool is bound to.
-queryArguments.displayName=Parameter values
-queryArguments.shortDescription=SQL parameter values (comma separated)
-queryArgumentsTypes.displayName=Parameter types
-queryArgumentsTypes.shortDescription=JDBC Type names from java.sql.Types. VARCHAR, INTEGER, etc. (comma separated)
-variableNames.displayName=Variable names
-variableNames.shortDescription=Output variable names for each column  (comma separated)
-resultVariable.displayName=Result variable name
-resultVariable.shortDescription=Name of the JMeter variable that stores the result set objects in a list of maps for looking up results by column name.
-
