This is an automated email from the ASF dual-hosted git repository. davsclaus pushed a commit to branch main in repository https://gitbox.apache.org/repos/asf/camel.git
The following commit(s) were added to refs/heads/main by this push: new d1891886f2f CAMEL-19601: StreamCaching can configure allow/deny list of classes to control what can be cached or not. d1891886f2f is described below commit d1891886f2f15ac3073ce29b6c4d48e0172d27ff Author: Claus Ibsen <claus.ib...@gmail.com> AuthorDate: Thu Jul 13 13:50:13 2023 +0200 CAMEL-19601: StreamCaching can configure allow/deny list of classes to control what can be cached or not. --- .../main/camel-main-configuration-metadata.json | 2 + .../apache/camel/catalog/schemas/camel-spring.xsd | 20 +++ .../processor/SpringStreamCachingStrategyTest.java | 5 + .../processor/SpringStreamCachingStrategyTest.xml | 3 +- .../apache/camel/spi/StreamCachingStrategy.java | 37 +++++ .../impl/engine/DefaultStreamCachingStrategy.java | 87 ++++++++++- .../org/apache/camel/core/xml/streamCaching.json | 24 +-- .../core/xml/AbstractCamelContextFactoryBean.java | 8 + .../xml/CamelStreamCachingStrategyDefinition.java | 28 ++++ .../processor/StreamCachingAllowDenyTest.java | 161 +++++++++++++++++++++ .../MainConfigurationPropertiesConfigurer.java | 12 ++ .../camel-main-configuration-metadata.json | 2 + core/camel-main/src/main/docs/main.adoc | 4 +- .../camel/main/DefaultConfigurationConfigurer.java | 2 + .../camel/main/DefaultConfigurationProperties.java | 44 ++++++ .../mbean/ManagedStreamCachingStrategyMBean.java | 6 + .../mbean/ManagedStreamCachingStrategy.java | 22 +++ 17 files changed, 453 insertions(+), 14 deletions(-) diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/main/camel-main-configuration-metadata.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/main/camel-main-configuration-metadata.json index 2d16d3f2fc2..6b495e49656 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/main/camel-main-configuration-metadata.json +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/main/camel-main-configuration-metadata.json @@ -109,8 +109,10 @@ { "name": "camel.main.startupRecorderProfile", "description": "To use a specific Java Flight Recorder profile configuration, such as default or profile. The default is default.", "sourceType": "org.apache.camel.main.DefaultConfigurationProperties", "type": "string", "javaType": "java.lang.String", "defaultValue": "default" }, { "name": "camel.main.startupRecorderRecording", "description": "To enable Java Flight Recorder to start a recording and automatic dump the recording to disk after startup is complete. This requires that camel-jfr is on the classpath, and to enable this option.", "sourceType": "org.apache.camel.main.DefaultConfigurationProperties", "type": "boolean", "javaType": "boolean", "defaultValue": "false" }, { "name": "camel.main.startupSummaryLevel", "description": "Controls the level of information logged during startup (and shutdown) of CamelContext.", "sourceType": "org.apache.camel.main.DefaultConfigurationProperties", "type": "object", "javaType": "org.apache.camel.StartupSummaryLevel", "defaultValue": "Default" }, + { "name": "camel.main.streamCachingAllowClasses", "description": "To filter stream caching of a given set of allowed\/denied classes. By default, all classes that are java.io.InputStream is allowed. Multiple class names can be separated by comma.", "sourceType": "org.apache.camel.main.DefaultConfigurationProperties", "type": "string", "javaType": "java.lang.String" }, { "name": "camel.main.streamCachingAnySpoolRules", "description": "Sets whether if just any of the org.apache.camel.spi.StreamCachingStrategy.SpoolRule rules returns true then shouldSpoolCache(long) returns true, to allow spooling to disk. If this option is false, then all the org.apache.camel.spi.StreamCachingStrategy.SpoolRule must return true. The default value is false which means that all the rules must return true.", "sourceType": "org.apache.camel.main.DefaultConfigurationProp [...] { "name": "camel.main.streamCachingBufferSize", "description": "Sets the stream caching buffer size to use when allocating in-memory buffers used for in-memory stream caches. The default size is 4096.", "sourceType": "org.apache.camel.main.DefaultConfigurationProperties", "type": "integer", "javaType": "int" }, + { "name": "camel.main.streamCachingDenyClasses", "description": "To filter stream caching of a given set of allowed\/denied classes. By default, all classes that are java.io.InputStream is allowed. Multiple class names can be separated by comma.", "sourceType": "org.apache.camel.main.DefaultConfigurationProperties", "type": "string", "javaType": "java.lang.String" }, { "name": "camel.main.streamCachingEnabled", "description": "Sets whether stream caching is enabled or not. While stream types (like StreamSource, InputStream and Reader) are commonly used in messaging for performance reasons, they also have an important drawback: they can only be read once. In order to be able to work with message content multiple times, the stream needs to be cached. Streams are cached in memory only (by default). If streamCachingSpoolEnabled=true, then, for large [...] { "name": "camel.main.streamCachingRemoveSpoolDirectoryWhenStopping", "description": "Whether to remove stream caching temporary directory when stopping. This option is default true.", "sourceType": "org.apache.camel.main.DefaultConfigurationProperties", "type": "boolean", "javaType": "boolean", "defaultValue": true }, { "name": "camel.main.streamCachingSpoolCipher", "description": "Sets a stream caching cipher name to use when spooling to disk to write with encryption. By default the data is not encrypted.", "sourceType": "org.apache.camel.main.DefaultConfigurationProperties", "type": "string", "javaType": "java.lang.String" }, diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/schemas/camel-spring.xsd b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/schemas/camel-spring.xsd index 686bc27ce4c..bc618f3edb9 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/schemas/camel-spring.xsd +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/schemas/camel-spring.xsd @@ -3093,6 +3093,26 @@ no longer necessary. Default is true. Default value: true To enable stream caching spooling to disk. This means, for large stream messages (over 128 KB by default) will be cached in a temporary file instead, and Camel will handle deleting the temporary file once the cached stream is no longer necessary. Default is false. Default value: false +]]> + </xs:documentation> + </xs:annotation> + </xs:attribute> + <xs:attribute name="allowClasses" type="xs:string"> + <xs:annotation> + <xs:documentation xml:lang="en"> +<![CDATA[ +To filter stream caching of a given set of allowed/denied classes. By default, all classes that are java.io.InputStream +is allowed. Multiple class names can be separated by comma. +]]> + </xs:documentation> + </xs:annotation> + </xs:attribute> + <xs:attribute name="denyClasses" type="xs:string"> + <xs:annotation> + <xs:documentation xml:lang="en"> +<![CDATA[ +To filter stream caching of a given set of allowed/denied classes. By default, all classes that are java.io.InputStream +is allowed. Multiple class names can be separated by comma. ]]> </xs:documentation> </xs:annotation> diff --git a/components/camel-spring-xml/src/test/java/org/apache/camel/spring/processor/SpringStreamCachingStrategyTest.java b/components/camel-spring-xml/src/test/java/org/apache/camel/spring/processor/SpringStreamCachingStrategyTest.java index ee65654539f..9b00b47a6b1 100644 --- a/components/camel-spring-xml/src/test/java/org/apache/camel/spring/processor/SpringStreamCachingStrategyTest.java +++ b/components/camel-spring-xml/src/test/java/org/apache/camel/spring/processor/SpringStreamCachingStrategyTest.java @@ -34,11 +34,16 @@ public class SpringStreamCachingStrategyTest extends SpringTestSupport { @Test public void testStreamCaching() { + context.getStreamCachingStrategy().start(); + assertTrue(context.getStreamCachingStrategy().isEnabled()); assertEquals(normalizePath("target/cachedir"), normalizePath(context.getStreamCachingStrategy().getSpoolDirectory().toString())); assertEquals(Integer.valueOf(4096).intValue(), context.getStreamCachingStrategy().getBufferSize()); assertEquals(Long.valueOf(8192).longValue(), context.getStreamCachingStrategy().getSpoolThreshold()); + assertEquals("java.io.ByteArrayInputStream", + context.getStreamCachingStrategy().getAllowClasses().iterator().next().getName()); + assertEquals("java.io.Reader", context.getStreamCachingStrategy().getDenyClasses().iterator().next().getName()); } } diff --git a/components/camel-spring-xml/src/test/resources/org/apache/camel/spring/processor/SpringStreamCachingStrategyTest.xml b/components/camel-spring-xml/src/test/resources/org/apache/camel/spring/processor/SpringStreamCachingStrategyTest.xml index b1383a12cc2..7265f2db271 100644 --- a/components/camel-spring-xml/src/test/resources/org/apache/camel/spring/processor/SpringStreamCachingStrategyTest.xml +++ b/components/camel-spring-xml/src/test/resources/org/apache/camel/spring/processor/SpringStreamCachingStrategyTest.xml @@ -26,7 +26,8 @@ <camelContext streamCache="true" xmlns="http://camel.apache.org/schema/spring"> - <streamCaching id="myCacheConfig" spoolEnabled="true" bufferSize="2048" spoolDirectory="target/cachedir" spoolThreshold="8192"/> + <streamCaching id="myCacheConfig" allowClasses="java.io.ByteArrayInputStream" denyClasses="java.io.Reader" + spoolEnabled="true" bufferSize="2048" spoolDirectory="target/cachedir" spoolThreshold="8192"/> <route> <from uri="direct:c"/> diff --git a/core/camel-api/src/main/java/org/apache/camel/spi/StreamCachingStrategy.java b/core/camel-api/src/main/java/org/apache/camel/spi/StreamCachingStrategy.java index 3f27a0c2d52..68de83dd718 100644 --- a/core/camel-api/src/main/java/org/apache/camel/spi/StreamCachingStrategy.java +++ b/core/camel-api/src/main/java/org/apache/camel/spi/StreamCachingStrategy.java @@ -17,6 +17,7 @@ package org.apache.camel.spi; import java.io.File; +import java.util.Collection; import org.apache.camel.Exchange; import org.apache.camel.Message; @@ -115,6 +116,42 @@ public interface StreamCachingStrategy extends StaticService { boolean isEnabled(); + /** + * To filter stream caching of a given set of allowed/denied classes. By default, all classes that are + * {@link java.io.InputStream} is allowed. + */ + void setAllowClasses(Class<?>... classes); + + /** + * To filter stream caching of a given set of allowed/denied classes. By default, all classes that are + * {@link java.io.InputStream} is allowed. Multiple class names can be separated by comma. + */ + void setAllowClasses(String names); + + /** + * To filter stream caching of a given set of allowed/denied classes. By default, all classes that are + * {@link java.io.InputStream} is allowed. + */ + Collection<Class<?>> getAllowClasses(); + + /** + * To filter stream caching of a given set of allowed/denied classes. By default, all classes that are + * {@link java.io.InputStream} is allowed. + */ + void setDenyClasses(Class<?>... classes); + + /** + * To filter stream caching of a given set of allowed/denied classes. By default, all classes that are + * {@link java.io.InputStream} is allowed. Multiple class names can be separated by comma. + */ + void setDenyClasses(String names); + + /** + * To filter stream caching of a given set of allowed/denied classes. By default, all classes that are + * {@link java.io.InputStream} is allowed. + */ + Collection<Class<?>> getDenyClasses(); + /** * Enables spooling to disk. * <p/> diff --git a/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/DefaultStreamCachingStrategy.java b/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/DefaultStreamCachingStrategy.java index 8e6cb33a4bb..f7513cb65f2 100644 --- a/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/DefaultStreamCachingStrategy.java +++ b/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/DefaultStreamCachingStrategy.java @@ -19,7 +19,10 @@ package org.apache.camel.impl.engine; import java.io.File; import java.lang.management.ManagementFactory; import java.lang.management.MemoryMXBean; +import java.util.ArrayList; +import java.util.Collection; import java.util.LinkedHashSet; +import java.util.List; import java.util.Set; import org.apache.camel.CamelContext; @@ -44,6 +47,10 @@ public class DefaultStreamCachingStrategy extends ServiceSupport implements Came private CamelContext camelContext; private boolean enabled; + private String allowClassNames; + private String denyClassNames; + private Collection<Class<?>> allowClasses; + private Collection<Class<?>> denyClasses; private boolean spoolEnabled; private File spoolDirectory; private transient String spoolDirectoryName = "${java.io.tmpdir}/camel/camel-tmp-#uuid#"; @@ -77,6 +84,34 @@ public class DefaultStreamCachingStrategy extends ServiceSupport implements Came this.enabled = enabled; } + @Override + public Collection<Class<?>> getAllowClasses() { + return allowClasses; + } + + public void setAllowClasses(Class<?>... allowClasses) { + this.allowClasses = List.of(allowClasses); + } + + @Override + public void setAllowClasses(String names) { + this.allowClassNames = names; + } + + @Override + public Collection<Class<?>> getDenyClasses() { + return denyClasses; + } + + public void setDenyClasses(Class<?>... denyClasses) { + this.denyClasses = List.of(denyClasses); + } + + @Override + public void setDenyClasses(String names) { + this.denyClassNames = names; + } + @Override public boolean isSpoolEnabled() { return spoolEnabled; @@ -223,7 +258,27 @@ public class DefaultStreamCachingStrategy extends ServiceSupport implements Came // try convert to stream cache Object body = message.getBody(); if (body != null) { - cache = camelContext.getTypeConverter().convertTo(StreamCache.class, message.getExchange(), body); + boolean allowed = allowClasses == null && denyClasses == null; + if (!allowed) { + Class<?> source = body.getClass(); + if (denyClasses != null && allowClasses != null) { + // deny takes precedence + allowed = !isAssignableFrom(source, denyClasses); + if (allowed) { + allowed = isAssignableFrom(source, allowClasses); + } + } else if (denyClasses != null) { + allowed = !isAssignableFrom(source, denyClasses); + } else { + allowed = isAssignableFrom(source, allowClasses); + } + if (LOG.isTraceEnabled()) { + LOG.trace("Cache stream from class: {} is {}", source, allowed ? "allowed" : "denied"); + } + } + if (allowed) { + cache = camelContext.getTypeConverter().convertTo(StreamCache.class, message.getExchange(), body); + } } if (cache != null) { if (LOG.isTraceEnabled()) { @@ -244,6 +299,15 @@ public class DefaultStreamCachingStrategy extends ServiceSupport implements Came return cache; } + protected static boolean isAssignableFrom(Class<?> source, Collection<Class<?>> targets) { + for (Class<?> target : targets) { + if (target.isAssignableFrom(source)) { + return true; + } + } + return false; + } + protected String resolveSpoolDirectory(String path) { if (camelContext.getManagementNameStrategy() != null) { String name = camelContext.getManagementNameStrategy().resolveManagementName(path, camelContext.getName(), false); @@ -288,6 +352,27 @@ public class DefaultStreamCachingStrategy extends ServiceSupport implements Came return; } + if (allowClassNames != null) { + if (allowClasses == null) { + allowClasses = new ArrayList<>(); + } + for (String name : allowClassNames.split(",")) { + name = name.trim(); + Class<?> clazz = camelContext.getClassResolver().resolveMandatoryClass(name); + allowClasses.add(clazz); + } + } + if (denyClassNames != null) { + if (denyClasses == null) { + denyClasses = new ArrayList<>(); + } + for (String name : denyClassNames.split(",")) { + name = name.trim(); + Class<?> clazz = camelContext.getClassResolver().resolveMandatoryClass(name); + denyClasses.add(clazz); + } + } + if (spoolUsedHeapMemoryThreshold > 99) { throw new IllegalArgumentException( "SpoolHeapMemoryWatermarkThreshold must not be higher than 99, was: " + spoolUsedHeapMemoryThreshold); diff --git a/core/camel-core-xml/src/generated/resources/org/apache/camel/core/xml/streamCaching.json b/core/camel-core-xml/src/generated/resources/org/apache/camel/core/xml/streamCaching.json index b6a0396c5de..c650f64e412 100644 --- a/core/camel-core-xml/src/generated/resources/org/apache/camel/core/xml/streamCaching.json +++ b/core/camel-core-xml/src/generated/resources/org/apache/camel/core/xml/streamCaching.json @@ -14,16 +14,18 @@ "properties": { "enabled": { "index": 0, "kind": "attribute", "displayName": "Enabled", "required": false, "type": "boolean", "javaType": "java.lang.Boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "description": "Sets whether stream caching is enabled or not. While stream types (like StreamSource, InputStream and Reader) are commonly used in messaging for performance reasons, they also have an important drawback: they can only be read once. In order to be ab [...] "spoolEnabled": { "index": 1, "kind": "attribute", "displayName": "Spool Enabled", "required": false, "type": "boolean", "javaType": "java.lang.Boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "To enable stream caching spooling to disk. This means, for large stream messages (over 128 KB by default) will be cached in a temporary file instead, and Camel will handle deleting the temporary file once the cached stream is no longer n [...] - "spoolDirectory": { "index": 2, "kind": "attribute", "displayName": "Spool Directory", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Sets the spool (temporary) directory to use for overflow and spooling to disk. If no spool directory has been explicit configured, then a temporary directory is created in the java.io.tmpdir directory." }, - "spoolCipher": { "index": 3, "kind": "attribute", "displayName": "Spool Cipher", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Sets a cipher name to use when spooling to disk to write with encryption. By default the data is not encrypted." }, - "spoolThreshold": { "index": 4, "kind": "attribute", "displayName": "Spool Threshold", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "defaultValue": "131072", "description": "Threshold in bytes when overflow to disk is activated. The default threshold is org.apache.camel.StreamCache#DEFAULT_SPOOL_THRESHOLD bytes (eg 128kb). Use -1 to disable overflow to disk." }, - "spoolUsedHeapMemoryThreshold": { "index": 5, "kind": "attribute", "displayName": "Spool Used Heap Memory Threshold", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Sets a percentage (1-99) of used heap memory threshold to activate spooling to disk." }, - "spoolUsedHeapMemoryLimit": { "index": 6, "kind": "attribute", "displayName": "Spool Used Heap Memory Limit", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Sets what the upper bounds should be when spoolUsedHeapMemoryThreshold is in use." }, - "spoolRules": { "index": 7, "kind": "attribute", "displayName": "Spool Rules", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Reference to one or more custom org.apache.camel.spi.StreamCachingStrategy.SpoolRule to use. Multiple rules can be separated by comma." }, - "bufferSize": { "index": 8, "kind": "attribute", "displayName": "Buffer Size", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "defaultValue": "4096", "description": "Sets the buffer size to use when allocating in-memory buffers used for in-memory stream caches. The default size is org.apache.camel.util.IOHelper#DEFAULT_BUFFER_SIZE" }, - "removeSpoolDirectoryWhenStopping": { "index": 9, "kind": "attribute", "displayName": "Remove Spool Directory When Stopping", "required": false, "type": "boolean", "javaType": "java.lang.Boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "description": "Whether to remove the temporary directory when stopping. This option is default true" }, - "statisticsEnabled": { "index": 10, "kind": "attribute", "displayName": "Statistics Enabled", "required": false, "type": "boolean", "javaType": "java.lang.Boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Sets whether statistics is enabled." }, - "anySpoolRules": { "index": 11, "kind": "attribute", "displayName": "Any Spool Rules", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "defaultValue": "false", "description": "Sets whether if just any of the org.apache.camel.spi.StreamCachingStrategy.SpoolRule rules returns true then shouldSpoolCache(long) returns true. If this option is false, then all the org.apache.camel.spi.StreamCachingStrategy.SpoolR [...] - "id": { "index": 12, "kind": "attribute", "displayName": "Id", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The id of this node" } + "allowClasses": { "index": 2, "kind": "attribute", "displayName": "Allow Classes", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "To filter stream caching of a given set of allowed\/denied classes. By default, all classes that are java.io.InputStream is allowed. Multiple class names can be separated by comma." }, + "denyClasses": { "index": 3, "kind": "attribute", "displayName": "Deny Classes", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "To filter stream caching of a given set of allowed\/denied classes. By default, all classes that are java.io.InputStream is allowed. Multiple class names can be separated by comma." }, + "spoolDirectory": { "index": 4, "kind": "attribute", "displayName": "Spool Directory", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Sets the spool (temporary) directory to use for overflow and spooling to disk. If no spool directory has been explicit configured, then a temporary directory is created in the java.io.tmpdir directory." }, + "spoolCipher": { "index": 5, "kind": "attribute", "displayName": "Spool Cipher", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Sets a cipher name to use when spooling to disk to write with encryption. By default the data is not encrypted." }, + "spoolThreshold": { "index": 6, "kind": "attribute", "displayName": "Spool Threshold", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "defaultValue": "131072", "description": "Threshold in bytes when overflow to disk is activated. The default threshold is org.apache.camel.StreamCache#DEFAULT_SPOOL_THRESHOLD bytes (eg 128kb). Use -1 to disable overflow to disk." }, + "spoolUsedHeapMemoryThreshold": { "index": 7, "kind": "attribute", "displayName": "Spool Used Heap Memory Threshold", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Sets a percentage (1-99) of used heap memory threshold to activate spooling to disk." }, + "spoolUsedHeapMemoryLimit": { "index": 8, "kind": "attribute", "displayName": "Spool Used Heap Memory Limit", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Sets what the upper bounds should be when spoolUsedHeapMemoryThreshold is in use." }, + "spoolRules": { "index": 9, "kind": "attribute", "displayName": "Spool Rules", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Reference to one or more custom org.apache.camel.spi.StreamCachingStrategy.SpoolRule to use. Multiple rules can be separated by comma." }, + "bufferSize": { "index": 10, "kind": "attribute", "displayName": "Buffer Size", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "defaultValue": "4096", "description": "Sets the buffer size to use when allocating in-memory buffers used for in-memory stream caches. The default size is org.apache.camel.util.IOHelper#DEFAULT_BUFFER_SIZE" }, + "removeSpoolDirectoryWhenStopping": { "index": 11, "kind": "attribute", "displayName": "Remove Spool Directory When Stopping", "required": false, "type": "boolean", "javaType": "java.lang.Boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": true, "description": "Whether to remove the temporary directory when stopping. This option is default true" }, + "statisticsEnabled": { "index": 12, "kind": "attribute", "displayName": "Statistics Enabled", "required": false, "type": "boolean", "javaType": "java.lang.Boolean", "deprecated": false, "autowired": false, "secret": false, "defaultValue": false, "description": "Sets whether statistics is enabled." }, + "anySpoolRules": { "index": 13, "kind": "attribute", "displayName": "Any Spool Rules", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "defaultValue": "false", "description": "Sets whether if just any of the org.apache.camel.spi.StreamCachingStrategy.SpoolRule rules returns true then shouldSpoolCache(long) returns true. If this option is false, then all the org.apache.camel.spi.StreamCachingStrategy.SpoolR [...] + "id": { "index": 14, "kind": "attribute", "displayName": "Id", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "The id of this node" } } } diff --git a/core/camel-core-xml/src/main/java/org/apache/camel/core/xml/AbstractCamelContextFactoryBean.java b/core/camel-core-xml/src/main/java/org/apache/camel/core/xml/AbstractCamelContextFactoryBean.java index fb2662db6b5..16efac70f54 100644 --- a/core/camel-core-xml/src/main/java/org/apache/camel/core/xml/AbstractCamelContextFactoryBean.java +++ b/core/camel-core-xml/src/main/java/org/apache/camel/core/xml/AbstractCamelContextFactoryBean.java @@ -765,6 +765,14 @@ public abstract class AbstractCamelContextFactoryBean<T extends ModelCamelContex // stream-caching is default enabled getContext().getStreamCachingStrategy().setEnabled(true); } + String allowClasses = CamelContextHelper.parseText(getContext(), streamCaching.getAllowClasses()); + if (allowClasses != null) { + getContext().getStreamCachingStrategy().setAllowClasses(allowClasses); + } + String denyClasses = CamelContextHelper.parseText(getContext(), streamCaching.getDenyClasses()); + if (denyClasses != null) { + getContext().getStreamCachingStrategy().setDenyClasses(denyClasses); + } Boolean spoolEnabled = CamelContextHelper.parseBoolean(getContext(), streamCaching.getSpoolEnabled()); if (spoolEnabled != null) { getContext().getStreamCachingStrategy().setSpoolEnabled(spoolEnabled); diff --git a/core/camel-core-xml/src/main/java/org/apache/camel/core/xml/CamelStreamCachingStrategyDefinition.java b/core/camel-core-xml/src/main/java/org/apache/camel/core/xml/CamelStreamCachingStrategyDefinition.java index 8a6f785a30e..632777569cc 100644 --- a/core/camel-core-xml/src/main/java/org/apache/camel/core/xml/CamelStreamCachingStrategyDefinition.java +++ b/core/camel-core-xml/src/main/java/org/apache/camel/core/xml/CamelStreamCachingStrategyDefinition.java @@ -41,6 +41,10 @@ public class CamelStreamCachingStrategyDefinition extends IdentifiedType { @Metadata(defaultValue = "false", javaType = "java.lang.Boolean") private String spoolEnabled; @XmlAttribute + private String allowClasses; + @XmlAttribute + private String denyClasses; + @XmlAttribute private String spoolDirectory; @XmlAttribute private String spoolCipher; @@ -89,6 +93,30 @@ public class CamelStreamCachingStrategyDefinition extends IdentifiedType { this.enabled = enabled; } + public String getAllowClasses() { + return allowClasses; + } + + /** + * To filter stream caching of a given set of allowed/denied classes. By default, all classes that are + * {@link java.io.InputStream} is allowed. Multiple class names can be separated by comma. + */ + public void setAllowClasses(String allowClasses) { + this.allowClasses = allowClasses; + } + + public String getDenyClasses() { + return denyClasses; + } + + /** + * To filter stream caching of a given set of allowed/denied classes. By default, all classes that are + * {@link java.io.InputStream} is allowed. Multiple class names can be separated by comma. + */ + public void setDenyClasses(String denyClasses) { + this.denyClasses = denyClasses; + } + public String getSpoolEnabled() { return spoolEnabled; } diff --git a/core/camel-core/src/test/java/org/apache/camel/processor/StreamCachingAllowDenyTest.java b/core/camel-core/src/test/java/org/apache/camel/processor/StreamCachingAllowDenyTest.java new file mode 100644 index 00000000000..48b9b7a5f39 --- /dev/null +++ b/core/camel-core/src/test/java/org/apache/camel/processor/StreamCachingAllowDenyTest.java @@ -0,0 +1,161 @@ +/* + * 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.processor; + +import java.io.ByteArrayInputStream; +import java.io.Reader; +import java.io.StringReader; + +import org.apache.camel.ContextTestSupport; +import org.apache.camel.StreamCache; +import org.apache.camel.builder.RouteBuilder; +import org.apache.camel.component.mock.MockEndpoint; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; + +public class StreamCachingAllowDenyTest extends ContextTestSupport { + + @Override + public boolean isUseRouteBuilder() { + return false; + } + + @Test + public void testAllow() throws Exception { + context.addRoutes(new RouteBuilder() { + @Override + public void configure() throws Exception { + context.getStreamCachingStrategy().setAllowClasses(ByteArrayInputStream.class); + from("direct:a").to("mock:a"); + } + }); + context.start(); + + MockEndpoint a = getMockEndpoint("mock:a"); + a.expectedMessageCount(1); + template.sendBody("direct:a", new ByteArrayInputStream("Hello World".getBytes())); + assertMockEndpointsSatisfied(); + // should be converted + assertTrue(a.getReceivedExchanges().get(0).getMessage().getBody() instanceof StreamCache); + + assertEquals("Hello World", a.assertExchangeReceived(0).getIn().getBody(String.class)); + + // reset + a.reset(); + a.expectedMessageCount(1); + template.sendBody("direct:a", new StringReader("Bye World")); + assertMockEndpointsSatisfied(); + // should not be converted + assertFalse(a.getReceivedExchanges().get(0).getMessage().getBody() instanceof StreamCache); + assertEquals("Bye World", a.assertExchangeReceived(0).getIn().getBody(String.class)); + } + + @Test + public void testDeny() throws Exception { + context.addRoutes(new RouteBuilder() { + @Override + public void configure() throws Exception { + context.getStreamCachingStrategy().setDenyClasses(ByteArrayInputStream.class); + from("direct:a").to("mock:a"); + } + }); + context.start(); + + MockEndpoint a = getMockEndpoint("mock:a"); + a.expectedMessageCount(1); + template.sendBody("direct:a", new ByteArrayInputStream("Hello World".getBytes())); + assertMockEndpointsSatisfied(); + // should NOT be converted + assertFalse(a.getReceivedExchanges().get(0).getMessage().getBody() instanceof StreamCache); + + assertEquals("Hello World", a.assertExchangeReceived(0).getIn().getBody(String.class)); + + // reset + a.reset(); + a.expectedMessageCount(1); + template.sendBody("direct:a", new StringReader("Bye World")); + assertMockEndpointsSatisfied(); + // should be converted + assertTrue(a.getReceivedExchanges().get(0).getMessage().getBody() instanceof StreamCache); + assertEquals("Bye World", a.assertExchangeReceived(0).getIn().getBody(String.class)); + } + + @Test + public void testAllowAndDeny() throws Exception { + context.addRoutes(new RouteBuilder() { + @Override + public void configure() throws Exception { + context.getStreamCachingStrategy().setAllowClasses(ByteArrayInputStream.class); + context.getStreamCachingStrategy().setDenyClasses(Reader.class); + from("direct:a").to("mock:a"); + } + }); + context.start(); + + MockEndpoint a = getMockEndpoint("mock:a"); + a.expectedMessageCount(1); + template.sendBody("direct:a", new ByteArrayInputStream("Hello World".getBytes())); + assertMockEndpointsSatisfied(); + // should be converted + assertTrue(a.getReceivedExchanges().get(0).getMessage().getBody() instanceof StreamCache); + + assertEquals("Hello World", a.assertExchangeReceived(0).getIn().getBody(String.class)); + + // reset + a.reset(); + a.expectedMessageCount(1); + template.sendBody("direct:a", new StringReader("Bye World")); + assertMockEndpointsSatisfied(); + // should not be converted + assertFalse(a.getReceivedExchanges().get(0).getMessage().getBody() instanceof StreamCache); + assertEquals("Bye World", a.assertExchangeReceived(0).getIn().getBody(String.class)); + } + + @Test + public void testDualDeny() throws Exception { + context.addRoutes(new RouteBuilder() { + @Override + public void configure() throws Exception { + context.getStreamCachingStrategy().setDenyClasses(ByteArrayInputStream.class, Reader.class); + from("direct:a").to("mock:a"); + } + }); + context.start(); + + MockEndpoint a = getMockEndpoint("mock:a"); + a.expectedMessageCount(1); + template.sendBody("direct:a", new ByteArrayInputStream("Hello World".getBytes())); + assertMockEndpointsSatisfied(); + // should NOT be converted + assertFalse(a.getReceivedExchanges().get(0).getMessage().getBody() instanceof StreamCache); + + assertEquals("Hello World", a.assertExchangeReceived(0).getIn().getBody(String.class)); + + // reset + a.reset(); + a.expectedMessageCount(1); + template.sendBody("direct:a", new StringReader("Bye World")); + assertMockEndpointsSatisfied(); + // should not be converted + assertFalse(a.getReceivedExchanges().get(0).getMessage().getBody() instanceof StreamCache); + assertEquals("Bye World", a.assertExchangeReceived(0).getIn().getBody(String.class)); + } + +} diff --git a/core/camel-main/src/generated/java/org/apache/camel/main/MainConfigurationPropertiesConfigurer.java b/core/camel-main/src/generated/java/org/apache/camel/main/MainConfigurationPropertiesConfigurer.java index d9d958ccc81..a135eac6123 100644 --- a/core/camel-main/src/generated/java/org/apache/camel/main/MainConfigurationPropertiesConfigurer.java +++ b/core/camel-main/src/generated/java/org/apache/camel/main/MainConfigurationPropertiesConfigurer.java @@ -213,10 +213,14 @@ public class MainConfigurationPropertiesConfigurer extends org.apache.camel.supp case "StartupRecorderRecording": target.setStartupRecorderRecording(property(camelContext, boolean.class, value)); return true; case "startupsummarylevel": case "StartupSummaryLevel": target.setStartupSummaryLevel(property(camelContext, org.apache.camel.StartupSummaryLevel.class, value)); return true; + case "streamcachingallowclasses": + case "StreamCachingAllowClasses": target.setStreamCachingAllowClasses(property(camelContext, java.lang.String.class, value)); return true; case "streamcachinganyspoolrules": case "StreamCachingAnySpoolRules": target.setStreamCachingAnySpoolRules(property(camelContext, boolean.class, value)); return true; case "streamcachingbuffersize": case "StreamCachingBufferSize": target.setStreamCachingBufferSize(property(camelContext, int.class, value)); return true; + case "streamcachingdenyclasses": + case "StreamCachingDenyClasses": target.setStreamCachingDenyClasses(property(camelContext, java.lang.String.class, value)); return true; case "streamcachingenabled": case "StreamCachingEnabled": target.setStreamCachingEnabled(property(camelContext, boolean.class, value)); return true; case "streamcachingremovespooldirectorywhenstopping": @@ -456,10 +460,14 @@ public class MainConfigurationPropertiesConfigurer extends org.apache.camel.supp case "StartupRecorderRecording": return boolean.class; case "startupsummarylevel": case "StartupSummaryLevel": return org.apache.camel.StartupSummaryLevel.class; + case "streamcachingallowclasses": + case "StreamCachingAllowClasses": return java.lang.String.class; case "streamcachinganyspoolrules": case "StreamCachingAnySpoolRules": return boolean.class; case "streamcachingbuffersize": case "StreamCachingBufferSize": return int.class; + case "streamcachingdenyclasses": + case "StreamCachingDenyClasses": return java.lang.String.class; case "streamcachingenabled": case "StreamCachingEnabled": return boolean.class; case "streamcachingremovespooldirectorywhenstopping": @@ -700,10 +708,14 @@ public class MainConfigurationPropertiesConfigurer extends org.apache.camel.supp case "StartupRecorderRecording": return target.isStartupRecorderRecording(); case "startupsummarylevel": case "StartupSummaryLevel": return target.getStartupSummaryLevel(); + case "streamcachingallowclasses": + case "StreamCachingAllowClasses": return target.getStreamCachingAllowClasses(); case "streamcachinganyspoolrules": case "StreamCachingAnySpoolRules": return target.isStreamCachingAnySpoolRules(); case "streamcachingbuffersize": case "StreamCachingBufferSize": return target.getStreamCachingBufferSize(); + case "streamcachingdenyclasses": + case "StreamCachingDenyClasses": return target.getStreamCachingDenyClasses(); case "streamcachingenabled": case "StreamCachingEnabled": return target.isStreamCachingEnabled(); case "streamcachingremovespooldirectorywhenstopping": diff --git a/core/camel-main/src/generated/resources/META-INF/camel-main-configuration-metadata.json b/core/camel-main/src/generated/resources/META-INF/camel-main-configuration-metadata.json index 2d16d3f2fc2..6b495e49656 100644 --- a/core/camel-main/src/generated/resources/META-INF/camel-main-configuration-metadata.json +++ b/core/camel-main/src/generated/resources/META-INF/camel-main-configuration-metadata.json @@ -109,8 +109,10 @@ { "name": "camel.main.startupRecorderProfile", "description": "To use a specific Java Flight Recorder profile configuration, such as default or profile. The default is default.", "sourceType": "org.apache.camel.main.DefaultConfigurationProperties", "type": "string", "javaType": "java.lang.String", "defaultValue": "default" }, { "name": "camel.main.startupRecorderRecording", "description": "To enable Java Flight Recorder to start a recording and automatic dump the recording to disk after startup is complete. This requires that camel-jfr is on the classpath, and to enable this option.", "sourceType": "org.apache.camel.main.DefaultConfigurationProperties", "type": "boolean", "javaType": "boolean", "defaultValue": "false" }, { "name": "camel.main.startupSummaryLevel", "description": "Controls the level of information logged during startup (and shutdown) of CamelContext.", "sourceType": "org.apache.camel.main.DefaultConfigurationProperties", "type": "object", "javaType": "org.apache.camel.StartupSummaryLevel", "defaultValue": "Default" }, + { "name": "camel.main.streamCachingAllowClasses", "description": "To filter stream caching of a given set of allowed\/denied classes. By default, all classes that are java.io.InputStream is allowed. Multiple class names can be separated by comma.", "sourceType": "org.apache.camel.main.DefaultConfigurationProperties", "type": "string", "javaType": "java.lang.String" }, { "name": "camel.main.streamCachingAnySpoolRules", "description": "Sets whether if just any of the org.apache.camel.spi.StreamCachingStrategy.SpoolRule rules returns true then shouldSpoolCache(long) returns true, to allow spooling to disk. If this option is false, then all the org.apache.camel.spi.StreamCachingStrategy.SpoolRule must return true. The default value is false which means that all the rules must return true.", "sourceType": "org.apache.camel.main.DefaultConfigurationProp [...] { "name": "camel.main.streamCachingBufferSize", "description": "Sets the stream caching buffer size to use when allocating in-memory buffers used for in-memory stream caches. The default size is 4096.", "sourceType": "org.apache.camel.main.DefaultConfigurationProperties", "type": "integer", "javaType": "int" }, + { "name": "camel.main.streamCachingDenyClasses", "description": "To filter stream caching of a given set of allowed\/denied classes. By default, all classes that are java.io.InputStream is allowed. Multiple class names can be separated by comma.", "sourceType": "org.apache.camel.main.DefaultConfigurationProperties", "type": "string", "javaType": "java.lang.String" }, { "name": "camel.main.streamCachingEnabled", "description": "Sets whether stream caching is enabled or not. While stream types (like StreamSource, InputStream and Reader) are commonly used in messaging for performance reasons, they also have an important drawback: they can only be read once. In order to be able to work with message content multiple times, the stream needs to be cached. Streams are cached in memory only (by default). If streamCachingSpoolEnabled=true, then, for large [...] { "name": "camel.main.streamCachingRemoveSpoolDirectoryWhenStopping", "description": "Whether to remove stream caching temporary directory when stopping. This option is default true.", "sourceType": "org.apache.camel.main.DefaultConfigurationProperties", "type": "boolean", "javaType": "boolean", "defaultValue": true }, { "name": "camel.main.streamCachingSpoolCipher", "description": "Sets a stream caching cipher name to use when spooling to disk to write with encryption. By default the data is not encrypted.", "sourceType": "org.apache.camel.main.DefaultConfigurationProperties", "type": "string", "javaType": "java.lang.String" }, diff --git a/core/camel-main/src/main/docs/main.adoc b/core/camel-main/src/main/docs/main.adoc index b499f201672..04b2390e786 100644 --- a/core/camel-main/src/main/docs/main.adoc +++ b/core/camel-main/src/main/docs/main.adoc @@ -19,7 +19,7 @@ The following tables lists all the options: // main options: START === Camel Main configurations -The camel.main supports 118 options, which are listed below. +The camel.main supports 120 options, which are listed below. [width="100%",cols="2,5,^1,2",options="header"] |=== @@ -120,8 +120,10 @@ The camel.main supports 118 options, which are listed below. | *camel.main.startupRecorder{zwsp}Profile* | To use a specific Java Flight Recorder profile configuration, such as default or profile. The default is default. | default | String | *camel.main.startupRecorder{zwsp}Recording* | To enable Java Flight Recorder to start a recording and automatic dump the recording to disk after startup is complete. This requires that camel-jfr is on the classpath, and to enable this option. | false | boolean | *camel.main.startupSummaryLevel* | Controls the level of information logged during startup (and shutdown) of CamelContext. | Default | StartupSummaryLevel +| *camel.main.streamCachingAllow{zwsp}Classes* | To filter stream caching of a given set of allowed/denied classes. By default, all classes that are java.io.InputStream is allowed. Multiple class names can be separated by comma. | | String | *camel.main.streamCachingAny{zwsp}SpoolRules* | Sets whether if just any of the org.apache.camel.spi.StreamCachingStrategy.SpoolRule rules returns true then shouldSpoolCache(long) returns true, to allow spooling to disk. If this option is false, then all the org.apache.camel.spi.StreamCachingStrategy.SpoolRule must return true. The default value is false which means that all the rules must return true. | false | boolean | *camel.main.streamCachingBuffer{zwsp}Size* | Sets the stream caching buffer size to use when allocating in-memory buffers used for in-memory stream caches. The default size is 4096. | | int +| *camel.main.streamCachingDeny{zwsp}Classes* | To filter stream caching of a given set of allowed/denied classes. By default, all classes that are java.io.InputStream is allowed. Multiple class names can be separated by comma. | | String | *camel.main.streamCaching{zwsp}Enabled* | Sets whether stream caching is enabled or not. While stream types (like StreamSource, InputStream and Reader) are commonly used in messaging for performance reasons, they also have an important drawback: they can only be read once. In order to be able to work with message content multiple times, the stream needs to be cached. Streams are cached in memory only (by default). If streamCachingSpoolEnabled=true, then, for large stream messages (over [...] | *camel.main.streamCachingRemove{zwsp}SpoolDirectoryWhenStopping* | Whether to remove stream caching temporary directory when stopping. This option is default true. | true | boolean | *camel.main.streamCachingSpool{zwsp}Cipher* | Sets a stream caching cipher name to use when spooling to disk to write with encryption. By default the data is not encrypted. | | String diff --git a/core/camel-main/src/main/java/org/apache/camel/main/DefaultConfigurationConfigurer.java b/core/camel-main/src/main/java/org/apache/camel/main/DefaultConfigurationConfigurer.java index 772a0d3fa42..753971d76c8 100644 --- a/core/camel-main/src/main/java/org/apache/camel/main/DefaultConfigurationConfigurer.java +++ b/core/camel-main/src/main/java/org/apache/camel/main/DefaultConfigurationConfigurer.java @@ -187,6 +187,8 @@ public final class DefaultConfigurationConfigurer { // stream caching camelContext.setStreamCaching(config.isStreamCachingEnabled()); + camelContext.getStreamCachingStrategy().setAllowClasses(config.getStreamCachingAllowClasses()); + camelContext.getStreamCachingStrategy().setDenyClasses(config.getStreamCachingDenyClasses()); camelContext.getStreamCachingStrategy().setSpoolEnabled(config.isStreamCachingSpoolEnabled()); camelContext.getStreamCachingStrategy().setAnySpoolRules(config.isStreamCachingAnySpoolRules()); camelContext.getStreamCachingStrategy().setBufferSize(config.getStreamCachingBufferSize()); diff --git a/core/camel-main/src/main/java/org/apache/camel/main/DefaultConfigurationProperties.java b/core/camel-main/src/main/java/org/apache/camel/main/DefaultConfigurationProperties.java index b664348f418..ee44283e346 100644 --- a/core/camel-main/src/main/java/org/apache/camel/main/DefaultConfigurationProperties.java +++ b/core/camel-main/src/main/java/org/apache/camel/main/DefaultConfigurationProperties.java @@ -59,6 +59,8 @@ public abstract class DefaultConfigurationProperties<T> { private boolean modeline; private int logDebugMaxChars; private boolean streamCachingEnabled = true; + private String streamCachingAllowClasses; + private String streamCachingDenyClasses; private boolean streamCachingSpoolEnabled; private String streamCachingSpoolDirectory; private String streamCachingSpoolCipher; @@ -461,6 +463,30 @@ public abstract class DefaultConfigurationProperties<T> { this.streamCachingEnabled = streamCachingEnabled; } + public String getStreamCachingAllowClasses() { + return streamCachingAllowClasses; + } + + /** + * To filter stream caching of a given set of allowed/denied classes. By default, all classes that are + * {@link java.io.InputStream} is allowed. Multiple class names can be separated by comma. + */ + public void setStreamCachingAllowClasses(String streamCachingAllowClasses) { + this.streamCachingAllowClasses = streamCachingAllowClasses; + } + + public String getStreamCachingDenyClasses() { + return streamCachingDenyClasses; + } + + /** + * To filter stream caching of a given set of allowed/denied classes. By default, all classes that are + * {@link java.io.InputStream} is allowed. Multiple class names can be separated by comma. + */ + public void setStreamCachingDenyClasses(String streamCachingDenyClasses) { + this.streamCachingDenyClasses = streamCachingDenyClasses; + } + public boolean isStreamCachingSpoolEnabled() { return streamCachingSpoolEnabled; } @@ -1838,6 +1864,24 @@ public abstract class DefaultConfigurationProperties<T> { return (T) this; } + /** + * To filter stream caching of a given set of allowed/denied classes. By default, all classes that are + * {@link java.io.InputStream} is allowed. Multiple class names can be separated by comma. + */ + public T withStreamCachingAllowClasses(String streamCachingAllowClasses) { + this.streamCachingAllowClasses = streamCachingAllowClasses; + return (T) this; + } + + /** + * To filter stream caching of a given set of allowed/denied classes. By default, all classes that are + * {@link java.io.InputStream} is allowed. Multiple class names can be separated by comma. + */ + public T withStreamCachingDenyClasses(String streamCachingDenyClasses) { + this.streamCachingDenyClasses = streamCachingDenyClasses; + return (T) this; + } + /** * To enable stream caching spooling to disk. This means, for large stream messages (over 128 KB by default) will be * cached in a temporary file instead, and Camel will handle deleting the temporary file once the cached stream is diff --git a/core/camel-management-api/src/main/java/org/apache/camel/api/management/mbean/ManagedStreamCachingStrategyMBean.java b/core/camel-management-api/src/main/java/org/apache/camel/api/management/mbean/ManagedStreamCachingStrategyMBean.java index c420d1eb357..ff16b2da1c5 100644 --- a/core/camel-management-api/src/main/java/org/apache/camel/api/management/mbean/ManagedStreamCachingStrategyMBean.java +++ b/core/camel-management-api/src/main/java/org/apache/camel/api/management/mbean/ManagedStreamCachingStrategyMBean.java @@ -32,6 +32,12 @@ public interface ManagedStreamCachingStrategyMBean extends ManagedServiceMBean { @ManagedAttribute(description = "Whether stream caching is enabled") boolean isEnabled(); + @ManagedAttribute(description = "To filter stream caching of a given set of allowed/denied classes.") + String[] getAllowClasses(); + + @ManagedAttribute(description = "To filter stream caching of a given set of allowed/denied classes.") + String[] getDenyClasses(); + @ManagedAttribute(description = "Whether spooling to disk enabled") boolean isSpoolEnabled(); diff --git a/core/camel-management/src/main/java/org/apache/camel/management/mbean/ManagedStreamCachingStrategy.java b/core/camel-management/src/main/java/org/apache/camel/management/mbean/ManagedStreamCachingStrategy.java index 7249fa4653e..74dc57d2e05 100644 --- a/core/camel-management/src/main/java/org/apache/camel/management/mbean/ManagedStreamCachingStrategy.java +++ b/core/camel-management/src/main/java/org/apache/camel/management/mbean/ManagedStreamCachingStrategy.java @@ -26,11 +26,23 @@ public class ManagedStreamCachingStrategy extends ManagedService implements Mana private final CamelContext camelContext; private final StreamCachingStrategy streamCachingStrategy; + private final String[] allowClasses; + private final String[] denyClasses; public ManagedStreamCachingStrategy(CamelContext camelContext, StreamCachingStrategy streamCachingStrategy) { super(camelContext, streamCachingStrategy); this.camelContext = camelContext; this.streamCachingStrategy = streamCachingStrategy; + if (streamCachingStrategy.getAllowClasses() != null) { + this.allowClasses = streamCachingStrategy.getAllowClasses().toArray(new String[0]); + } else { + this.allowClasses = null; + } + if (streamCachingStrategy.getDenyClasses() != null) { + this.denyClasses = streamCachingStrategy.getDenyClasses().toArray(new String[0]); + } else { + this.denyClasses = null; + } } public CamelContext getCamelContext() { @@ -46,6 +58,16 @@ public class ManagedStreamCachingStrategy extends ManagedService implements Mana return streamCachingStrategy.isEnabled(); } + @Override + public String[] getAllowClasses() { + return allowClasses; + } + + @Override + public String[] getDenyClasses() { + return denyClasses; + } + @Override public boolean isSpoolEnabled() { return streamCachingStrategy.isSpoolEnabled();