You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by da...@apache.org on 2016/01/14 17:41:41 UTC
[3/3] camel git commit: CAMEL-4725: Batch support and other options
for Producer.
CAMEL-4725: Batch support and other options for Producer.
Project: http://git-wip-us.apache.org/repos/asf/camel/repo
Commit: http://git-wip-us.apache.org/repos/asf/camel/commit/df5944fa
Tree: http://git-wip-us.apache.org/repos/asf/camel/tree/df5944fa
Diff: http://git-wip-us.apache.org/repos/asf/camel/diff/df5944fa
Branch: refs/heads/master
Commit: df5944fad4e3100e054f1dda09c60ebc80274e15
Parents: f511606
Author: Sami Nurminen <sn...@gmail.com>
Authored: Tue Jan 12 23:12:18 2016 +0200
Committer: Claus Ibsen <da...@apache.org>
Committed: Thu Jan 14 16:34:09 2016 +0000
----------------------------------------------------------------------
.../BatchCallableStatementCreatorFactory.java | 100 +++
.../sql/stored/CallableStatementWrapper.java | 128 +++
.../stored/CallableStatementWrapperFactory.java | 101 +++
.../sql/stored/SqlStoredComponent.java | 28 +-
.../sql/stored/SqlStoredConstants.java | 30 +
.../component/sql/stored/SqlStoredEndpoint.java | 128 +--
.../component/sql/stored/SqlStoredProducer.java | 95 ++-
.../component/sql/stored/StamentWrapper.java | 42 +
.../sql/stored/TemplateStoredProcedure.java | 83 ++
.../sql/stored/WrapperExecuteCallback.java | 26 +
.../sql/stored/template/TemplateParser.java | 45 +
.../template/TemplateStoredProcedure.java | 74 --
.../TemplateStoredProcedureFactory.java | 76 --
.../sql/stored/template/ast/InputParameter.java | 52 +-
.../sql/stored/template/ast/ParseHelper.java | 51 +-
.../sql/stored/template/ast/Template.java | 17 +-
.../sql/stored/template/ast/ValueExtractor.java | 29 +
.../template/generated/ParseException.java | 315 ++++---
.../stored/template/generated/SSPTParser.java | 542 ++++++------
.../template/generated/SSPTParserConstants.java | 56 +-
.../generated/SSPTParserTokenManager.java | 695 +++++++--------
.../template/generated/SimpleCharStream.java | 854 +++++++++----------
.../sql/stored/template/generated/Token.java | 228 +++--
.../template/generated/TokenMgrError.java | 241 +++---
.../sql/stored/template/grammar/sspt.jj | 37 +-
.../stored/CallableStatementWrapperTest.java | 99 +++
.../camel/component/sql/stored/ParserTest.java | 39 +-
.../component/sql/stored/ProducerBatchTest.java | 95 +++
.../component/sql/stored/ProducerTest.java | 7 +-
.../ProducerUseMessageBodyForTemplateTest.java | 85 ++
.../sql/stored/SqlStoredDataSourceTest.java | 80 ++
.../component/sql/stored/TemplateCacheTest.java | 59 ++
.../sql/stored/TemplateStoredProcedureTest.java | 79 --
.../sql/stored/TestStoredProcedure.java | 19 +-
.../test/resources/sql/storedProcedureTest.sql | 12 +-
35 files changed, 2786 insertions(+), 1861 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/camel/blob/df5944fa/components/camel-sql/src/main/java/org/apache/camel/component/sql/stored/BatchCallableStatementCreatorFactory.java
----------------------------------------------------------------------
diff --git a/components/camel-sql/src/main/java/org/apache/camel/component/sql/stored/BatchCallableStatementCreatorFactory.java b/components/camel-sql/src/main/java/org/apache/camel/component/sql/stored/BatchCallableStatementCreatorFactory.java
new file mode 100644
index 0000000..cda2bd4
--- /dev/null
+++ b/components/camel-sql/src/main/java/org/apache/camel/component/sql/stored/BatchCallableStatementCreatorFactory.java
@@ -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.
+ */
+package org.apache.camel.component.sql.stored;
+
+import java.sql.CallableStatement;
+import java.sql.SQLException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.camel.component.sql.stored.template.ast.InputParameter;
+import org.apache.camel.component.sql.stored.template.ast.Template;
+import org.springframework.jdbc.core.CallableStatementCreator;
+import org.springframework.jdbc.core.CallableStatementCreatorFactory;
+import org.springframework.jdbc.core.SqlParameter;
+import org.springframework.jdbc.core.StatementCreatorUtils;
+
+
+public class BatchCallableStatementCreatorFactory {
+
+ final CallableStatementCreatorFactory callableStatementCreatorFactory;
+
+ final List<SqlParameter> sqlParameterList;
+
+ final Template template;
+
+
+ public BatchCallableStatementCreatorFactory(Template template) {
+ this.template = template;
+ this.sqlParameterList = createParams();
+ this.callableStatementCreatorFactory = new CallableStatementCreatorFactory(formatSql(), createParams());
+ }
+
+ public void addParameter(CallableStatement callableStatement, Map batchRow) throws SQLException {
+ int i = 1;
+ for (SqlParameter parameter : getSqlParameterList()) {
+ StatementCreatorUtils.setParameterValue(callableStatement, i, parameter, batchRow.get(parameter.getName()));
+ i++;
+ }
+ }
+
+ private String formatSql() {
+ return "{call " + this.template.getProcedureName() + "(" + repeatParameter(this.template.getParameterList()
+ .size()) + ")}";
+ }
+
+ private String repeatParameter(int size) {
+ StringBuilder ret = new StringBuilder();
+ for (int i = 0; i < size; i++) {
+ ret.append('?');
+ if (i + 1 < size) {
+ ret.append(',');
+ }
+ }
+ return ret.toString();
+ }
+
+ private List<SqlParameter> createParams() {
+ List<SqlParameter> params = new ArrayList<>();
+
+ for (Object parameter : template.getParameterList()) {
+ if (parameter instanceof InputParameter) {
+ InputParameter inputParameter = (InputParameter) parameter;
+ params.add(new SqlParameter(inputParameter.getName(), inputParameter.getSqlType()));
+
+ } else {
+ throw new UnsupportedOperationException("Only IN parameters supported by batch!");
+ }
+ }
+
+
+ return params;
+ }
+
+ public CallableStatementCreator newCallableStatementCreator(Map params) {
+ return this.callableStatementCreatorFactory.newCallableStatementCreator(params);
+ }
+
+ public List<SqlParameter> getSqlParameterList() {
+ return sqlParameterList;
+ }
+
+ public Template getTemplate() {
+ return template;
+ }
+}
http://git-wip-us.apache.org/repos/asf/camel/blob/df5944fa/components/camel-sql/src/main/java/org/apache/camel/component/sql/stored/CallableStatementWrapper.java
----------------------------------------------------------------------
diff --git a/components/camel-sql/src/main/java/org/apache/camel/component/sql/stored/CallableStatementWrapper.java b/components/camel-sql/src/main/java/org/apache/camel/component/sql/stored/CallableStatementWrapper.java
new file mode 100644
index 0000000..824f21d
--- /dev/null
+++ b/components/camel-sql/src/main/java/org/apache/camel/component/sql/stored/CallableStatementWrapper.java
@@ -0,0 +1,128 @@
+/**
+ * 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.
+ */
+package org.apache.camel.component.sql.stored;
+
+import java.sql.CallableStatement;
+import java.sql.Connection;
+import java.sql.SQLException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.camel.Exchange;
+import org.apache.camel.component.sql.stored.template.ast.InputParameter;
+import org.springframework.dao.DataAccessException;
+import org.springframework.jdbc.core.CallableStatementCallback;
+import org.springframework.jdbc.core.CallableStatementCreator;
+
+public class CallableStatementWrapper implements StamentWrapper {
+
+ final CallableStatementWrapperFactory factory;
+
+ final String template;
+
+ Map result;
+
+ List<Map> batchItems;
+
+ Integer updateCount;
+
+ BatchCallableStatementCreatorFactory batchFactory;
+
+ public CallableStatementWrapper(String template, CallableStatementWrapperFactory wrapperFactory) {
+ this.factory = wrapperFactory;
+ this.template = template;
+ }
+
+ @Override
+ public void call(final WrapperExecuteCallback cb) throws Exception {
+ cb.execute(this);
+ }
+
+
+ @Override
+ public int[] executeBatch() throws SQLException {
+
+ if (this.batchItems == null) {
+ throw new IllegalArgumentException("Batch must have at least one item");
+ }
+
+ final Iterator<Map> params = batchItems.iterator();
+
+
+ return factory.getJdbcTemplate().execute(new CallableStatementCreator() {
+ @Override
+ public CallableStatement createCallableStatement(Connection connection) throws SQLException {
+ return batchFactory.newCallableStatementCreator(params.next()).createCallableStatement(connection);
+
+ }
+ }, new CallableStatementCallback<int[]>() {
+ @Override
+ public int[] doInCallableStatement(CallableStatement callableStatement) throws SQLException, DataAccessException {
+ //add first item to batch
+ callableStatement.addBatch();
+
+ while (params.hasNext()) {
+ batchFactory.addParameter(callableStatement, params.next());
+ callableStatement.addBatch();
+ }
+ return callableStatement.executeBatch();
+ }
+ });
+ }
+
+
+ @Override
+ public Integer getUpdateCount() throws SQLException {
+ return this.updateCount;
+ }
+
+
+ @Override
+ public Object executeStatement() throws SQLException {
+ return this.result;
+ }
+
+ @Override
+ public void populateStatement(Object value, Exchange exchange) throws SQLException {
+ this.result = this.factory.getTemplateStoredProcedure(this.template).execute(exchange, value);
+ //Spring sets #update-result-1
+ this.updateCount = (Integer) this.result.get("#update-count-1");
+ }
+
+ @Override
+ public void addBatch(Object value, Exchange exchange) {
+
+ if (this.batchFactory == null) {
+ this.batchFactory = factory.getTemplateForBatch(template);
+ }
+
+ Map<String, Object> batchValues = new HashMap<>();
+ //only IN-parameters supported by template
+ for (Object param : this.batchFactory.getTemplate().getParameterList()) {
+ InputParameter inputParameter = (InputParameter) param;
+ Object paramValue = inputParameter.getValueExtractor().eval(exchange, value);
+ batchValues.put(inputParameter.getName(), paramValue);
+ }
+ if (this.batchItems == null) {
+ this.batchItems = new ArrayList<>();
+ }
+ batchItems.add(batchValues);
+ }
+}
http://git-wip-us.apache.org/repos/asf/camel/blob/df5944fa/components/camel-sql/src/main/java/org/apache/camel/component/sql/stored/CallableStatementWrapperFactory.java
----------------------------------------------------------------------
diff --git a/components/camel-sql/src/main/java/org/apache/camel/component/sql/stored/CallableStatementWrapperFactory.java b/components/camel-sql/src/main/java/org/apache/camel/component/sql/stored/CallableStatementWrapperFactory.java
new file mode 100644
index 0000000..503fdb3
--- /dev/null
+++ b/components/camel-sql/src/main/java/org/apache/camel/component/sql/stored/CallableStatementWrapperFactory.java
@@ -0,0 +1,101 @@
+/**
+ * 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.
+ */
+package org.apache.camel.component.sql.stored;
+
+import java.sql.SQLException;
+
+import org.apache.camel.component.sql.stored.template.TemplateParser;
+import org.apache.camel.support.ServiceSupport;
+import org.apache.camel.util.LRUCache;
+import org.springframework.jdbc.core.JdbcTemplate;
+
+/**
+ * Statefull class that cached template functions.
+ */
+public class CallableStatementWrapperFactory extends ServiceSupport {
+
+ public static final int TEMPLATE_CACHE_DEFAULT_SIZE = 200;
+
+ public static final int BATCH_TEMPLATE_CACHE_DEFAULT_SIZE = 200;
+
+ final JdbcTemplate jdbcTemplate;
+
+ final TemplateParser templateParser;
+
+ private final LRUCache<String, TemplateStoredProcedure> templateCache = new LRUCache<>(TEMPLATE_CACHE_DEFAULT_SIZE);
+
+ private final LRUCache<String, BatchCallableStatementCreatorFactory> batchTemplateCache = new LRUCache<>(BATCH_TEMPLATE_CACHE_DEFAULT_SIZE);
+
+ public CallableStatementWrapperFactory(JdbcTemplate jdbcTemplate, TemplateParser
+ templateParser) {
+ this.jdbcTemplate = jdbcTemplate;
+ this.templateParser = templateParser;
+ }
+
+ public StamentWrapper create(String sql) throws SQLException {
+ return new CallableStatementWrapper(sql, this);
+ }
+
+ public BatchCallableStatementCreatorFactory getTemplateForBatch(String sql) {
+ BatchCallableStatementCreatorFactory template = this.batchTemplateCache.get(sql);
+ if (template != null) {
+ return template;
+ }
+
+ template = new BatchCallableStatementCreatorFactory(templateParser.parseTemplate(sql));
+ this.batchTemplateCache.put(sql, template);
+
+ return template;
+ }
+
+ public TemplateStoredProcedure getTemplateStoredProcedure(String sql) {
+ TemplateStoredProcedure templateStoredProcedure = this.templateCache.get(sql);
+ if (templateStoredProcedure != null) {
+ return templateStoredProcedure;
+ }
+
+ templateStoredProcedure = new TemplateStoredProcedure(jdbcTemplate, templateParser.parseTemplate(sql));
+
+ this.templateCache.put(sql, templateStoredProcedure);
+
+ return templateStoredProcedure;
+ }
+
+ public JdbcTemplate getJdbcTemplate() {
+ return jdbcTemplate;
+ }
+
+ @Override
+ protected void doStart() throws Exception {
+ }
+
+ @Override
+ protected void doStop() throws Exception {
+ try {
+ // clear cache when we are stopping
+ templateCache.clear();
+ } catch (Exception ex) {
+ //noop
+ }
+ try {
+ // clear cache when we are stopping
+ batchTemplateCache.clear();
+ } catch (Exception ex) {
+ //noop
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/camel/blob/df5944fa/components/camel-sql/src/main/java/org/apache/camel/component/sql/stored/SqlStoredComponent.java
----------------------------------------------------------------------
diff --git a/components/camel-sql/src/main/java/org/apache/camel/component/sql/stored/SqlStoredComponent.java b/components/camel-sql/src/main/java/org/apache/camel/component/sql/stored/SqlStoredComponent.java
index 3391450..5444b18 100644
--- a/components/camel-sql/src/main/java/org/apache/camel/component/sql/stored/SqlStoredComponent.java
+++ b/components/camel-sql/src/main/java/org/apache/camel/component/sql/stored/SqlStoredComponent.java
@@ -21,19 +21,24 @@ import javax.sql.DataSource;
import org.apache.camel.CamelContext;
import org.apache.camel.Endpoint;
-import org.apache.camel.component.sql.stored.template.TemplateStoredProcedureFactory;
import org.apache.camel.impl.UriEndpointComponent;
-import org.apache.camel.util.CamelContextHelper;
import org.springframework.jdbc.core.JdbcTemplate;
public class SqlStoredComponent extends UriEndpointComponent {
-
private DataSource dataSource;
public SqlStoredComponent() {
super(SqlStoredEndpoint.class);
}
+ public SqlStoredComponent(Class<? extends Endpoint> endpointClass) {
+ super(endpointClass);
+ }
+
+ public SqlStoredComponent(CamelContext context) {
+ super(context, SqlStoredEndpoint.class);
+ }
+
public SqlStoredComponent(CamelContext context, Class<? extends Endpoint> endpointClass) {
super(context, endpointClass);
}
@@ -47,10 +52,6 @@ public class SqlStoredComponent extends UriEndpointComponent {
if (ds != null) {
target = ds;
}
- String dataSourceRef = getAndRemoveParameter(parameters, "dataSourceRef", String.class);
- if (target == null && dataSourceRef != null) {
- target = CamelContextHelper.mandatoryLookup(getCamelContext(), dataSourceRef, DataSource.class);
- }
if (target == null) {
// fallback and use component
target = dataSource;
@@ -59,14 +60,12 @@ public class SqlStoredComponent extends UriEndpointComponent {
throw new IllegalArgumentException("DataSource must be configured");
}
- JdbcTemplate template = new JdbcTemplate(target);
- TemplateStoredProcedureFactory factory = new TemplateStoredProcedureFactory(template);
+ JdbcTemplate jdbcTemplate = new JdbcTemplate(target);
+ String template = remaining;
- SqlStoredEndpoint answer = new SqlStoredEndpoint(uri, this);
- answer.setJdbcTemplate(template);
- answer.setTemplate(remaining);
- answer.setTemplateStoredProcedureFactory(factory);
- return answer;
+ SqlStoredEndpoint endpoint = new SqlStoredEndpoint(uri, this, jdbcTemplate);
+ endpoint.setTemplate(template);
+ return endpoint;
}
public DataSource getDataSource() {
@@ -79,5 +78,4 @@ public class SqlStoredComponent extends UriEndpointComponent {
public void setDataSource(DataSource dataSource) {
this.dataSource = dataSource;
}
-
}
http://git-wip-us.apache.org/repos/asf/camel/blob/df5944fa/components/camel-sql/src/main/java/org/apache/camel/component/sql/stored/SqlStoredConstants.java
----------------------------------------------------------------------
diff --git a/components/camel-sql/src/main/java/org/apache/camel/component/sql/stored/SqlStoredConstants.java b/components/camel-sql/src/main/java/org/apache/camel/component/sql/stored/SqlStoredConstants.java
new file mode 100644
index 0000000..801d4ea
--- /dev/null
+++ b/components/camel-sql/src/main/java/org/apache/camel/component/sql/stored/SqlStoredConstants.java
@@ -0,0 +1,30 @@
+/**
+ * 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.
+ */
+package org.apache.camel.component.sql.stored;
+
+public final class SqlStoredConstants {
+
+ public static final String SQL_STORED_TEMPLATE = "CamelSqlStoredTemplate";
+
+ public static final String SQL_STORED_PARAMETERS = "CamelSqlStoredParameters";
+
+ public static final String SQL_STORED_UPDATE_COUNT = "CamelSqlStoredUpdateCount";
+
+ private SqlStoredConstants() {
+ // Utility class
+ }
+}
http://git-wip-us.apache.org/repos/asf/camel/blob/df5944fa/components/camel-sql/src/main/java/org/apache/camel/component/sql/stored/SqlStoredEndpoint.java
----------------------------------------------------------------------
diff --git a/components/camel-sql/src/main/java/org/apache/camel/component/sql/stored/SqlStoredEndpoint.java b/components/camel-sql/src/main/java/org/apache/camel/component/sql/stored/SqlStoredEndpoint.java
index e65fa8b..7897c74 100644
--- a/components/camel-sql/src/main/java/org/apache/camel/component/sql/stored/SqlStoredEndpoint.java
+++ b/components/camel-sql/src/main/java/org/apache/camel/component/sql/stored/SqlStoredEndpoint.java
@@ -16,96 +16,128 @@
*/
package org.apache.camel.component.sql.stored;
-import org.apache.camel.Component;
-import org.apache.camel.Consumer;
-import org.apache.camel.Processor;
+import javax.sql.DataSource;
+
import org.apache.camel.Producer;
-import org.apache.camel.component.sql.stored.template.TemplateStoredProcedureFactory;
-import org.apache.camel.impl.DefaultEndpoint;
+import org.apache.camel.component.sql.stored.template.TemplateParser;
+import org.apache.camel.impl.DefaultPollingEndpoint;
import org.apache.camel.spi.Metadata;
import org.apache.camel.spi.UriEndpoint;
+import org.apache.camel.spi.UriParam;
import org.apache.camel.spi.UriPath;
-import org.apache.camel.util.ObjectHelper;
-import org.apache.camel.util.ServiceHelper;
import org.apache.camel.util.UnsafeUriCharactersEncoder;
import org.springframework.jdbc.core.JdbcTemplate;
@UriEndpoint(scheme = "sql-stored", title = "SQL StoredProcedure", syntax = "sql-stored:template", producerOnly = true, label = "database,sql")
-public class SqlStoredEndpoint extends DefaultEndpoint {
+public class SqlStoredEndpoint extends DefaultPollingEndpoint {
+ private final CallableStatementWrapperFactory wrapperFactory;
private JdbcTemplate jdbcTemplate;
- private TemplateStoredProcedureFactory templateStoredProcedureFactory;
- @UriPath @Metadata(required = "true")
- private String template;
+ @UriParam(description = "Sets the DataSource to use to communicate with the database.")
+ private DataSource dataSource;
- public SqlStoredEndpoint(String endpointUri, Component component) {
- super(endpointUri, component);
+ @UriPath(description = "Sets the StoredProcedure template to perform")
+ @Metadata(required = "true")
+ private String template;
+ @UriParam(label = "producer", description = "Enables or disables batch mode")
+ private boolean batch;
+ @UriParam(label = "producer", description = "Whether to use the message body as the template and then headers for parameters. If this option is enabled then the template in the uri is not used.")
+ private boolean useMessageBodyForTemplate;
+ @UriParam(label = "producer", description = "If set, will ignore the results of the template and use the existing IN message as the OUT message for the continuation of processing")
+ private boolean noop;
+ @UriParam(description = "Store the template result in a header instead of the message body. By default, outputHeader == null and the template result is stored"
+ + " in the message body, any existing content in the message body is discarded. If outputHeader is set, the value is used as the name of the header"
+ + " to store the template result and the original message body is preserved.")
+ private String outputHeader;
+
+ public SqlStoredEndpoint(String uri, SqlStoredComponent component, JdbcTemplate jdbcTemplate) {
+ super(uri, component);
+ setJdbcTemplate(jdbcTemplate);
+ wrapperFactory = new CallableStatementWrapperFactory(jdbcTemplate, new TemplateParser());
}
- @Override
public Producer createProducer() throws Exception {
- ObjectHelper.notNull(template, "template");
- ObjectHelper.notNull(templateStoredProcedureFactory, "templateStoredProcedureFactory");
-
- return new SqlStoredProducer(this, template, templateStoredProcedureFactory);
+ SqlStoredProducer result = new SqlStoredProducer(this);
+ return result;
}
+
@Override
- public Consumer createConsumer(Processor processor) throws Exception {
- throw new UnsupportedOperationException("This component does not support consumer");
+ protected String createEndpointUri() {
+ // Make sure it's properly encoded
+ return "sql-stored:" + UnsafeUriCharactersEncoder.encode(this.template);
}
@Override
- public boolean isSingleton() {
- return true;
+ protected void doStop() throws Exception {
+ super.doStop();
+ this.wrapperFactory.shutdown();
+
}
- @Override
- protected String createEndpointUri() {
- return "sql-stored:" + UnsafeUriCharactersEncoder.encode(template);
+ public JdbcTemplate getJdbcTemplate() {
+ return jdbcTemplate;
}
- @Override
- protected void doStart() throws Exception {
- ServiceHelper.startService(templateStoredProcedureFactory);
+ public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
+ this.jdbcTemplate = jdbcTemplate;
}
- @Override
- protected void doStop() throws Exception {
- ServiceHelper.stopService(templateStoredProcedureFactory);
+ public boolean isBatch() {
+ return batch;
+ }
+
+ public void setBatch(boolean batch) {
+ this.batch = batch;
+ }
+
+ public boolean isUseMessageBodyForTemplate() {
+ return useMessageBodyForTemplate;
+ }
+
+ public void setUseMessageBodyForTemplate(boolean useMessageBodyForTemplate) {
+ this.useMessageBodyForTemplate = useMessageBodyForTemplate;
+ }
+
+ public boolean isNoop() {
+ return noop;
+ }
+
+ public void setNoop(boolean noop) {
+ this.noop = noop;
+ }
+
+ public String getOutputHeader() {
+ return outputHeader;
+ }
+
+ public void setOutputHeader(String outputHeader) {
+ this.outputHeader = outputHeader;
}
public String getTemplate() {
return template;
}
- /**
- * The stored procedure template to perform
- */
public void setTemplate(String template) {
this.template = template;
}
- public TemplateStoredProcedureFactory getTemplateStoredProcedureFactory() {
- return templateStoredProcedureFactory;
+ public DataSource getDataSource() {
+ return dataSource;
}
- /**
- * To use a custom instance of TemplateStoredProcedureFactory
- */
- public void setTemplateStoredProcedureFactory(TemplateStoredProcedureFactory templateStoredProcedureFactory) {
- this.templateStoredProcedureFactory = templateStoredProcedureFactory;
+ public void setDataSource(DataSource dataSource) {
+ this.dataSource = dataSource;
}
- public JdbcTemplate getJdbcTemplate() {
- return jdbcTemplate;
+ @Override
+ public boolean isSingleton() {
+ return false;
}
- /**
- * to use a custom instance of JdbcTemplate
- */
- public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
- this.jdbcTemplate = jdbcTemplate;
+ public CallableStatementWrapperFactory getWrapperFactory() {
+ return wrapperFactory;
}
}
http://git-wip-us.apache.org/repos/asf/camel/blob/df5944fa/components/camel-sql/src/main/java/org/apache/camel/component/sql/stored/SqlStoredProducer.java
----------------------------------------------------------------------
diff --git a/components/camel-sql/src/main/java/org/apache/camel/component/sql/stored/SqlStoredProducer.java b/components/camel-sql/src/main/java/org/apache/camel/component/sql/stored/SqlStoredProducer.java
index 4a7ccc4..eff61b1 100644
--- a/components/camel-sql/src/main/java/org/apache/camel/component/sql/stored/SqlStoredProducer.java
+++ b/components/camel-sql/src/main/java/org/apache/camel/component/sql/stored/SqlStoredProducer.java
@@ -16,24 +16,101 @@
*/
package org.apache.camel.component.sql.stored;
-import org.apache.camel.Endpoint;
+import java.sql.SQLException;
+import java.util.Iterator;
+
import org.apache.camel.Exchange;
-import org.apache.camel.component.sql.stored.template.TemplateStoredProcedure;
-import org.apache.camel.component.sql.stored.template.TemplateStoredProcedureFactory;
import org.apache.camel.impl.DefaultProducer;
+import org.springframework.dao.DataAccessException;
public class SqlStoredProducer extends DefaultProducer {
+ private CallableStatementWrapperFactory callableStatementWrapperFactory;
- private TemplateStoredProcedure defaultTemplateStoredProcedure;
-
- public SqlStoredProducer(Endpoint endpoint, String template, TemplateStoredProcedureFactory templateStoredProcedureFactory) {
+ public SqlStoredProducer(SqlStoredEndpoint endpoint) {
super(endpoint);
- this.defaultTemplateStoredProcedure = templateStoredProcedureFactory.createFromString(template);
}
@Override
- public void process(Exchange exchange) throws Exception {
- defaultTemplateStoredProcedure.execute(exchange);
+ public SqlStoredEndpoint getEndpoint() {
+ return (SqlStoredEndpoint) super.getEndpoint();
+ }
+
+ public void process(final Exchange exchange) throws Exception {
+ StamentWrapper stamentWrapper = createStatement(exchange);
+ stamentWrapper.call(new WrapperExecuteCallback() {
+ @Override
+ public void execute(StamentWrapper ps) throws SQLException, DataAccessException {
+ // transfer incoming message body data to prepared statement parameters, if necessary
+ if (getEndpoint().isBatch()) {
+ Iterator<?> iterator;
+ if (getEndpoint().isUseMessageBodyForTemplate()) {
+ iterator = exchange.getIn().getHeader(SqlStoredConstants.SQL_STORED_PARAMETERS, Iterator.class);
+ } else {
+ iterator = exchange.getIn().getBody(Iterator.class);
+ }
+
+ if (iterator == null) {
+ throw new IllegalStateException("batch=true but Iterator cannot be found from body or header");
+ }
+ while (iterator.hasNext()) {
+ Object value = iterator.next();
+ ps.addBatch(value, exchange);
+ }
+ } else {
+ Object value;
+ if (getEndpoint().isUseMessageBodyForTemplate()) {
+ value = exchange.getIn().getHeader(SqlStoredConstants.SQL_STORED_PARAMETERS);
+ } else {
+ value = exchange.getIn().getBody();
+ }
+ ps.populateStatement(value, exchange);
+ }
+
+ // call the prepared statement and populate the outgoing message
+ if (getEndpoint().isBatch()) {
+ int[] updateCounts = ps.executeBatch();
+ int total = 0;
+ for (int count : updateCounts) {
+ total += count;
+ }
+ exchange.getIn().setHeader(SqlStoredConstants.SQL_STORED_UPDATE_COUNT, total);
+ } else {
+ Object result = ps.executeStatement();
+ // preserve headers first, so we can override the SQL_ROW_COUNT and SQL_UPDATE_COUNT headers
+ // if statement returns them
+ exchange.getOut().getHeaders().putAll(exchange.getIn().getHeaders());
+
+ if (result != null) {
+ if (getEndpoint().isNoop()) {
+ exchange.getOut().setBody(exchange.getIn().getBody());
+ } else if (getEndpoint().getOutputHeader() != null) {
+ exchange.getOut().setBody(exchange.getIn().getBody());
+ exchange.getOut().setHeader(getEndpoint().getOutputHeader(), result);
+ } else {
+ exchange.getOut().setBody(result);
+ }
+ }
+ // for noop=true we still want to enrich with the headers
+
+ if (ps.getUpdateCount() != null) {
+ exchange.getOut().setHeader(SqlStoredConstants.SQL_STORED_UPDATE_COUNT, ps.getUpdateCount());
+ }
+ }
+ }
+ });
+ }
+
+ private StamentWrapper createStatement(Exchange exchange) throws SQLException {
+ final String sql;
+ if (getEndpoint().isUseMessageBodyForTemplate()) {
+ sql = exchange.getIn().getBody(String.class);
+ } else {
+ String templateHeader = exchange.getIn().getHeader(SqlStoredConstants.SQL_STORED_TEMPLATE, String.class);
+ sql = templateHeader != null ? templateHeader : getEndpoint().getTemplate();
+ }
+
+ return getEndpoint().getWrapperFactory().create(sql);
}
+
}
http://git-wip-us.apache.org/repos/asf/camel/blob/df5944fa/components/camel-sql/src/main/java/org/apache/camel/component/sql/stored/StamentWrapper.java
----------------------------------------------------------------------
diff --git a/components/camel-sql/src/main/java/org/apache/camel/component/sql/stored/StamentWrapper.java b/components/camel-sql/src/main/java/org/apache/camel/component/sql/stored/StamentWrapper.java
new file mode 100644
index 0000000..1b92b28
--- /dev/null
+++ b/components/camel-sql/src/main/java/org/apache/camel/component/sql/stored/StamentWrapper.java
@@ -0,0 +1,42 @@
+/**
+ * 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.
+ */
+package org.apache.camel.component.sql.stored;
+
+import java.sql.SQLException;
+
+import org.apache.camel.Exchange;
+import org.apache.camel.component.sql.SqlProducer;
+
+/**
+ * Wrapper that simplifies operations on {@link java.sql.CallableStatement}
+ * in {@link SqlStoredProducer}.
+ * Wrappers are statefull objects and must not be reused.
+ */
+public interface StamentWrapper {
+
+ void call(WrapperExecuteCallback cb) throws Exception;
+
+ int[] executeBatch() throws SQLException;
+
+ Integer getUpdateCount() throws SQLException;
+
+ Object executeStatement() throws SQLException;
+
+ void populateStatement(Object value, Exchange exchange) throws SQLException;
+
+ void addBatch(Object value, Exchange exchange);
+}
http://git-wip-us.apache.org/repos/asf/camel/blob/df5944fa/components/camel-sql/src/main/java/org/apache/camel/component/sql/stored/TemplateStoredProcedure.java
----------------------------------------------------------------------
diff --git a/components/camel-sql/src/main/java/org/apache/camel/component/sql/stored/TemplateStoredProcedure.java b/components/camel-sql/src/main/java/org/apache/camel/component/sql/stored/TemplateStoredProcedure.java
new file mode 100644
index 0000000..c7a1df5
--- /dev/null
+++ b/components/camel-sql/src/main/java/org/apache/camel/component/sql/stored/TemplateStoredProcedure.java
@@ -0,0 +1,83 @@
+/**
+ * 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.
+ */
+package org.apache.camel.component.sql.stored;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.camel.Exchange;
+import org.apache.camel.component.sql.stored.template.ast.InputParameter;
+import org.apache.camel.component.sql.stored.template.ast.OutParameter;
+import org.apache.camel.component.sql.stored.template.ast.Template;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.jdbc.core.JdbcTemplate;
+import org.springframework.jdbc.core.SqlOutParameter;
+import org.springframework.jdbc.core.SqlParameter;
+import org.springframework.jdbc.object.StoredProcedure;
+
+public class TemplateStoredProcedure extends StoredProcedure {
+
+ private static final Logger LOG = LoggerFactory.getLogger(TemplateStoredProcedure.class);
+
+ private final Template template;
+
+ private List<InputParameter> inputParameterList = new ArrayList<>();
+
+ public TemplateStoredProcedure(JdbcTemplate jdbcTemplate, Template template) {
+ this.template = template;
+ setDataSource(jdbcTemplate.getDataSource());
+
+ setSql(template.getProcedureName());
+
+ for (Object parameter : template.getParameterList()) {
+ if (parameter instanceof InputParameter) {
+ InputParameter inputParameter = (InputParameter) parameter;
+ declareParameter(new SqlParameter(inputParameter.getName(), inputParameter.getSqlType()));
+ inputParameterList.add(inputParameter);
+
+ } else if (parameter instanceof OutParameter) {
+ OutParameter outParameter = (OutParameter) parameter;
+ declareParameter(new SqlOutParameter(outParameter.getOutHeader(), outParameter.getSqlType()));
+ setFunction(false);
+ }
+ }
+
+ LOG.debug("Compiling stored procedure: {}", template.getProcedureName());
+ compile();
+ }
+
+ public Map execute(Exchange exchange, Object rowData) {
+ Map<String, Object> params = new HashMap<>();
+
+ for (InputParameter inputParameter : inputParameterList) {
+ params.put(inputParameter.getName(), inputParameter.getValueExtractor().eval(exchange, rowData));
+ }
+
+ LOG.debug("Invoking stored procedure: {}", template.getProcedureName());
+ Map<String, Object> ret = super.execute(params);
+
+ return ret;
+ }
+
+ public Template getTemplate() {
+ return template;
+ }
+}
+
http://git-wip-us.apache.org/repos/asf/camel/blob/df5944fa/components/camel-sql/src/main/java/org/apache/camel/component/sql/stored/WrapperExecuteCallback.java
----------------------------------------------------------------------
diff --git a/components/camel-sql/src/main/java/org/apache/camel/component/sql/stored/WrapperExecuteCallback.java b/components/camel-sql/src/main/java/org/apache/camel/component/sql/stored/WrapperExecuteCallback.java
new file mode 100644
index 0000000..fedd926
--- /dev/null
+++ b/components/camel-sql/src/main/java/org/apache/camel/component/sql/stored/WrapperExecuteCallback.java
@@ -0,0 +1,26 @@
+/**
+ * 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.
+ */
+package org.apache.camel.component.sql.stored;
+
+import java.sql.SQLException;
+
+import org.springframework.dao.DataAccessException;
+
+public interface WrapperExecuteCallback {
+
+ void execute(StamentWrapper stamentWrapper) throws SQLException, DataAccessException;
+}
http://git-wip-us.apache.org/repos/asf/camel/blob/df5944fa/components/camel-sql/src/main/java/org/apache/camel/component/sql/stored/template/TemplateParser.java
----------------------------------------------------------------------
diff --git a/components/camel-sql/src/main/java/org/apache/camel/component/sql/stored/template/TemplateParser.java b/components/camel-sql/src/main/java/org/apache/camel/component/sql/stored/template/TemplateParser.java
new file mode 100644
index 0000000..321fa09
--- /dev/null
+++ b/components/camel-sql/src/main/java/org/apache/camel/component/sql/stored/template/TemplateParser.java
@@ -0,0 +1,45 @@
+/**
+ * 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.
+ */
+package org.apache.camel.component.sql.stored.template;
+
+import java.io.StringReader;
+
+import org.apache.camel.component.sql.stored.template.ast.ParseRuntimeException;
+import org.apache.camel.component.sql.stored.template.ast.Template;
+import org.apache.camel.component.sql.stored.template.generated.ParseException;
+import org.apache.camel.component.sql.stored.template.generated.SSPTParser;
+
+public class TemplateParser {
+
+ public Template parseTemplate(String template) {
+ try {
+ SSPTParser parser = new SSPTParser(new StringReader(template));
+ Template ret = validate(parser.parse());
+
+ return ret;
+
+ } catch (ParseException parseException) {
+ throw new ParseRuntimeException(parseException);
+ }
+ }
+
+ private Template validate(Template input) {
+ return input;
+ }
+
+
+}
http://git-wip-us.apache.org/repos/asf/camel/blob/df5944fa/components/camel-sql/src/main/java/org/apache/camel/component/sql/stored/template/TemplateStoredProcedure.java
----------------------------------------------------------------------
diff --git a/components/camel-sql/src/main/java/org/apache/camel/component/sql/stored/template/TemplateStoredProcedure.java b/components/camel-sql/src/main/java/org/apache/camel/component/sql/stored/template/TemplateStoredProcedure.java
deleted file mode 100644
index 180c1b2..0000000
--- a/components/camel-sql/src/main/java/org/apache/camel/component/sql/stored/template/TemplateStoredProcedure.java
+++ /dev/null
@@ -1,74 +0,0 @@
-/**
- * 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.
- */
-package org.apache.camel.component.sql.stored.template;
-
-import java.util.HashMap;
-import java.util.Map;
-
-import org.apache.camel.Exchange;
-import org.apache.camel.component.sql.stored.template.ast.InputParameter;
-import org.apache.camel.component.sql.stored.template.ast.OutParameter;
-import org.apache.camel.component.sql.stored.template.ast.Template;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.jdbc.core.JdbcTemplate;
-import org.springframework.jdbc.core.SqlOutParameter;
-import org.springframework.jdbc.core.SqlParameter;
-import org.springframework.jdbc.object.StoredProcedure;
-
-public class TemplateStoredProcedure extends StoredProcedure {
-
- private static final Logger LOG = LoggerFactory.getLogger(TemplateStoredProcedure.class);
- private final Template template;
-
- public TemplateStoredProcedure(JdbcTemplate jdbcTemplate, Template template) {
- this.template = template;
- setDataSource(jdbcTemplate.getDataSource());
-
- setSql(template.getProcedureName());
-
- for (InputParameter inputParameter : template.getInputParameterList()) {
- declareParameter(new SqlParameter(inputParameter.getName(), inputParameter.getSqlType()));
- }
-
- for (OutParameter outParameter : template.getOutParameterList()) {
- declareParameter(new SqlOutParameter(outParameter.getName(), outParameter.getSqlType()));
- setFunction(false);
- }
-
- LOG.debug("Compiling stored procedure: {}", template.getProcedureName());
- compile();
- }
-
- public void execute(Exchange exchange) {
-
- Map<String, Object> params = new HashMap<>();
-
- for (InputParameter inputParameter : template.getInputParameterList()) {
- params.put(inputParameter.getName(), inputParameter.getValueExpression().evaluate(exchange, inputParameter.getJavaType()));
- }
-
- LOG.debug("Invoking stored procedure: {}", template.getProcedureName());
- Map<String, Object> ret = super.execute(params);
-
- for (OutParameter out : template.getOutParameterList()) {
- exchange.getOut().setHeader(out.getOutHeader(), ret.get(out.getName()));
- }
-
- }
-
-}
http://git-wip-us.apache.org/repos/asf/camel/blob/df5944fa/components/camel-sql/src/main/java/org/apache/camel/component/sql/stored/template/TemplateStoredProcedureFactory.java
----------------------------------------------------------------------
diff --git a/components/camel-sql/src/main/java/org/apache/camel/component/sql/stored/template/TemplateStoredProcedureFactory.java b/components/camel-sql/src/main/java/org/apache/camel/component/sql/stored/template/TemplateStoredProcedureFactory.java
deleted file mode 100644
index f096dc8..0000000
--- a/components/camel-sql/src/main/java/org/apache/camel/component/sql/stored/template/TemplateStoredProcedureFactory.java
+++ /dev/null
@@ -1,76 +0,0 @@
-/**
- * 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.
- */
-package org.apache.camel.component.sql.stored.template;
-
-import java.io.StringReader;
-
-import org.apache.camel.component.sql.stored.template.ast.ParseRuntimeException;
-import org.apache.camel.component.sql.stored.template.ast.Template;
-import org.apache.camel.component.sql.stored.template.generated.ParseException;
-import org.apache.camel.component.sql.stored.template.generated.SSPTParser;
-import org.apache.camel.support.ServiceSupport;
-import org.apache.camel.util.LRUCache;
-import org.springframework.jdbc.core.JdbcTemplate;
-
-public class TemplateStoredProcedureFactory extends ServiceSupport {
-
- public static final int TEMPLATE_CACHE_DEFAULT_SIZE = 200;
- private final JdbcTemplate jdbcTemplate;
- private final LRUCache<String, TemplateStoredProcedure> templateCache = new LRUCache<String, TemplateStoredProcedure>(TEMPLATE_CACHE_DEFAULT_SIZE);
-
- public TemplateStoredProcedureFactory(JdbcTemplate jdbcTemplate) {
- this.jdbcTemplate = jdbcTemplate;
- }
-
- public TemplateStoredProcedure createFromString(String string) {
- TemplateStoredProcedure fromCache = templateCache.get(string);
-
- if (fromCache != null) {
- return fromCache;
- }
-
- Template sptpRootNode = parseTemplate(string);
- TemplateStoredProcedure ret = new TemplateStoredProcedure(jdbcTemplate, sptpRootNode);
-
- templateCache.put(string, ret);
-
- return ret;
- }
-
- public Template parseTemplate(String template) {
- try {
- SSPTParser parser = new SSPTParser(new StringReader(template));
- return validate(parser.parse());
- } catch (ParseException parseException) {
- throw new ParseRuntimeException(parseException);
- }
- }
-
- private Template validate(Template input) {
- return input;
- }
-
- @Override
- protected void doStart() throws Exception {
- }
-
- @Override
- protected void doStop() throws Exception {
- // clear cache when we are stopping
- templateCache.clear();
- }
-}
http://git-wip-us.apache.org/repos/asf/camel/blob/df5944fa/components/camel-sql/src/main/java/org/apache/camel/component/sql/stored/template/ast/InputParameter.java
----------------------------------------------------------------------
diff --git a/components/camel-sql/src/main/java/org/apache/camel/component/sql/stored/template/ast/InputParameter.java b/components/camel-sql/src/main/java/org/apache/camel/component/sql/stored/template/ast/InputParameter.java
index 68927a2..deb4d52 100644
--- a/components/camel-sql/src/main/java/org/apache/camel/component/sql/stored/template/ast/InputParameter.java
+++ b/components/camel-sql/src/main/java/org/apache/camel/component/sql/stored/template/ast/InputParameter.java
@@ -16,27 +16,63 @@
*/
package org.apache.camel.component.sql.stored.template.ast;
+import java.util.Map;
+
+import org.apache.camel.Exchange;
import org.apache.camel.Expression;
import org.apache.camel.builder.ExpressionBuilder;
+import org.apache.camel.component.sql.stored.template.generated.SSPTParserConstants;
+import org.apache.camel.component.sql.stored.template.generated.Token;
public class InputParameter {
private final String name;
private final int sqlType;
- private final Expression valueExpression;
private final Class javaType;
+ private ValueExtractor valueExtractor;
- public InputParameter(String name, int sqlType, String valueSrcAsStr, Class javaType) {
+ public InputParameter(String name, int sqlType, Token valueSrcToken, Class javaType) {
this.name = name;
this.sqlType = sqlType;
this.javaType = javaType;
- this.valueExpression = parseValueExpression(valueSrcAsStr);
+ parseValueExpression(valueSrcToken);
}
- private Expression parseValueExpression(String str) {
- return ExpressionBuilder.simpleExpression(str);
+ private void parseValueExpression(Token valueSrcToken) {
+ if (SSPTParserConstants.SIMPLE_EXP_TOKEN == valueSrcToken.kind) {
+ final Expression exp = ExpressionBuilder.simpleExpression(valueSrcToken.toString());
+ this.valueExtractor = new ValueExtractor() {
+
+ @Override
+ public Object eval(Exchange exchange, Object container) {
+ return exp.evaluate(exchange, javaType);
+ }
+ };
+ } else if (SSPTParserConstants.PARAMETER_POS_TOKEN == valueSrcToken.kind) {
+
+ //remove leading :#
+ final String mapKey = valueSrcToken.toString().substring(2);
+ this.valueExtractor = new ValueExtractor() {
+ @Override
+ public Object eval(Exchange exchange, Object container) {
+ return ((Map) container).get(mapKey);
+ }
+ };
+ }
}
+ /*public Object getParameterValueFromContainer(Exchange exchange, Object container) {
+ if (this.valueExpression != null) {
+ return valueExpression.evaluate(exchange, this.getJavaType());
+ } else {
+ return getValueFromMap((Map<String, Object>) container);
+ }
+ }*/
+
+ /*private Object getValueFromMap(Map<String, Object> container) {
+ return container.get(mapKey);
+ }*/
+
public String getName() {
return name;
}
@@ -45,12 +81,12 @@ public class InputParameter {
return sqlType;
}
- public Expression getValueExpression() {
- return valueExpression;
- }
public Class getJavaType() {
return javaType;
}
+ public ValueExtractor getValueExtractor() {
+ return valueExtractor;
+ }
}
http://git-wip-us.apache.org/repos/asf/camel/blob/df5944fa/components/camel-sql/src/main/java/org/apache/camel/component/sql/stored/template/ast/ParseHelper.java
----------------------------------------------------------------------
diff --git a/components/camel-sql/src/main/java/org/apache/camel/component/sql/stored/template/ast/ParseHelper.java b/components/camel-sql/src/main/java/org/apache/camel/component/sql/stored/template/ast/ParseHelper.java
index dd926ef..8a2d9b5 100644
--- a/components/camel-sql/src/main/java/org/apache/camel/component/sql/stored/template/ast/ParseHelper.java
+++ b/components/camel-sql/src/main/java/org/apache/camel/component/sql/stored/template/ast/ParseHelper.java
@@ -17,14 +17,31 @@
package org.apache.camel.component.sql.stored.template.ast;
import java.lang.reflect.Field;
-import java.math.BigInteger;
+import java.math.BigDecimal;
import java.sql.Date;
import java.sql.Types;
+import java.util.HashMap;
+import java.util.Map;
import org.springframework.util.ReflectionUtils;
public final class ParseHelper {
+ static final Map<Integer, Class> SQL_TYPE_TO_JAVA_CLASS = new HashMap<>();
+
+ //somekind of mapping here https://docs.oracle.com/cd/E19501-01/819-3659/gcmaz/
+ //TODO: test with each SQL_TYPE_TO_JAVA_CLASS that JAVA conversion works!
+ static {
+ SQL_TYPE_TO_JAVA_CLASS.put(Types.INTEGER, Integer.class);
+ SQL_TYPE_TO_JAVA_CLASS.put(Types.VARCHAR, String.class);
+ SQL_TYPE_TO_JAVA_CLASS.put(Types.BIGINT, Long.class);
+ SQL_TYPE_TO_JAVA_CLASS.put(Types.CHAR, String.class);
+ SQL_TYPE_TO_JAVA_CLASS.put(Types.DECIMAL, BigDecimal.class);
+ SQL_TYPE_TO_JAVA_CLASS.put(Types.BOOLEAN, Boolean.class);
+ SQL_TYPE_TO_JAVA_CLASS.put(Types.DATE, Date.class);
+ SQL_TYPE_TO_JAVA_CLASS.put(Types.TIMESTAMP, Date.class);
+ }
+
private ParseHelper() {
}
@@ -41,36 +58,10 @@ public final class ParseHelper {
}
public static Class sqlTypeToJavaType(int sqlType, String sqlTypeStr) {
- //TODO: as rest of types.
- //TODO: add test for each type.
- Class ret;
- switch (sqlType) {
- case Types.INTEGER:
- ret = Integer.class;
- break;
- case Types.VARCHAR:
- ret = String.class;
- break;
- case Types.BIGINT:
- ret = BigInteger.class;
- break;
- case Types.CHAR:
- ret = String.class;
- break;
- case Types.BOOLEAN:
- ret = Boolean.class;
- break;
- case Types.DATE:
- ret = Date.class;
- break;
- case Types.TIMESTAMP:
- ret = Date.class;
- break;
- default:
+ Class javaType = SQL_TYPE_TO_JAVA_CLASS.get(sqlType);
+ if (javaType == null) {
throw new ParseRuntimeException("Unable to map SQL type " + sqlTypeStr + " to Java type");
}
-
- return ret;
+ return javaType;
}
-
}
http://git-wip-us.apache.org/repos/asf/camel/blob/df5944fa/components/camel-sql/src/main/java/org/apache/camel/component/sql/stored/template/ast/Template.java
----------------------------------------------------------------------
diff --git a/components/camel-sql/src/main/java/org/apache/camel/component/sql/stored/template/ast/Template.java b/components/camel-sql/src/main/java/org/apache/camel/component/sql/stored/template/ast/Template.java
index 935609c..290abde 100644
--- a/components/camel-sql/src/main/java/org/apache/camel/component/sql/stored/template/ast/Template.java
+++ b/components/camel-sql/src/main/java/org/apache/camel/component/sql/stored/template/ast/Template.java
@@ -24,16 +24,11 @@ import java.util.List;
*/
public class Template {
+ private final List<Object> parameterList = new ArrayList<>();
private String procedureName;
- private final List<InputParameter> inputParameterList = new ArrayList<>();
- private final List<OutParameter> outParameterList = new ArrayList<>();
public void addParameter(Object parameter) {
- if (parameter instanceof OutParameter) {
- outParameterList.add((OutParameter) parameter);
- } else {
- inputParameterList.add((InputParameter) parameter);
- }
+ parameterList.add(parameter);
}
public String getProcedureName() {
@@ -44,12 +39,8 @@ public class Template {
this.procedureName = procedureName;
}
- public List<InputParameter> getInputParameterList() {
- return inputParameterList;
- }
-
- public List<OutParameter> getOutParameterList() {
- return outParameterList;
+ public List<Object> getParameterList() {
+ return parameterList;
}
}
http://git-wip-us.apache.org/repos/asf/camel/blob/df5944fa/components/camel-sql/src/main/java/org/apache/camel/component/sql/stored/template/ast/ValueExtractor.java
----------------------------------------------------------------------
diff --git a/components/camel-sql/src/main/java/org/apache/camel/component/sql/stored/template/ast/ValueExtractor.java b/components/camel-sql/src/main/java/org/apache/camel/component/sql/stored/template/ast/ValueExtractor.java
new file mode 100644
index 0000000..228c758
--- /dev/null
+++ b/components/camel-sql/src/main/java/org/apache/camel/component/sql/stored/template/ast/ValueExtractor.java
@@ -0,0 +1,29 @@
+/**
+ * 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.
+ */
+package org.apache.camel.component.sql.stored.template.ast;
+
+import org.apache.camel.Exchange;
+
+/**
+ * ValueExtractotr extracts value from Exchange and Container object.
+ * Usually each input parameter has one extractor which extracts
+ * parameter value from input "map" to be sent into db.
+ */
+public interface ValueExtractor {
+
+ Object eval(Exchange exchange, Object container);
+}
http://git-wip-us.apache.org/repos/asf/camel/blob/df5944fa/components/camel-sql/src/main/java/org/apache/camel/component/sql/stored/template/generated/ParseException.java
----------------------------------------------------------------------
diff --git a/components/camel-sql/src/main/java/org/apache/camel/component/sql/stored/template/generated/ParseException.java b/components/camel-sql/src/main/java/org/apache/camel/component/sql/stored/template/generated/ParseException.java
index 30e4737..b3829dd 100644
--- a/components/camel-sql/src/main/java/org/apache/camel/component/sql/stored/template/generated/ParseException.java
+++ b/components/camel-sql/src/main/java/org/apache/camel/component/sql/stored/template/generated/ParseException.java
@@ -13,175 +13,168 @@ package org.apache.camel.component.sql.stored.template.generated;
*/
public class ParseException extends Exception {
- /**
- * The version identifier for this Serializable class.
- * Increment only if the <i>serialized</i> form of the
- * class changes.
- */
- private static final long serialVersionUID = 1L;
+ /**
+ * The version identifier for this Serializable class.
+ * Increment only if the <i>serialized</i> form of the
+ * class changes.
+ */
+ private static final long serialVersionUID = 1L;
+ /**
+ * This is the last token that has been consumed successfully. If
+ * this object has been created due to a parse error, the token
+ * followng this token will (therefore) be the first error token.
+ */
+ public Token currentToken;
+ /**
+ * Each entry in this array is an array of integers. Each array
+ * of integers represents a sequence of tokens (by their ordinal
+ * values) that is expected at this point of the parse.
+ */
+ public int[][] expectedTokenSequences;
+ /**
+ * This is a reference to the "tokenImage" array of the generated
+ * parser within which the parse error occurred. This array is
+ * defined in the generated ...Constants interface.
+ */
+ public String[] tokenImage;
+ /**
+ * The end of line string for this machine.
+ */
+ protected String eol = System.getProperty("line.separator", "\n");
- /**
- * This constructor is used by the method "generateParseException"
- * in the generated parser. Calling this constructor generates
- * a new object of this type with the fields "currentToken",
- * "expectedTokenSequences", and "tokenImage" set.
- */
- public ParseException(Token currentTokenVal,
- int[][] expectedTokenSequencesVal,
- String[] tokenImageVal
- )
- {
- super(initialise(currentTokenVal, expectedTokenSequencesVal, tokenImageVal));
- currentToken = currentTokenVal;
- expectedTokenSequences = expectedTokenSequencesVal;
- tokenImage = tokenImageVal;
- }
-
- /**
- * The following constructors are for use by you for whatever
- * purpose you can think of. Constructing the exception in this
- * manner makes the exception behave in the normal way - i.e., as
- * documented in the class "Throwable". The fields "errorToken",
- * "expectedTokenSequences", and "tokenImage" do not contain
- * relevant information. The JavaCC generated code does not use
- * these constructors.
- */
-
- public ParseException() {
- super();
- }
-
- /** Constructor with message. */
- public ParseException(String message) {
- super(message);
- }
-
-
- /**
- * This is the last token that has been consumed successfully. If
- * this object has been created due to a parse error, the token
- * followng this token will (therefore) be the first error token.
- */
- public Token currentToken;
-
- /**
- * Each entry in this array is an array of integers. Each array
- * of integers represents a sequence of tokens (by their ordinal
- * values) that is expected at this point of the parse.
- */
- public int[][] expectedTokenSequences;
+ /**
+ * This constructor is used by the method "generateParseException"
+ * in the generated parser. Calling this constructor generates
+ * a new object of this type with the fields "currentToken",
+ * "expectedTokenSequences", and "tokenImage" set.
+ */
+ public ParseException(Token currentTokenVal,
+ int[][] expectedTokenSequencesVal,
+ String[] tokenImageVal
+ ) {
+ super(initialise(currentTokenVal, expectedTokenSequencesVal, tokenImageVal));
+ currentToken = currentTokenVal;
+ expectedTokenSequences = expectedTokenSequencesVal;
+ tokenImage = tokenImageVal;
+ }
- /**
- * This is a reference to the "tokenImage" array of the generated
- * parser within which the parse error occurred. This array is
- * defined in the generated ...Constants interface.
- */
- public String[] tokenImage;
+ /**
+ * The following constructors are for use by you for whatever
+ * purpose you can think of. Constructing the exception in this
+ * manner makes the exception behave in the normal way - i.e., as
+ * documented in the class "Throwable". The fields "errorToken",
+ * "expectedTokenSequences", and "tokenImage" do not contain
+ * relevant information. The JavaCC generated code does not use
+ * these constructors.
+ */
- /**
- * It uses "currentToken" and "expectedTokenSequences" to generate a parse
- * error message and returns it. If this object has been created
- * due to a parse error, and you do not catch it (it gets thrown
- * from the parser) the correct error message
- * gets displayed.
- */
- private static String initialise(Token currentToken,
- int[][] expectedTokenSequences,
- String[] tokenImage) {
- String eol = System.getProperty("line.separator", "\n");
- StringBuffer expected = new StringBuffer();
- int maxSize = 0;
- for (int i = 0; i < expectedTokenSequences.length; i++) {
- if (maxSize < expectedTokenSequences[i].length) {
- maxSize = expectedTokenSequences[i].length;
- }
- for (int j = 0; j < expectedTokenSequences[i].length; j++) {
- expected.append(tokenImage[expectedTokenSequences[i][j]]).append(' ');
- }
- if (expectedTokenSequences[i][expectedTokenSequences[i].length - 1] != 0) {
- expected.append("...");
- }
- expected.append(eol).append(" ");
+ public ParseException() {
+ super();
}
- String retval = "Encountered \"";
- Token tok = currentToken.next;
- for (int i = 0; i < maxSize; i++) {
- if (i != 0) retval += " ";
- if (tok.kind == 0) {
- retval += tokenImage[0];
- break;
- }
- retval += " " + tokenImage[tok.kind];
- retval += " \"";
- retval += add_escapes(tok.image);
- retval += " \"";
- tok = tok.next;
- }
- retval += "\" at line " + currentToken.next.beginLine + ", column " + currentToken.next.beginColumn;
- retval += "." + eol;
- if (expectedTokenSequences.length == 1) {
- retval += "Was expecting:" + eol + " ";
- } else {
- retval += "Was expecting one of:" + eol + " ";
+
+ /** Constructor with message. */
+ public ParseException(String message) {
+ super(message);
}
- retval += expected.toString();
- return retval;
- }
- /**
- * The end of line string for this machine.
- */
- protected String eol = System.getProperty("line.separator", "\n");
+ /**
+ * It uses "currentToken" and "expectedTokenSequences" to generate a parse
+ * error message and returns it. If this object has been created
+ * due to a parse error, and you do not catch it (it gets thrown
+ * from the parser) the correct error message
+ * gets displayed.
+ */
+ private static String initialise(Token currentToken,
+ int[][] expectedTokenSequences,
+ String[] tokenImage) {
+ String eol = System.getProperty("line.separator", "\n");
+ StringBuffer expected = new StringBuffer();
+ int maxSize = 0;
+ for (int i = 0; i < expectedTokenSequences.length; i++) {
+ if (maxSize < expectedTokenSequences[i].length) {
+ maxSize = expectedTokenSequences[i].length;
+ }
+ for (int j = 0; j < expectedTokenSequences[i].length; j++) {
+ expected.append(tokenImage[expectedTokenSequences[i][j]]).append(' ');
+ }
+ if (expectedTokenSequences[i][expectedTokenSequences[i].length - 1] != 0) {
+ expected.append("...");
+ }
+ expected.append(eol).append(" ");
+ }
+ String retval = "Encountered \"";
+ Token tok = currentToken.next;
+ for (int i = 0; i < maxSize; i++) {
+ if (i != 0) retval += " ";
+ if (tok.kind == 0) {
+ retval += tokenImage[0];
+ break;
+ }
+ retval += " " + tokenImage[tok.kind];
+ retval += " \"";
+ retval += add_escapes(tok.image);
+ retval += " \"";
+ tok = tok.next;
+ }
+ retval += "\" at line " + currentToken.next.beginLine + ", column " + currentToken.next.beginColumn;
+ retval += "." + eol;
+ if (expectedTokenSequences.length == 1) {
+ retval += "Was expecting:" + eol + " ";
+ } else {
+ retval += "Was expecting one of:" + eol + " ";
+ }
+ retval += expected.toString();
+ return retval;
+ }
- /**
- * Used to convert raw characters to their escaped version
- * when these raw version cannot be used as part of an ASCII
- * string literal.
- */
- static String add_escapes(String str) {
- StringBuffer retval = new StringBuffer();
- char ch;
- for (int i = 0; i < str.length(); i++) {
- switch (str.charAt(i))
- {
- case 0 :
- continue;
- case '\b':
- retval.append("\\b");
- continue;
- case '\t':
- retval.append("\\t");
- continue;
- case '\n':
- retval.append("\\n");
- continue;
- case '\f':
- retval.append("\\f");
- continue;
- case '\r':
- retval.append("\\r");
- continue;
- case '\"':
- retval.append("\\\"");
- continue;
- case '\'':
- retval.append("\\\'");
- continue;
- case '\\':
- retval.append("\\\\");
- continue;
- default:
- if ((ch = str.charAt(i)) < 0x20 || ch > 0x7e) {
- String s = "0000" + Integer.toString(ch, 16);
- retval.append("\\u" + s.substring(s.length() - 4, s.length()));
- } else {
- retval.append(ch);
- }
- continue;
+ /**
+ * Used to convert raw characters to their escaped version
+ * when these raw version cannot be used as part of an ASCII
+ * string literal.
+ */
+ static String add_escapes(String str) {
+ StringBuffer retval = new StringBuffer();
+ char ch;
+ for (int i = 0; i < str.length(); i++) {
+ switch (str.charAt(i)) {
+ case 0:
+ continue;
+ case '\b':
+ retval.append("\\b");
+ continue;
+ case '\t':
+ retval.append("\\t");
+ continue;
+ case '\n':
+ retval.append("\\n");
+ continue;
+ case '\f':
+ retval.append("\\f");
+ continue;
+ case '\r':
+ retval.append("\\r");
+ continue;
+ case '\"':
+ retval.append("\\\"");
+ continue;
+ case '\'':
+ retval.append("\\\'");
+ continue;
+ case '\\':
+ retval.append("\\\\");
+ continue;
+ default:
+ if ((ch = str.charAt(i)) < 0x20 || ch > 0x7e) {
+ String s = "0000" + Integer.toString(ch, 16);
+ retval.append("\\u" + s.substring(s.length() - 4, s.length()));
+ } else {
+ retval.append(ch);
+ }
+ continue;
+ }
}
- }
- return retval.toString();
- }
+ return retval.toString();
+ }
}
/* JavaCC - OriginalChecksum=5189b93605d5a3d3833ed059f46e94c9 (do not edit this line) */