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.sql;
018
019 import java.sql.PreparedStatement;
020 import java.sql.SQLException;
021 import java.util.Iterator;
022 import java.util.List;
023 import java.util.Map;
024
025 import org.apache.camel.Exchange;
026 import org.apache.camel.impl.DefaultProducer;
027 import org.springframework.dao.DataAccessException;
028 import org.springframework.jdbc.core.ColumnMapRowMapper;
029 import org.springframework.jdbc.core.JdbcTemplate;
030 import org.springframework.jdbc.core.PreparedStatementCallback;
031 import org.springframework.jdbc.core.RowMapperResultSetExtractor;
032
033 public class SqlProducer extends DefaultProducer {
034 private String query;
035 private JdbcTemplate jdbcTemplate;
036
037 public SqlProducer(SqlEndpoint endpoint, String query, JdbcTemplate jdbcTemplate) {
038 super(endpoint);
039 this.jdbcTemplate = jdbcTemplate;
040 this.query = query;
041 }
042
043 public void process(final Exchange exchange) throws Exception {
044 String queryHeader = exchange.getIn().getHeader(SqlConstants.SQL_QUERY, String.class);
045 jdbcTemplate.execute(queryHeader != null ? queryHeader : query, new PreparedStatementCallback<Map<?, ?>>() {
046 public Map<?, ?> doInPreparedStatement(PreparedStatement ps) throws SQLException, DataAccessException {
047 int argNumber = 1;
048
049 // number of parameters must match
050 int expected = ps.getParameterMetaData().getParameterCount();
051
052 if (expected > 0 && exchange.getIn().getBody() != null) {
053 Iterator<?> iterator = exchange.getIn().getBody(Iterator.class);
054 while (iterator != null && iterator.hasNext()) {
055 Object value = iterator.next();
056 log.trace("Setting parameter #{} with value: {}", argNumber, value);
057 ps.setObject(argNumber, value);
058 argNumber++;
059 }
060 }
061
062 if (argNumber - 1 != expected) {
063 throw new SQLException("Number of parameters mismatch. Expected: " + expected + ", was:" + (argNumber - 1));
064 }
065
066 boolean isResultSet = ps.execute();
067
068 if (isResultSet) {
069 RowMapperResultSetExtractor<Map<String, Object>> mapper = new RowMapperResultSetExtractor<Map<String, Object>>(new ColumnMapRowMapper());
070 List<Map<String, Object>> result = mapper.extractData(ps.getResultSet());
071 exchange.getOut().setBody(result);
072 exchange.getIn().setHeader(SqlConstants.SQL_ROW_COUNT, result.size());
073 // preserve headers
074 exchange.getOut().setHeaders(exchange.getIn().getHeaders());
075 } else {
076 exchange.getIn().setHeader(SqlConstants.SQL_UPDATE_COUNT, ps.getUpdateCount());
077 }
078
079 // data is set on exchange so return null
080 return null;
081 }
082 });
083 }
084
085 }