001    /**
002     * Licensed to the Apache Software Foundation (ASF) under one or more
003     * contributor license agreements.  See the NOTICE file distributed with
004     * this work for additional information regarding copyright ownership.
005     * The ASF licenses this file to You under the Apache License, Version 2.0
006     * (the "License"); you may not use this file except in compliance with
007     * the License.  You may obtain a copy of the License at
008     *
009     *      http://www.apache.org/licenses/LICENSE-2.0
010     *
011     * Unless required by applicable law or agreed to in writing, software
012     * distributed under the License is distributed on an "AS IS" BASIS,
013     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014     * See the License for the specific language governing permissions and
015     * limitations under the License.
016     */
017    package org.apache.camel.component.jdbc;
018    
019    import java.sql.Connection;
020    import java.sql.ResultSet;
021    import java.sql.ResultSetMetaData;
022    import java.sql.SQLException;
023    import java.sql.Statement;
024    import java.util.ArrayList;
025    import java.util.HashMap;
026    import java.util.List;
027    import java.util.Map;
028    
029    import javax.sql.DataSource;
030    
031    import org.apache.camel.Exchange;
032    import org.apache.camel.impl.DefaultProducer;
033    import org.apache.camel.util.IntrospectionSupport;
034    import org.apache.camel.util.ObjectHelper;
035    import org.apache.commons.logging.Log;
036    import org.apache.commons.logging.LogFactory;
037    
038    /**
039     * @version $Revision: 748495 $
040     */
041    public class JdbcProducer extends DefaultProducer {
042        private static final transient Log LOG = LogFactory.getLog(JdbcProducer.class);
043        private DataSource dataSource;
044        private int readSize;
045    
046        public JdbcProducer(JdbcEndpoint endpoint, DataSource dataSource, int readSize) throws Exception {
047            super(endpoint);
048            this.dataSource = dataSource;
049            this.readSize = readSize;
050        }
051    
052        /**
053         * Execute sql of exchange and set results on output
054         */
055        public void process(Exchange exchange) throws Exception {
056            String sql = exchange.getIn().getBody(String.class);
057            Connection conn = null;
058            Statement stmt = null;
059            ResultSet rs = null;
060            try {
061                conn = dataSource.getConnection();
062                stmt = conn.createStatement();
063                if (LOG.isDebugEnabled()) {
064                    LOG.debug("Executing JDBC statement: " + sql);
065                }
066                if (stmt.execute(sql)) {
067                    rs = stmt.getResultSet();
068                    setResultSet(exchange, rs);
069                } else {
070                    int updateCount = stmt.getUpdateCount();
071                    exchange.getOut().setHeader(JdbcConstants.JDBC_UPDATE_COUNT, updateCount);
072                }
073            } finally {
074                try {
075                    if (rs != null) {
076                        rs.close();
077                    }
078                    if (stmt != null) {
079                        stmt.close();
080                    }
081                    if (conn != null) {
082                        conn.close();
083                    }
084                } catch (SQLException e) {
085                    LOG.warn("Error closing JDBC resource: " + e, e);
086                }
087            }
088        }
089    
090        /**
091         * Sets the result from the ResultSet to the Exchange as its OUT body.
092         */
093        protected void setResultSet(Exchange exchange, ResultSet rs) throws SQLException {
094            ResultSetMetaData meta = rs.getMetaData();
095    
096            int count = meta.getColumnCount();
097            List<Map<String, Object>> data = new ArrayList<Map<String, Object>>();
098            int rowNumber = 0;
099            while (rs.next() && (readSize == 0 || rowNumber < readSize)) {
100                Map<String, Object> row = new HashMap<String, Object>();
101                for (int i = 0; i < count; i++) {
102                    int columnNumber = i + 1;
103                    String columnName = meta.getColumnName(columnNumber);
104                    row.put(columnName, rs.getObject(columnName));
105                }
106                data.add(row);
107                rowNumber++;
108            }
109            exchange.getOut().setHeader(JdbcConstants.JDBC_ROW_COUNT, rowNumber);
110            exchange.getOut().setBody(data);
111        }
112    
113    }