diff --git a/camel-core/src/main/java/org/apache/camel/CamelContext.java b/camel-core/src/main/java/org/apache/camel/CamelContext.java
index df87a448932c7..19c308b2155a7 100644
--- a/camel-core/src/main/java/org/apache/camel/CamelContext.java
+++ b/camel-core/src/main/java/org/apache/camel/CamelContext.java
@@ -1128,6 +1128,30 @@ public interface CamelContext extends SuspendableService, RuntimeConfiguration {
@Deprecated
void setLazyLoadTypeConverters(Boolean lazyLoadTypeConverters);
+ /**
+ * Whether or not type converter statistics is enabled.
+ *
+ * By default the type converter utilization statistics is disabled.
+ * Notice: If enabled then there is a slight performance impact under very heavy load.
+ *
+ * @return true if enabled, false if disabled (default).
+ */
+ Boolean isTypeConverterStatisticsEnabled();
+
+ /**
+ * Sets whether or not type converter statistics is enabled.
+ *
+ * By default the type converter utilization statistics is disabled.
+ * Notice: If enabled then there is a slight performance impact under very heavy load.
+ *
+ * You can enable/disable the statistics at runtime using the
+ * {@link org.apache.camel.spi.TypeConverterRegistry#getStatistics()#setTypeConverterStatisticsEnabled(Boolean)} method,
+ * or from JMX on the {@link org.apache.camel.api.management.mbean.ManagedTypeConverterRegistryMBean} mbean.
+ *
+ * @param typeConverterStatisticsEnabled true to enable, false to disable
+ */
+ void setTypeConverterStatisticsEnabled(Boolean typeConverterStatisticsEnabled);
+
/**
* Whether or not MDC logging is being enabled.
*
diff --git a/camel-core/src/main/java/org/apache/camel/api/management/mbean/ManagedTypeConverterRegistryMBean.java b/camel-core/src/main/java/org/apache/camel/api/management/mbean/ManagedTypeConverterRegistryMBean.java
index b0aeab8b0e64c..a7f53aefbf6aa 100644
--- a/camel-core/src/main/java/org/apache/camel/api/management/mbean/ManagedTypeConverterRegistryMBean.java
+++ b/camel-core/src/main/java/org/apache/camel/api/management/mbean/ManagedTypeConverterRegistryMBean.java
@@ -39,4 +39,10 @@ public interface ManagedTypeConverterRegistryMBean extends ManagedServiceMBean {
@ManagedOperation(description = "Resets the type conversion counters")
void resetTypeConversionCounters();
+ @ManagedAttribute(description = "Utilization statistics enabled")
+ boolean isStatisticsEnabled();
+
+ @ManagedAttribute(description = "Utilization statistics enabled")
+ void setStatisticsEnabled(boolean statisticsEnabled);
+
}
diff --git a/camel-core/src/main/java/org/apache/camel/component/bean/BeanInfo.java b/camel-core/src/main/java/org/apache/camel/component/bean/BeanInfo.java
index 555502dcc2773..a511943cf2708 100644
--- a/camel-core/src/main/java/org/apache/camel/component/bean/BeanInfo.java
+++ b/camel-core/src/main/java/org/apache/camel/component/bean/BeanInfo.java
@@ -500,7 +500,7 @@ protected MethodInfo chooseMethod(Object pojo, Exchange exchange, String name) t
if (noParameters && localOperationsWithNoBody.size() == 1) {
// if there was a method name configured and it has no parameters, then use the method with no body (eg no parameters)
return localOperationsWithNoBody.get(0);
- } else if (localOperationsWithBody.size() == 1) {
+ } else if (!noParameters && localOperationsWithBody.size() == 1) {
// if there is one method with body then use that one
return localOperationsWithBody.get(0);
}
@@ -874,9 +874,15 @@ private boolean matchMethod(Method method, String methodName) {
return false;
}
+ // is it a method with no parameters
+ boolean noParameters = methodName.endsWith("()");
+ if (noParameters) {
+ return method.getParameterTypes().length == 0;
+ }
+
// match qualifier types which is used to select among overloaded methods
String types = ObjectHelper.between(methodName, "(", ")");
- if (types != null) {
+ if (ObjectHelper.isNotEmpty(types)) {
// we must qualify based on types to match method
String[] parameters = StringQuoteHelper.splitSafeQuote(types, ',');
Iterator> it = ObjectHelper.createIterator(parameters);
diff --git a/camel-core/src/main/java/org/apache/camel/component/bean/MethodInfo.java b/camel-core/src/main/java/org/apache/camel/component/bean/MethodInfo.java
index 473fee6eb965b..44622d12f92be 100644
--- a/camel-core/src/main/java/org/apache/camel/component/bean/MethodInfo.java
+++ b/camel-core/src/main/java/org/apache/camel/component/bean/MethodInfo.java
@@ -426,8 +426,8 @@ public T evaluate(Exchange exchange, Class type) {
if (methodParameters != null) {
// split the parameters safely separated by comma, but beware that we can have
// quoted parameters which contains comma as well, so do a safe quote split
- String[] parameters = StringQuoteHelper.splitSafeQuote(methodParameters, ',');
- it = ObjectHelper.createIterator(parameters);
+ String[] parameters = StringQuoteHelper.splitSafeQuote(methodParameters, ',', false);
+ it = ObjectHelper.createIterator(parameters, ",", true);
}
// remove headers as they should not be propagated
@@ -490,8 +490,6 @@ private Object evaluateParameterValue(Exchange exchange, int index, Object param
// convert the parameter value to a String
String exp = exchange.getContext().getTypeConverter().convertTo(String.class, exchange, parameterValue);
if (exp != null) {
- // must trim first as there may be spaces between parameters
- exp = exp.trim();
// check if its a valid parameter value
boolean valid = BeanHelper.isValidParameterValue(exp);
diff --git a/camel-core/src/main/java/org/apache/camel/component/directvm/DirectVmProcessor.java b/camel-core/src/main/java/org/apache/camel/component/directvm/DirectVmProcessor.java
index 26cedfe9a62b9..5cec883212011 100644
--- a/camel-core/src/main/java/org/apache/camel/component/directvm/DirectVmProcessor.java
+++ b/camel-core/src/main/java/org/apache/camel/component/directvm/DirectVmProcessor.java
@@ -16,9 +16,10 @@
*/
package org.apache.camel.component.directvm;
+import org.apache.camel.AsyncCallback;
import org.apache.camel.Exchange;
import org.apache.camel.Processor;
-import org.apache.camel.processor.DelegateProcessor;
+import org.apache.camel.processor.DelegateAsyncProcessor;
import org.apache.camel.util.ExchangeHelper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -26,7 +27,7 @@
/**
*
*/
-public final class DirectVmProcessor extends DelegateProcessor {
+public final class DirectVmProcessor extends DelegateAsyncProcessor {
private static final transient Logger LOG = LoggerFactory.getLogger(DirectVmProcessor.class);
private final DirectVmEndpoint endpoint;
@@ -37,9 +38,9 @@ public DirectVmProcessor(Processor processor, DirectVmEndpoint endpoint) {
}
@Override
- public void process(Exchange exchange) throws Exception {
+ public boolean process(final Exchange exchange, final AsyncCallback callback) {
// need to use a copy of the incoming exchange, so we route using this camel context
- Exchange copy = prepareExchange(exchange);
+ final Exchange copy = prepareExchange(exchange);
ClassLoader current = Thread.currentThread().getContextClassLoader();
boolean changed = false;
@@ -51,10 +52,19 @@ public void process(Exchange exchange) throws Exception {
Thread.currentThread().setContextClassLoader(appClassLoader);
changed = true;
}
- getProcessor().process(copy);
+ return getProcessor().process(copy, new AsyncCallback() {
+ @Override
+ public void done(boolean done) {
+ try {
+ // make sure to copy results back
+ ExchangeHelper.copyResults(exchange, copy);
+ } finally {
+ // must call callback when we are done
+ callback.done(done);
+ }
+ }
+ });
} finally {
- // make sure to copy results back
- ExchangeHelper.copyResults(exchange, copy);
// restore TCCL if it was changed during processing
if (changed) {
LOG.trace("Restoring Thread ContextClassLoader to {}", current);
diff --git a/camel-core/src/main/java/org/apache/camel/impl/DefaultCamelContext.java b/camel-core/src/main/java/org/apache/camel/impl/DefaultCamelContext.java
index a911c1fb90d67..3e270637240b7 100644
--- a/camel-core/src/main/java/org/apache/camel/impl/DefaultCamelContext.java
+++ b/camel-core/src/main/java/org/apache/camel/impl/DefaultCamelContext.java
@@ -175,6 +175,7 @@ public class DefaultCamelContext extends ServiceSupport implements ModelCamelCon
private Boolean handleFault = Boolean.FALSE;
private Boolean disableJMX = Boolean.FALSE;
private Boolean lazyLoadTypeConverters = Boolean.FALSE;
+ private Boolean typeConverterStatisticsEnabled = Boolean.FALSE;
private Boolean useMDCLogging = Boolean.FALSE;
private Boolean useBreadcrumb = Boolean.TRUE;
private Long delay;
@@ -2152,6 +2153,10 @@ protected void forceLazyInitialization() {
getLanguageResolver();
getTypeConverterRegistry();
getTypeConverter();
+
+ if (isTypeConverterStatisticsEnabled() != null) {
+ getTypeConverterRegistry().getStatistics().setStatisticsEnabled(isTypeConverterStatisticsEnabled());
+ }
}
/**
@@ -2422,6 +2427,14 @@ public void setLazyLoadTypeConverters(Boolean lazyLoadTypeConverters) {
this.lazyLoadTypeConverters = lazyLoadTypeConverters;
}
+ public Boolean isTypeConverterStatisticsEnabled() {
+ return typeConverterStatisticsEnabled != null && typeConverterStatisticsEnabled;
+ }
+
+ public void setTypeConverterStatisticsEnabled(Boolean typeConverterStatisticsEnabled) {
+ this.typeConverterStatisticsEnabled = typeConverterStatisticsEnabled;
+ }
+
public Boolean isUseMDCLogging() {
return useMDCLogging != null && useMDCLogging;
}
diff --git a/camel-core/src/main/java/org/apache/camel/impl/converter/BaseTypeConverterRegistry.java b/camel-core/src/main/java/org/apache/camel/impl/converter/BaseTypeConverterRegistry.java
index b57015cff41f6..a00f62cbe3531 100644
--- a/camel-core/src/main/java/org/apache/camel/impl/converter/BaseTypeConverterRegistry.java
+++ b/camel-core/src/main/java/org/apache/camel/impl/converter/BaseTypeConverterRegistry.java
@@ -107,10 +107,14 @@ public T convertTo(Class type, Exchange exchange, Object value) {
Object answer;
try {
- attemptCounter.incrementAndGet();
+ if (statistics.isStatisticsEnabled()) {
+ attemptCounter.incrementAndGet();
+ }
answer = doConvertTo(type, exchange, value, false);
} catch (Exception e) {
- failedCounter.incrementAndGet();
+ if (statistics.isStatisticsEnabled()) {
+ failedCounter.incrementAndGet();
+ }
// if its a ExecutionException then we have rethrow it as its not due to failed conversion
// this is special for FutureTypeConverter
boolean execution = ObjectHelper.getException(ExecutionException.class, e) != null
@@ -127,12 +131,15 @@ public T convertTo(Class type, Exchange exchange, Object value) {
}
}
if (answer == Void.TYPE) {
- // Could not find suitable conversion
- missCounter.incrementAndGet();
+ if (statistics.isStatisticsEnabled()) {
+ missCounter.incrementAndGet();
+ }
// Could not find suitable conversion
return null;
} else {
- hitCounter.incrementAndGet();
+ if (statistics.isStatisticsEnabled()) {
+ hitCounter.incrementAndGet();
+ }
return (T) answer;
}
}
@@ -151,10 +158,14 @@ public T mandatoryConvertTo(Class type, Exchange exchange, Object value)
Object answer;
try {
- attemptCounter.incrementAndGet();
+ if (statistics.isStatisticsEnabled()) {
+ attemptCounter.incrementAndGet();
+ }
answer = doConvertTo(type, exchange, value, false);
} catch (Exception e) {
- failedCounter.incrementAndGet();
+ if (statistics.isStatisticsEnabled()) {
+ failedCounter.incrementAndGet();
+ }
// error occurred during type conversion
if (e instanceof TypeConversionException) {
throw (TypeConversionException) e;
@@ -163,12 +174,15 @@ public T mandatoryConvertTo(Class type, Exchange exchange, Object value)
}
}
if (answer == Void.TYPE || value == null) {
- // Could not find suitable conversion
- missCounter.incrementAndGet();
+ if (statistics.isStatisticsEnabled()) {
+ missCounter.incrementAndGet();
+ }
// Could not find suitable conversion
throw new NoTypeConversionAvailableException(value, type);
} else {
- hitCounter.incrementAndGet();
+ if (statistics.isStatisticsEnabled()) {
+ hitCounter.incrementAndGet();
+ }
return (T) answer;
}
}
@@ -187,18 +201,26 @@ public T tryConvertTo(Class type, Exchange exchange, Object value) {
Object answer;
try {
- attemptCounter.incrementAndGet();
+ if (statistics.isStatisticsEnabled()) {
+ attemptCounter.incrementAndGet();
+ }
answer = doConvertTo(type, exchange, value, true);
} catch (Exception e) {
- failedCounter.incrementAndGet();
+ if (statistics.isStatisticsEnabled()) {
+ failedCounter.incrementAndGet();
+ }
return null;
}
if (answer == Void.TYPE) {
- missCounter.incrementAndGet();
// Could not find suitable conversion
+ if (statistics.isStatisticsEnabled()) {
+ missCounter.incrementAndGet();
+ }
return null;
} else {
- hitCounter.incrementAndGet();
+ if (statistics.isStatisticsEnabled()) {
+ hitCounter.incrementAndGet();
+ }
return (T) answer;
}
}
@@ -517,9 +539,11 @@ protected void doStart() throws Exception {
@Override
protected void doStop() throws Exception {
// log utilization statistics when stopping, including mappings
- String info = statistics.toString();
- info += String.format(" mappings[total=%s, misses=%s]", typeMappings.size(), misses.size());
- log.info(info);
+ if (statistics.isStatisticsEnabled()) {
+ String info = statistics.toString();
+ info += String.format(" mappings[total=%s, misses=%s]", typeMappings.size(), misses.size());
+ log.info(info);
+ }
typeMappings.clear();
misses.clear();
@@ -531,6 +555,8 @@ protected void doStop() throws Exception {
*/
private final class UtilizationStatistics implements Statistics {
+ private boolean statisticsEnabled;
+
@Override
public long getAttemptCounter() {
return attemptCounter.get();
@@ -559,6 +585,16 @@ public void reset() {
failedCounter.set(0);
}
+ @Override
+ public boolean isStatisticsEnabled() {
+ return statisticsEnabled;
+ }
+
+ @Override
+ public void setStatisticsEnabled(boolean statisticsEnabled) {
+ this.statisticsEnabled = statisticsEnabled;
+ }
+
@Override
public String toString() {
return String.format("TypeConverterRegistry utilization[attempts=%s, hits=%s, misses=%s, failures=%s]",
diff --git a/camel-core/src/main/java/org/apache/camel/management/mbean/ManagedTypeConverterRegistry.java b/camel-core/src/main/java/org/apache/camel/management/mbean/ManagedTypeConverterRegistry.java
index 5b2ea41fcc250..55af467a0a7b1 100644
--- a/camel-core/src/main/java/org/apache/camel/management/mbean/ManagedTypeConverterRegistry.java
+++ b/camel-core/src/main/java/org/apache/camel/management/mbean/ManagedTypeConverterRegistry.java
@@ -57,4 +57,12 @@ public long getFailedCounter() {
public void resetTypeConversionCounters() {
registry.getStatistics().reset();
}
+
+ public boolean isStatisticsEnabled() {
+ return registry.getStatistics().isStatisticsEnabled();
+ }
+
+ public void setStatisticsEnabled(boolean statisticsEnabled) {
+ registry.getStatistics().setStatisticsEnabled(statisticsEnabled);
+ }
}
diff --git a/camel-core/src/main/java/org/apache/camel/spi/TypeConverterRegistry.java b/camel-core/src/main/java/org/apache/camel/spi/TypeConverterRegistry.java
index 719e692033b5e..b7c90e2b85a20 100644
--- a/camel-core/src/main/java/org/apache/camel/spi/TypeConverterRegistry.java
+++ b/camel-core/src/main/java/org/apache/camel/spi/TypeConverterRegistry.java
@@ -21,6 +21,9 @@
/**
* Registry for type converters.
+ *
+ * The utilization {@link Statistics} is by default disabled, as it has a slight performance impact under very high
+ * concurrent load. The statistics can be enabled using {@link Statistics#setStatisticsEnabled(boolean)} method.
*
* @version
*/
@@ -55,6 +58,18 @@ interface Statistics {
* Reset the counters
*/
void reset();
+
+ /**
+ * Whether statistics is enabled.
+ */
+ boolean isStatisticsEnabled();
+
+ /**
+ * Sets whether statistics is enabled.
+ *
+ * @param statisticsEnabled true to enable
+ */
+ void setStatisticsEnabled(boolean statisticsEnabled);
}
/**
diff --git a/camel-core/src/main/java/org/apache/camel/support/ServiceSupport.java b/camel-core/src/main/java/org/apache/camel/support/ServiceSupport.java
index 52e07067d18b9..85864c0a7e49b 100644
--- a/camel-core/src/main/java/org/apache/camel/support/ServiceSupport.java
+++ b/camel-core/src/main/java/org/apache/camel/support/ServiceSupport.java
@@ -22,6 +22,7 @@
import org.apache.camel.ServiceStatus;
import org.apache.camel.StatefulService;
+import org.apache.camel.util.IOHelper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -277,17 +278,21 @@ public synchronized String getVersion() {
if (version != null) {
return version;
}
-
+ InputStream is = null;
// try to load from maven properties first
try {
Properties p = new Properties();
- InputStream is = getClass().getResourceAsStream("/META-INF/maven/org.apache.camel/camel-core/pom.properties");
+ is = getClass().getResourceAsStream("/META-INF/maven/org.apache.camel/camel-core/pom.properties");
if (is != null) {
p.load(is);
version = p.getProperty("version", "");
}
} catch (Exception e) {
// ignore
+ } finally {
+ if (is != null) {
+ IOHelper.close(is);
+ }
}
// fallback to using Java API
diff --git a/camel-core/src/main/java/org/apache/camel/util/IntrospectionSupport.java b/camel-core/src/main/java/org/apache/camel/util/IntrospectionSupport.java
index 361c22260ef73..f6be206ec051b 100755
--- a/camel-core/src/main/java/org/apache/camel/util/IntrospectionSupport.java
+++ b/camel-core/src/main/java/org/apache/camel/util/IntrospectionSupport.java
@@ -225,11 +225,15 @@ public static boolean getProperties(Object target, Map propertie
if (info.isGetter && info.hasGetterAndSetter) {
String name = info.getterOrSetterShorthandName;
try {
+ // we may want to set options on classes that has package view visibility, so override the accessible
+ method.setAccessible(true);
Object value = method.invoke(target);
properties.put(optionPrefix + name, value);
rc = true;
} catch (Exception e) {
- // ignore
+ if (LOG.isTraceEnabled()) {
+ LOG.trace("Error invoking getter method " + method + ". This exception is ignored.", e);
+ }
}
}
}
@@ -483,6 +487,8 @@ public static boolean setProperty(CamelContext context, TypeConverter typeConver
try {
// If the type is null or it matches the needed type, just use the value directly
if (value == null || parameterType.isAssignableFrom(ref.getClass())) {
+ // we may want to set options on classes that has package view visibility, so override the accessible
+ setter.setAccessible(true);
setter.invoke(target, ref);
if (LOG.isDebugEnabled()) {
LOG.debug("Configured property: {} on bean: {} with value: {}", new Object[]{name, target, ref});
@@ -491,6 +497,8 @@ public static boolean setProperty(CamelContext context, TypeConverter typeConver
} else {
// We need to convert it
Object convertedValue = convert(typeConverter, parameterType, ref);
+ // we may want to set options on classes that has package view visibility, so override the accessible
+ setter.setAccessible(true);
setter.invoke(target, convertedValue);
if (LOG.isDebugEnabled()) {
LOG.debug("Configured property: {} on bean: {} with value: {}", new Object[]{name, target, ref});
@@ -509,6 +517,8 @@ public static boolean setProperty(CamelContext context, TypeConverter typeConver
}
}
// ignore exceptions as there could be another setter method where we could type convert successfully
+ } catch (SecurityException e) {
+ typeConversionFailed = e;
} catch (NoTypeConversionAvailableException e) {
typeConversionFailed = e;
} catch (IllegalArgumentException e) {
diff --git a/camel-core/src/main/java/org/apache/camel/util/MessageHelper.java b/camel-core/src/main/java/org/apache/camel/util/MessageHelper.java
index 7bab1342b5f3c..61be0f0a5afdf 100644
--- a/camel-core/src/main/java/org/apache/camel/util/MessageHelper.java
+++ b/camel-core/src/main/java/org/apache/camel/util/MessageHelper.java
@@ -23,6 +23,7 @@
import java.io.Writer;
import java.util.Map;
import java.util.TreeMap;
+import javax.xml.transform.Source;
import javax.xml.transform.stream.StreamSource;
import org.apache.camel.BytesSource;
@@ -185,9 +186,8 @@ public static String extractBodyForLogging(Message message, String prepend) {
* @param message the message
* @param prepend a message to prepend
* @param allowStreams whether or not streams is allowed
- * @param allowFiles whether or not files is allowed
- * @param maxChars limit to maximum number of chars. Use 0 or negative value
- * to not limit at all.
+ * @param allowFiles whether or not files is allowed (currently not in use)
+ * @param maxChars limit to maximum number of chars. Use 0 or negative value to not limit at all.
* @return the logging message
*/
public static String extractBodyForLogging(Message message, String prepend, boolean allowStreams, boolean allowFiles, int maxChars) {
@@ -197,12 +197,10 @@ public static String extractBodyForLogging(Message message, String prepend, bool
}
if (!allowStreams) {
- if (obj instanceof StreamSource && !(obj instanceof StringSource || obj instanceof BytesSource)) {
- /*
- * Generally do not log StreamSources but as StringSource and
- * ByteSource are memory based they are ok
- */
- return prepend + "[Body is instance of java.xml.transform.StreamSource]";
+ if (obj instanceof Source && !(obj instanceof StringSource || obj instanceof BytesSource)) {
+ // for Source its only StringSource or BytesSource that is okay as they are memory based
+ // all other kinds we should not touch the body
+ return prepend + "[Body is instance of java.xml.transform.Source]";
} else if (obj instanceof StreamCache) {
return prepend + "[Body is instance of org.apache.camel.StreamCache]";
} else if (obj instanceof InputStream) {
diff --git a/camel-core/src/main/java/org/apache/camel/util/StringQuoteHelper.java b/camel-core/src/main/java/org/apache/camel/util/StringQuoteHelper.java
index 3efa4debc18ab..452f459ba12fd 100644
--- a/camel-core/src/main/java/org/apache/camel/util/StringQuoteHelper.java
+++ b/camel-core/src/main/java/org/apache/camel/util/StringQuoteHelper.java
@@ -61,21 +61,40 @@ public static String[] splitSafeQuote(String input, char separator, boolean trim
return null;
}
+ if (input.indexOf(separator) == -1) {
+ // no separator in data, so return single string with input as is
+ return new String[]{trim ? input.trim() : input};
+ }
+
List answer = new ArrayList();
StringBuilder sb = new StringBuilder();
boolean singleQuoted = false;
boolean doubleQuoted = false;
+ boolean skipLeadingWhitespace = true;
for (int i = 0; i < input.length(); i++) {
char ch = input.charAt(i);
+ char prev = i > 0 ? input.charAt(i - 1) : 0;
if (ch == '\'') {
+ if (singleQuoted && prev == ch && sb.length() == 0) {
+ // its an empty quote so add empty text
+ answer.add("");
+ }
singleQuoted = !singleQuoted;
continue;
} else if (ch == '"') {
+ if (doubleQuoted && prev == ch && sb.length() == 0) {
+ // its an empty quote so add empty text
+ answer.add("");
+ }
doubleQuoted = !doubleQuoted;
continue;
+ } else if (ch == ' ') {
+ if (!singleQuoted && !doubleQuoted && skipLeadingWhitespace) {
+ continue;
+ }
} else if (ch == separator) {
// add as answer if we are not in a quote
if (!singleQuoted && !doubleQuoted && sb.length() > 0) {
diff --git a/camel-core/src/test/java/org/apache/camel/component/xslt/SAXSourceLogBodyTest.java b/camel-core/src/test/java/org/apache/camel/component/xslt/SAXSourceLogBodyTest.java
new file mode 100644
index 0000000000000..219f8be00356b
--- /dev/null
+++ b/camel-core/src/test/java/org/apache/camel/component/xslt/SAXSourceLogBodyTest.java
@@ -0,0 +1,70 @@
+/**
+ * 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.xslt;
+
+import java.io.File;
+import java.io.InputStream;
+import javax.xml.transform.sax.SAXSource;
+
+import org.xml.sax.InputSource;
+import org.xml.sax.XMLReader;
+import org.xml.sax.helpers.XMLReaderFactory;
+
+import org.apache.camel.ContextTestSupport;
+import org.apache.camel.Exchange;
+import org.apache.camel.LoggingLevel;
+import org.apache.camel.Processor;
+import org.apache.camel.builder.RouteBuilder;
+
+/**
+ *
+ */
+public class SAXSourceLogBodyTest extends ContextTestSupport {
+
+ public void testSAXSource() throws Exception {
+ getMockEndpoint("mock:result").expectedMessageCount(1);
+
+ template.sendBody("direct:start", new File("src/test/resources/xslt/staff/staff.xml"));
+
+ assertMockEndpointsSatisfied();
+ }
+
+ @Override
+ protected RouteBuilder createRouteBuilder() throws Exception {
+ return new RouteBuilder() {
+ @Override
+ public void configure() throws Exception {
+ from("direct:start").streamCaching()
+ // attach a SaxSource to body
+ .process(new Processor() {
+ @Override
+ public void process(Exchange exchange) throws Exception {
+ byte[] data = exchange.getIn().getBody(byte[].class);
+ InputStream is = exchange.getContext().getTypeConverter().convertTo(InputStream.class, data);
+ XMLReader xmlReader = XMLReaderFactory.createXMLReader();
+ exchange.getIn().setBody(new SAXSource(xmlReader, new InputSource(is)));
+ }
+ })
+ // The ${body} will toString the body and print it, so we need to enable stream caching
+ .log(LoggingLevel.WARN, "${body}")
+ .to("xslt:xslt/common/staff_template.xsl")
+ .to("log:result")
+ .to("mock:result");
+ }
+ };
+ }
+}
diff --git a/camel-core/src/test/java/org/apache/camel/impl/TypeConverterRegistryPerformanceTest.java b/camel-core/src/test/java/org/apache/camel/impl/TypeConverterRegistryPerformanceTest.java
new file mode 100644
index 0000000000000..0bdbe0c2c659d
--- /dev/null
+++ b/camel-core/src/test/java/org/apache/camel/impl/TypeConverterRegistryPerformanceTest.java
@@ -0,0 +1,75 @@
+/**
+ * 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.impl;
+
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.TimeUnit;
+
+import org.w3c.dom.Document;
+
+import org.apache.camel.ContextTestSupport;
+import org.apache.camel.util.StopWatch;
+
+public class TypeConverterRegistryPerformanceTest extends ContextTestSupport {
+
+ private int pool = 100;
+ private int inner = 10;
+ private int size = 20000;
+
+ private ExecutorService executorService;
+ private CountDownLatch latch;
+
+ public void testManual() throws Exception {
+ // noop
+ }
+
+ public void disbledtestPerformance() throws Exception {
+ // force converter to be loaded on startup
+ Document dom = context.getTypeConverter().convertTo(Document.class, "World");
+ assertNotNull(dom);
+
+ StopWatch watch = new StopWatch();
+
+ latch = new CountDownLatch(size);
+ executorService = Executors.newFixedThreadPool(pool);
+
+ for (int i = 0; i < size; i++) {
+ executorService.submit(new Runnable() {
+ @Override
+ public void run() {
+ for (int j = 0; j < inner; j++) {
+ Document dom = context.getTypeConverter().convertTo(Document.class, "World");
+ assertNotNull(dom);
+ }
+ latch.countDown();
+ }
+ });
+ }
+
+ assertTrue("Should all work", latch.await(2, TimeUnit.MINUTES));
+ log.info("Took " + watch.taken());
+
+ executorService.shutdownNow();
+ }
+
+ @Override
+ public boolean isUseRouteBuilder() {
+ return false;
+ }
+}
diff --git a/camel-core/src/test/java/org/apache/camel/impl/TypeConverterRegistryStatisticsEnabledTest.java b/camel-core/src/test/java/org/apache/camel/impl/TypeConverterRegistryStatisticsEnabledTest.java
new file mode 100644
index 0000000000000..609c61d9d0177
--- /dev/null
+++ b/camel-core/src/test/java/org/apache/camel/impl/TypeConverterRegistryStatisticsEnabledTest.java
@@ -0,0 +1,86 @@
+/**
+ * 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.impl;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.ContextTestSupport;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.spi.TypeConverterRegistry;
+
+/**
+ * @version
+ */
+public class TypeConverterRegistryStatisticsEnabledTest extends ContextTestSupport {
+
+ @Override
+ protected CamelContext createCamelContext() throws Exception {
+ CamelContext context = super.createCamelContext();
+ context.setTypeConverterStatisticsEnabled(true);
+ return context;
+ }
+
+ public void testTypeConverterRegistry() throws Exception {
+ getMockEndpoint("mock:a").expectedMessageCount(2);
+
+ template.sendBody("direct:start", "3");
+ template.sendBody("direct:start", "7");
+
+ assertMockEndpointsSatisfied();
+
+ TypeConverterRegistry reg = context.getTypeConverterRegistry();
+ assertTrue("Should be enabled", reg.getStatistics().isStatisticsEnabled());
+
+ Long failed = reg.getStatistics().getFailedCounter();
+ assertEquals(0, failed.intValue());
+ Long miss = reg.getStatistics().getMissCounter();
+ assertEquals(0, miss.intValue());
+
+ try {
+ template.sendBody("direct:start", "foo");
+ fail("Should have thrown exception");
+ } catch (Exception e) {
+ // expected
+ }
+
+ // should now have a failed
+ failed = reg.getStatistics().getFailedCounter();
+ assertEquals(1, failed.intValue());
+ miss = reg.getStatistics().getMissCounter();
+ assertEquals(0, miss.intValue());
+
+ // reset
+ reg.getStatistics().reset();
+
+ failed = reg.getStatistics().getFailedCounter();
+ assertEquals(0, failed.intValue());
+ miss = reg.getStatistics().getMissCounter();
+ assertEquals(0, miss.intValue());
+ }
+
+ @Override
+ protected RouteBuilder createRouteBuilder() throws Exception {
+ return new RouteBuilder() {
+ @Override
+ public void configure() throws Exception {
+ from("direct:start").routeId("foo")
+ .convertBodyTo(int.class)
+ .to("mock:a");
+ }
+ };
+ }
+
+}
diff --git a/camel-core/src/test/java/org/apache/camel/language/simple/SimpleTest.java b/camel-core/src/test/java/org/apache/camel/language/simple/SimpleTest.java
index f268980012e4c..6240ff38556bc 100644
--- a/camel-core/src/test/java/org/apache/camel/language/simple/SimpleTest.java
+++ b/camel-core/src/test/java/org/apache/camel/language/simple/SimpleTest.java
@@ -1124,6 +1124,16 @@ public void testBodyOgnlReplaceEscapedBackslashChar() throws Exception {
assertExpression("${body.replace('\\', '\\\\')}", "foo\\\\bar\\\\baz");
}
+ public void testBodyOgnlReplaceFirst() throws Exception {
+ exchange.getIn().setBody("http:camel.apache.org");
+
+ assertExpression("${body.replaceFirst('http:', 'http4:')}", "http4:camel.apache.org");
+ assertExpression("${body.replaceFirst('http:', '')}", "camel.apache.org");
+ assertExpression("${body.replaceFirst('http:', ' ')}", " camel.apache.org");
+ assertExpression("${body.replaceFirst('http:', ' ')}", " camel.apache.org");
+ assertExpression("${body.replaceFirst('http:',' ')}", " camel.apache.org");
+ }
+
public void testClassSimpleName() throws Exception {
Animal tiger = new Animal("Tony the Tiger", 13);
exchange.getIn().setBody(tiger);
diff --git a/camel-core/src/test/java/org/apache/camel/management/ManagedTypeConverterRegistryTest.java b/camel-core/src/test/java/org/apache/camel/management/ManagedTypeConverterRegistryTest.java
index 957d2a2e29c6b..e0f9483a5a708 100644
--- a/camel-core/src/test/java/org/apache/camel/management/ManagedTypeConverterRegistryTest.java
+++ b/camel-core/src/test/java/org/apache/camel/management/ManagedTypeConverterRegistryTest.java
@@ -17,6 +17,7 @@
package org.apache.camel.management;
import java.util.Set;
+import javax.management.Attribute;
import javax.management.MBeanServer;
import javax.management.ObjectName;
@@ -50,6 +51,13 @@ public void testTypeConverterRegistry() throws Exception {
}
assertNotNull("Cannot find DefaultTypeConverter", name);
+ // is disabled by default
+ Boolean enabled = (Boolean) mbeanServer.getAttribute(name, "StatisticsEnabled");
+ assertEquals(Boolean.FALSE, enabled);
+
+ // need to enable statistics
+ mbeanServer.setAttribute(name, new Attribute("StatisticsEnabled", Boolean.TRUE));
+
Long failed = (Long) mbeanServer.getAttribute(name, "FailedCounter");
assertEquals(0, failed.intValue());
Long miss = (Long) mbeanServer.getAttribute(name, "MissCounter");
diff --git a/camel-core/src/test/java/org/apache/camel/util/StingQuoteHelperTest.java b/camel-core/src/test/java/org/apache/camel/util/StingQuoteHelperTest.java
index af3452169e04b..fea93b91829ca 100644
--- a/camel-core/src/test/java/org/apache/camel/util/StingQuoteHelperTest.java
+++ b/camel-core/src/test/java/org/apache/camel/util/StingQuoteHelperTest.java
@@ -27,7 +27,8 @@ public void testSplitSafeQuote() throws Exception {
assertEquals(null, StringQuoteHelper.splitSafeQuote(null, ','));
String[] out = StringQuoteHelper.splitSafeQuote("", ',');
- assertEquals(0, out.length);
+ assertEquals(1, out.length);
+ assertEquals("", out[0]);
out = StringQuoteHelper.splitSafeQuote(" ", ',');
assertEquals(1, out.length);
@@ -82,10 +83,38 @@ public void testSplitSafeQuote() throws Exception {
assertEquals("Hello Camel", out[0]);
assertEquals("Bye World", out[1]);
- out = StringQuoteHelper.splitSafeQuote("'Hello Camel', 'Bye World'", ',', false);
+ out = StringQuoteHelper.splitSafeQuote("'Hello Camel', ' Bye World'", ',', false);
assertEquals(2, out.length);
assertEquals("Hello Camel", out[0]);
assertEquals(" Bye World", out[1]);
+
+ out = StringQuoteHelper.splitSafeQuote("'http:', ' '", ',', false);
+ assertEquals(2, out.length);
+ assertEquals("http:", out[0]);
+ assertEquals(" ", out[1]);
+
+ out = StringQuoteHelper.splitSafeQuote("'http:', ''", ',', false);
+ assertEquals(2, out.length);
+ assertEquals("http:", out[0]);
+ assertEquals("", out[1]);
+
+ out = StringQuoteHelper.splitSafeQuote("'Hello Camel', 5, true", ',', false);
+ assertEquals(3, out.length);
+ assertEquals("Hello Camel", out[0]);
+ assertEquals("5", out[1]);
+ assertEquals("true", out[2]);
+
+ out = StringQuoteHelper.splitSafeQuote("'Hello Camel',5,true", ',', false);
+ assertEquals(3, out.length);
+ assertEquals("Hello Camel", out[0]);
+ assertEquals("5", out[1]);
+ assertEquals("true", out[2]);
+
+ out = StringQuoteHelper.splitSafeQuote(" 'Hello Camel', 5 , true ", ',', false);
+ assertEquals(3, out.length);
+ assertEquals("Hello Camel", out[0]);
+ assertEquals("5", out[1]);
+ assertEquals("true", out[2]);
}
}
diff --git a/camel-core/src/test/resources/xslt/staff/staff.xml b/camel-core/src/test/resources/xslt/staff/staff.xml
new file mode 100644
index 0000000000000..681fd0af6db24
--- /dev/null
+++ b/camel-core/src/test/resources/xslt/staff/staff.xml
@@ -0,0 +1,60 @@
+
+
+
+
+
+ Bugs Bunny
+ 03/21/1970
+ 31
+ 4895 Wabbit Hole Road
+ 865-111-1111
+
+
+
+ Daisy Duck
+ 08/09/1949
+ 51
+ 748 Golden Pond
+ 865-222-2222
+
+
+
+ Minnie Mouse
+ 04/13/1977
+ 24
+ 4064 Cheese Factory Blvd
+ 865-333-3333
+
+
+
+ Pluto
+ 07/04/1979
+ 21
+ 414 Dog Lane
+ 865-333-3333
+
+
+
+ Road Runner
+ 01/19/1953
+ 48
+ 135 Desert View Street
+ none
+
+
+
\ No newline at end of file
diff --git a/components/camel-aws/src/main/java/org/apache/camel/component/aws/s3/S3Consumer.java b/components/camel-aws/src/main/java/org/apache/camel/component/aws/s3/S3Consumer.java
index 58b157edcf66b..0128df0d83b7b 100644
--- a/components/camel-aws/src/main/java/org/apache/camel/component/aws/s3/S3Consumer.java
+++ b/components/camel-aws/src/main/java/org/apache/camel/component/aws/s3/S3Consumer.java
@@ -27,6 +27,7 @@
import com.amazonaws.services.s3.model.S3Object;
import com.amazonaws.services.s3.model.S3ObjectSummary;
+import org.apache.camel.AsyncCallback;
import org.apache.camel.Exchange;
import org.apache.camel.NoFactoryAvailableException;
import org.apache.camel.Processor;
@@ -58,7 +59,7 @@ protected int poll() throws Exception {
pendingExchanges = 0;
String bucketName = getConfiguration().getBucketName();
- LOG.trace("Quering objects in bucket [{}]...", bucketName);
+ LOG.trace("Queueing objects in bucket [{}]...", bucketName);
ListObjectsRequest listObjectsRequest = new ListObjectsRequest();
listObjectsRequest.setBucketName(bucketName);
@@ -66,15 +67,19 @@ protected int poll() throws Exception {
listObjectsRequest.setMaxKeys(maxMessagesPerPoll);
ObjectListing listObjects = getAmazonS3Client().listObjects(listObjectsRequest);
-
- LOG.trace("Found {} objects in bucket [{}]...", listObjects.getObjectSummaries().size(), bucketName);
+
+ if (LOG.isTraceEnabled()) {
+ LOG.trace("Found {} objects in bucket [{}]...", listObjects.getObjectSummaries().size(), bucketName);
+ }
Queue exchanges = createExchanges(listObjects.getObjectSummaries());
return processBatch(CastUtils.cast(exchanges));
}
protected Queue createExchanges(List s3ObjectSummaries) {
- LOG.trace("Received {} messages in this poll", s3ObjectSummaries.size());
+ if (LOG.isTraceEnabled()) {
+ LOG.trace("Received {} messages in this poll", s3ObjectSummaries.size());
+ }
Queue answer = new LinkedList();
for (S3ObjectSummary s3ObjectSummary : s3ObjectSummaries) {
@@ -91,7 +96,7 @@ public int processBatch(Queue