URI options that are unmatched should result in an error 
to prevent subtle errors in configuration.

git-svn-id: https://svn.apache.org/repos/asf/activemq/trunk@1186842 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Timothy A. Bish 2011-10-20 15:04:21 +00:00
parent 4553ff18ef
commit fa40250863
4 changed files with 146 additions and 49 deletions

View File

@ -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
}
}
}

View File

@ -52,8 +52,8 @@ import org.apache.activemq.util.URISupport.CompositeData;
* Connections. <p/> 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<String,String> map = URISupport.parseQuery(this.brokerURL.getQuery());
Map<String,Object> 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<String,Object> 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 <a
* href="http://activemq.apache.org/message-groups.html">Message Groups</a>
*
*
* @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

View File

@ -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());
}

View File

@ -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<String, String> rc = new HashMap<String, String>();
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<String, String> 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<String, String> 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<String, String> params) throws URISyntaxException {
String s = createQueryString(params);
if (s.length() == 0) {
s = null;