diff --git a/activemq-camel/src/test/java/org/apache/activemq/camel/AMQ2240Test.java b/activemq-camel/src/test/java/org/apache/activemq/camel/AMQ2240Test.java new file mode 100644 index 0000000000..b8bb003fd3 --- /dev/null +++ b/activemq-camel/src/test/java/org/apache/activemq/camel/AMQ2240Test.java @@ -0,0 +1,69 @@ +/** + * 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.activemq.camel; + +import static org.junit.Assert.*; + +import org.apache.activemq.broker.BrokerService; +import org.apache.activemq.camel.component.ActiveMQComponent; +import org.apache.camel.CamelContext; +import org.apache.camel.builder.RouteBuilder; +import org.apache.camel.impl.DefaultCamelContext; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class AMQ2240Test { + + private static final Logger LOG = LoggerFactory.getLogger(AMQ2240Test.class); + + @Test + public void testBadVMTransportOptionsJMSPrefix() throws Exception { + + try{ + final String vmUri = "vm://localhost?" + + "jms.redeliveryPolicy.maximumRedeliveries=0&" + + "jms.redeliveryPolicy.initialRedeliveryDelay=500&" + + "jms.useAsyncSend=false&jms.sendTimeout=ABC&" + + "jms.maxXXXXReconnectAttempts=1&jms.timeout=3000"; + + LOG.info("creating context with bad URI: " + vmUri); + ActiveMQComponent.activeMQComponent(vmUri); + + fail("Should have received an exception from the bad URI."); + } catch(Exception e) { + // Expected + } + } + + @Test + public void testBadVMTransportOptionsBrokerPrefix() throws Exception { + try{ + final String vmUri = "vm://localhost?" + + "broker.XXX=foo&broker.persistent=XXX&broker.useJmx=false"; + + LOG.info("creating context with bad URI: " + vmUri); + ActiveMQComponent.activeMQComponent(vmUri).start(); + + fail("Should have received an exception from the bad URI."); + } catch(Exception e) { + // Expected + } + } +} diff --git a/activemq-core/src/main/java/org/apache/activemq/ActiveMQConnectionFactory.java b/activemq-core/src/main/java/org/apache/activemq/ActiveMQConnectionFactory.java index 0007470193..8cc9fd7c25 100755 --- a/activemq-core/src/main/java/org/apache/activemq/ActiveMQConnectionFactory.java +++ b/activemq-core/src/main/java/org/apache/activemq/ActiveMQConnectionFactory.java @@ -52,8 +52,8 @@ import org.apache.activemq.util.URISupport.CompositeData; * Connections.

This class also implements QueueConnectionFactory and * TopicConnectionFactory. You can use this connection to create both * QueueConnections and TopicConnections. - * - * + * + * * @see javax.jms.ConnectionFactory */ public class ActiveMQConnectionFactory extends JNDIBaseStorable implements ConnectionFactory, QueueConnectionFactory, TopicConnectionFactory, StatsCapable, Cloneable { @@ -237,7 +237,7 @@ public class ActiveMQConnectionFactory extends JNDIBaseStorable implements Conne /** * Creates a Transport based on this object's connection settings. Separated * from createActiveMQConnection to allow for subclasses to override. - * + * * @return The newly created Transport. * @throws JMSException If unable to create trasnport. * @author sepandm@gmail.com @@ -331,7 +331,7 @@ public class ActiveMQConnectionFactory extends JNDIBaseStorable implements Conne connection.addTransportListener(transportListener); } if (exceptionListener != null) { - connection.setExceptionListener(exceptionListener); + connection.setExceptionListener(exceptionListener); } if (clientInternalExceptionListener != null) { connection.setClientInternalExceptionListener(clientInternalExceptionListener); @@ -363,8 +363,18 @@ public class ActiveMQConnectionFactory extends JNDIBaseStorable implements Conne // It might be a standard URI or... try { - Map map = URISupport.parseQuery(this.brokerURL.getQuery()); - if (buildFromMap(IntrospectionSupport.extractProperties(map, "jms."))) { + Map map = URISupport.parseQuery(this.brokerURL.getQuery()); + Map jmsOptionsMap = IntrospectionSupport.extractProperties(map, "jms."); + if (buildFromMap(jmsOptionsMap)) { + if (!jmsOptionsMap.isEmpty()) { + String msg = "There are " + jmsOptionsMap.size() + + " jms options that couldn't be set on the ConnectionFactory." + + " Check the options are spelled correctly." + + " Unknown parameters=[" + jmsOptionsMap + "]." + + " This connection factory cannot be started."; + throw new IllegalArgumentException(msg); + } + this.brokerURL = URISupport.createRemainingURI(this.brokerURL, map); } @@ -376,7 +386,17 @@ public class ActiveMQConnectionFactory extends JNDIBaseStorable implements Conne // It might be a composite URI. try { CompositeData data = URISupport.parseComposite(this.brokerURL); - if (buildFromMap(IntrospectionSupport.extractProperties(data.getParameters(), "jms."))) { + Map jmsOptionsMap = IntrospectionSupport.extractProperties(data.getParameters(), "jms."); + if (buildFromMap(jmsOptionsMap)) { + if (!jmsOptionsMap.isEmpty()) { + String msg = "There are " + jmsOptionsMap.size() + + " jms options that couldn't be set on the ConnectionFactory." + + " Check the options are spelled correctly." + + " Unknown parameters=[" + jmsOptionsMap + "]." + + " This connection factory cannot be started."; + throw new IllegalArgumentException(msg); + } + this.brokerURL = data.toURI(); } } catch (URISyntaxException e) { @@ -503,7 +523,7 @@ public class ActiveMQConnectionFactory extends JNDIBaseStorable implements Conne /** * Set true if always require messages to be sync sent - * + * * @param alwaysSyncSend */ public void setAlwaysSyncSend(boolean alwaysSyncSend) { @@ -542,7 +562,7 @@ public class ActiveMQConnectionFactory extends JNDIBaseStorable implements Conne * Enables or disables whether or not queue consumers should be exclusive or * not for example to preserve ordering when not using Message Groups - * + * * @param exclusiveConsumer */ public void setExclusiveConsumer(boolean exclusiveConsumer) { @@ -564,7 +584,7 @@ public class ActiveMQConnectionFactory extends JNDIBaseStorable implements Conne public MessageTransformer getTransformer() { return transformer; } - + /** * @return the sendTimeout */ @@ -578,7 +598,7 @@ public class ActiveMQConnectionFactory extends JNDIBaseStorable implements Conne public void setSendTimeout(int sendTimeout) { this.sendTimeout = sendTimeout; } - + /** * @return the sendAcksAsync */ @@ -592,7 +612,7 @@ public class ActiveMQConnectionFactory extends JNDIBaseStorable implements Conne public void setSendAcksAsync(boolean sendAcksAsync) { this.sendAcksAsync = sendAcksAsync; } - + /** * @return the messagePrioritySupported */ @@ -617,6 +637,7 @@ public class ActiveMQConnectionFactory extends JNDIBaseStorable implements Conne this.transformer = transformer; } + @SuppressWarnings({ "unchecked", "rawtypes" }) @Override public void buildFromProperties(Properties properties) { @@ -751,7 +772,7 @@ public class ActiveMQConnectionFactory extends JNDIBaseStorable implements Conne * minimize context switches which boost performance. However sometimes its * better to go slower to ensure that a single blocked consumer socket does * not block delivery to other consumers. - * + * * @param asyncDispatch If true then consumers created on this connection * will default to having their messages dispatched * asynchronously. The default value is false. @@ -841,7 +862,7 @@ public class ActiveMQConnectionFactory extends JNDIBaseStorable implements Conne /** * Sets the prefix used by autogenerated JMS Client ID values which are used * if the JMS client does not explicitly specify on. - * + * * @param clientIDPrefix */ public void setClientIDPrefix(String clientIDPrefix) { @@ -941,12 +962,12 @@ public class ActiveMQConnectionFactory extends JNDIBaseStorable implements Conne public void setTransportListener(TransportListener transportListener) { this.transportListener = transportListener; } - - + + public ExceptionListener getExceptionListener() { return exceptionListener; } - + /** * Allows an {@link ExceptionListener} to be configured on the ConnectionFactory so that when this factory * is used by frameworks which don't expose the Connection such as Spring JmsTemplate, you can register @@ -957,37 +978,37 @@ public class ActiveMQConnectionFactory extends JNDIBaseStorable implements Conne * created by this factory */ public void setExceptionListener(ExceptionListener exceptionListener) { - this.exceptionListener = exceptionListener; + this.exceptionListener = exceptionListener; } - public int getAuditDepth() { - return auditDepth; - } + public int getAuditDepth() { + return auditDepth; + } - public void setAuditDepth(int auditDepth) { - this.auditDepth = auditDepth; - } + public void setAuditDepth(int auditDepth) { + this.auditDepth = auditDepth; + } - public int getAuditMaximumProducerNumber() { - return auditMaximumProducerNumber; - } + public int getAuditMaximumProducerNumber() { + return auditMaximumProducerNumber; + } - public void setAuditMaximumProducerNumber(int auditMaximumProducerNumber) { - this.auditMaximumProducerNumber = auditMaximumProducerNumber; - } + public void setAuditMaximumProducerNumber(int auditMaximumProducerNumber) { + this.auditMaximumProducerNumber = auditMaximumProducerNumber; + } public void setUseDedicatedTaskRunner(boolean useDedicatedTaskRunner) { this.useDedicatedTaskRunner = useDedicatedTaskRunner; } - + public boolean isUseDedicatedTaskRunner() { return useDedicatedTaskRunner; } - + public void setConsumerFailoverRedeliveryWaitPeriod(long consumerFailoverRedeliveryWaitPeriod) { this.consumerFailoverRedeliveryWaitPeriod = consumerFailoverRedeliveryWaitPeriod; } - + public long getConsumerFailoverRedeliveryWaitPeriod() { return consumerFailoverRedeliveryWaitPeriod; } @@ -995,7 +1016,7 @@ public class ActiveMQConnectionFactory extends JNDIBaseStorable implements Conne public ClientInternalExceptionListener getClientInternalExceptionListener() { return clientInternalExceptionListener; } - + /** * Allows an {@link ClientInternalExceptionListener} to be configured on the ConnectionFactory so that when this factory * is used by frameworks which don't expose the Connection such as Spring JmsTemplate, you can register diff --git a/activemq-core/src/main/java/org/apache/activemq/broker/DefaultBrokerFactory.java b/activemq-core/src/main/java/org/apache/activemq/broker/DefaultBrokerFactory.java index 656577f308..e31d0d193f 100644 --- a/activemq-core/src/main/java/org/apache/activemq/broker/DefaultBrokerFactory.java +++ b/activemq-core/src/main/java/org/apache/activemq/broker/DefaultBrokerFactory.java @@ -28,8 +28,8 @@ import org.apache.activemq.util.URISupport.CompositeData; * Simple BrokerFactorySPI which using the brokerURI to extract the * configuration parameters for the broker service. This directly configures the * pojo model so there is no dependency on spring for configuration. - * - * + * + * */ public class DefaultBrokerFactory implements BrokerFactoryHandler { @@ -40,6 +40,15 @@ public class DefaultBrokerFactory implements BrokerFactoryHandler { BrokerService brokerService = new BrokerService(); IntrospectionSupport.setProperties(brokerService, params); + if (!params.isEmpty()) { + String msg = "There are " + params.size() + + " Broker options that couldn't be set on the BrokerService." + + " Check the options are spelled correctly." + + " Unknown parameters=[" + params + "]." + + " This BrokerService cannot be started."; + throw new IllegalArgumentException(msg); + } + if (compositeData.getPath() != null) { brokerService.setBrokerName(compositeData.getPath()); } diff --git a/activemq-core/src/main/java/org/apache/activemq/util/URISupport.java b/activemq-core/src/main/java/org/apache/activemq/util/URISupport.java index 686f8f3054..e969fc0db5 100755 --- a/activemq-core/src/main/java/org/apache/activemq/util/URISupport.java +++ b/activemq-core/src/main/java/org/apache/activemq/util/URISupport.java @@ -24,12 +24,11 @@ import java.net.URLEncoder; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; -import java.util.Iterator; import java.util.List; import java.util.Map; /** - * + * Utility class that provides methods for parsing URI's */ public class URISupport { @@ -105,7 +104,7 @@ public class URISupport { try { uri = uri.substring(uri.lastIndexOf("?") + 1); // get only the relevant part of the query Map rc = new HashMap(); - if (uri != null) { + if (uri != null && !uri.isEmpty()) { String[] parameters = uri.split("&"); for (int i = 0; i < parameters.length; i++) { int p = parameters[i].indexOf("="); @@ -134,7 +133,7 @@ public class URISupport { if (parameters.isEmpty()) { parameters = emptyMap(); } - + return parameters; } } @@ -159,7 +158,7 @@ public class URISupport { } return uri; } - + @SuppressWarnings("unchecked") private static Map emptyMap() { return Collections.EMPTY_MAP; @@ -181,7 +180,7 @@ public class URISupport { int questionMark = schemeSpecificPart.lastIndexOf("?"); // make sure question mark is not within parentheses if (questionMark < schemeSpecificPart.lastIndexOf(")")) { - questionMark = -1; + questionMark = -1; } if (questionMark > 0) { schemeSpecificPart = schemeSpecificPart.substring(0, questionMark); @@ -197,14 +196,14 @@ public class URISupport { CompositeData rc = new CompositeData(); rc.scheme = uri.getScheme(); String ssp = stripPrefix(uri.getRawSchemeSpecificPart().trim(), "//").trim(); - + parseComposite(uri, rc, ssp); rc.fragment = uri.getFragment(); return rc; } - + public static boolean isCompositeURI(URI uri) { if (uri.getQuery() != null) { return false; @@ -322,18 +321,17 @@ public class URISupport { return new URI(stripPrefix(uri.getSchemeSpecificPart().trim(), "//")); } - public static String createQueryString(Map options) throws URISyntaxException { + public static String createQueryString(Map options) throws URISyntaxException { try { if (options.size() > 0) { StringBuffer rc = new StringBuffer(); boolean first = true; - for (Iterator iter = options.keySet().iterator(); iter.hasNext();) { + for (String key : options.keySet()) { if (first) { first = false; } else { rc.append("&"); } - String key = (String)iter.next(); String value = (String)options.get(key); rc.append(URLEncoder.encode(key, "UTF-8")); rc.append("="); @@ -350,10 +348,10 @@ public class URISupport { /** * Creates a URI from the original URI and the remaining paramaters - * + * * @throws URISyntaxException */ - public static URI createRemainingURI(URI originalURI, Map params) throws URISyntaxException { + public static URI createRemainingURI(URI originalURI, Map params) throws URISyntaxException { String s = createQueryString(params); if (s.length() == 0) { s = null;